diff --git a/lib_com/hq_tools_fx.c b/lib_com/hq_tools_fx.c index 7077f9924ac15eb069ba93df2b2914c63dda3f74..f83d20ccdcf983ef13640c7c5453a4f4fb63304c 100644 --- a/lib_com/hq_tools_fx.c +++ b/lib_com/hq_tools_fx.c @@ -39,6 +39,7 @@ #include "rom_com.h" /* Static table prototypes FIP version */ #include "stl.h" /* required for wmc_tool */ #include "prot_fx.h" +#include "prot.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #endif @@ -1920,6 +1921,104 @@ Word16 get_nor_delta_hf_fx( } return add_bits_denv; } +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * calc_nor_delta_hf() + * + * + *--------------------------------------------------------------------------*/ +Word16 calc_nor_delta_hf_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word32 *t_audio, /* i : transform-domain coefficients Qx*/ + Word16 *ynrm, /* i/o: norm indices */ + Word16 *Rsubband, /* i/o: sub-band bit allocation */ + const Word16 num_env_bands, /* i : Number coded envelope bands */ + const Word16 nb_sfm, /* i : Number of envelope bands */ + const Word16 *sfmsize, /* i : band length */ + const Word16 *sfm_start, /* i : Start index of bands */ + const Word16 core_sfm /* i : index of the end band for core */ +) +{ + Word16 i; + Word16 ynrm_t[44], normqlg2_t[44]; + Word16 delta, max_delta, min_delta, bitsforDelta, add_bits_denv; + + max_delta = -100; + move16(); + calc_norm_fx( t_audio, 12, ynrm_t, normqlg2_t, 0, nb_sfm, sfmsize, sfm_start ); + add_bits_denv = 0; + move16(); + FOR( i = num_env_bands; i < nb_sfm; ++i ) + { + IF( Rsubband[i] != 0 ) + { + delta = sub( ynrm_t[i], ynrm[i] ); + IF( delta > 0 ) + { + delta = add( delta, 1 ); + } + ELSE + { + delta = negate( delta ); + } + if ( GT_16( delta, max_delta ) ) + { + max_delta = delta; + move16(); + } + } + } + IF( GE_16( core_sfm, num_env_bands ) ) + { + IF( LT_16( max_delta, 16 ) ) + { + bitsforDelta = 2; + move16(); + FOR( ; max_delta >= 2; max_delta >>= 1 ) + { + bitsforDelta = add( bitsforDelta, 1 ); + } + } + ELSE + { + bitsforDelta = 5; + move16(); + } + max_delta = sub( shl( 1, sub( bitsforDelta, 1 ) ), 1 ); + min_delta = negate( add( max_delta, 1 ) ); + + /* updating norm & storing delta norm */ + add_bits_denv = 2; + move16(); + push_indice( hBstr, IND_DELTA_ENV_HQ, sub( bitsforDelta, 2 ), 2 ); + FOR( i = num_env_bands; i < nb_sfm; ++i ) + { + IF( Rsubband[i] != 0 ) + { + delta = sub( ynrm_t[i], ynrm[i] ); + IF( GT_16( delta, max_delta ) ) + { + delta = max_delta; + move16(); + } + ELSE IF( LT_16( delta, min_delta ) ) + { + delta = min_delta; + move16(); + } + push_indice( hBstr, IND_DELTA_ENV_HQ, delta - min_delta, bitsforDelta ); + ynrm[i] = add( ynrm[i], delta ); + move16(); + add_bits_denv = add( add_bits_denv, bitsforDelta ); + } + } + + /* updating bit allocation */ + update_rsubband_fx( nb_sfm, Rsubband, add_bits_denv ); + } + return add_bits_denv; +} +#endif /*-------------------------------------------------------------------* * calc_nor_delta_hf() * @@ -2557,7 +2656,47 @@ void enforce_zero_for_min_envelope_fx( return; } +#ifdef IVAS_FLOAT_FIXED +/*--------------------------------------------------------------------------* + * apply_envelope() + * + * Apply spectral envelope with envelope adjustments + *--------------------------------------------------------------------------*/ +void apply_envelope_enc_ivas_fx( + const Word16 *coeff, /* i/o: Coded/noisefilled normalized spectrum Q12 */ + const Word16 *norm, /* i : Envelope Q0 */ + const Word16 num_sfm, /* i : Total number of bands Q0 */ + const Word16 *sfm_start, /* i : Sub band start indices Q0 */ + const Word16 *sfm_end, /* i : Sub band end indices Q0 */ + Word32 *coeff_out /* o : coded/noisefilled spectrum Q12 */ +) +{ + Word16 i; + Word16 sfm; + UWord16 lsb; + Word32 normq; + Word32 L_tmp; + + FOR( sfm = 0; sfm < num_sfm; sfm++ ) + { + normq = dicn_fx[norm[sfm]]; + move16(); + + FOR( i = sfm_start[sfm]; i < sfm_end[sfm]; i++ ) + { + /*coeff_out[i] = coeff[i]*normq; */ + Mpy_32_16_ss( normq, coeff[i], &L_tmp, &lsb ); + coeff_out[i] = L_add( L_shl( L_tmp, 1 ), L_shr( lsb, 15 ) ); + move32(); /* Q12 (14+12+1-16)+1 */ + } + } + + + return; +} + +#endif /*--------------------------------------------------------------------------* * apply_envelope() * diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 4aa1dcbc6ea64a9cea302856d103c7a20c06ab7a..b775d8ccf134cf6a08f64b4ff5f775aaa77f22f3 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -1372,12 +1372,18 @@ void computeDiffuseness_fixed( min_q_shift2 = Q31; move16(); - min_q_shift2 = s_min( min_q_shift2, getScaleFactor32( buffer_energy, i_mult( DIRAC_NUM_DIMS, i_mult( DIRAC_NO_COL_AVG_DIFF, num_freq_bands ) ) ) ); - min_q_shift2 = find_guarded_bits_fx( DIRAC_NO_COL_AVG_DIFF ); + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + min_q_shift2 = s_min( min_q_shift2, getScaleFactor32( buffer_intensity[i][j], num_freq_bands ) ); + } + } + min_q_shift2 = sub( min_q_shift2, find_guarded_bits_fx( DIRAC_NO_COL_AVG_DIFF ) ); q_ene = add( q_factor_energy[0], min_q_shift1 ); move16(); - q_intensity = sub( q_factor_intensity[0], min_q_shift2 ); + q_intensity = add( q_factor_intensity[0], min_q_shift2 ); move16(); FOR( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i ) @@ -1403,13 +1409,13 @@ void computeDiffuseness_fixed( q_ene = s_min( q_ene, q_tmp ); /* Intensity slow */ - q_tmp = sub( q_factor_intensity[i], min_q_shift2 ); + q_tmp = add( q_factor_intensity[i], min_q_shift2 ); FOR( j = 0; j < DIRAC_NUM_DIMS; ++j ) { p_tmp = buffer_intensity[j][i]; FOR( k = 0; k < num_freq_bands; k++ ) { - tmp = L_shr( p_tmp[k], min_q_shift2 ); + tmp = L_shl( p_tmp[k], min_q_shift2 ); IF( LT_16( q_intensity, q_tmp ) ) { intensity_slow[add( i_mult( j, num_freq_bands ), k )] = L_add( intensity_slow[add( i_mult( j, num_freq_bands ), k )], L_shr( tmp, sub( q_tmp, q_intensity ) ) ); diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 90b5695016c57797d1b98310942b790e4ee3f2f0..c753e4d039440095b676440f543d00f7e0155b28 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -80,15 +80,29 @@ void copy_encoder_config( const int16_t flag_all /* i : flag 1==update all, 0=partial update */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_write_format( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); +#else +void ivas_write_format_fx( /* i/o: IVAS encoder structure */ + Encoder_Struct *st_ivas +); +#endif +#ifndef IVAS_FLOAT_FIXED void ivas_write_format_sid( const IVAS_FORMAT ivas_format, /* i : IVAS format */ const int16_t element_mode, /* i : element bitrate */ BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ ); +#else +void ivas_write_format_sid_fx( + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const Word16 element_mode, /* i : element bitrate */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ +); +#endif ivas_error create_sce_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ diff --git a/lib_com/logqnorm_fx.c b/lib_com/logqnorm_fx.c index d47feb209e6c55d44875beebbac0f429cb21fe07..4505c749d1a6b4016edb201c6e8e55e283e82150 100644 --- a/lib_com/logqnorm_fx.c +++ b/lib_com/logqnorm_fx.c @@ -294,8 +294,6 @@ void calc_norm_ivas_fx( Word16 tmp; set16_fx( norm, 0, start_band ); - - // logqnorm_ivas_fx( &x_fx[band_start[start_band]], 12, &x[band_start[start_band]], &nrm, 32, band_len[start_band], thren_HQ ); logqnorm_ivas_fx( &x_fx[band_start[start_band]], 12, &nrm, 32, band_len[start_band], thren_HQ_fx ); norm[start_band] = nrm; move16(); diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 0e05b8ced15fe7baed3554ac09e64459f23eaffb..0dedd638c574381de1d08225e71164d361467612 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -675,7 +675,19 @@ Word16 calc_nor_delta_hf_fx( const Word16 *sfm_start, /* i : Start index of bands */ const Word16 core_sfm /* i : index of the end band for core */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 calc_nor_delta_hf_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word32 *t_audio, /* i : transform-domain coefficients Qx*/ + Word16 *ynrm, /* i/o: norm indices */ + Word16 *Rsubband, /* i/o: sub-band bit allocation */ + const Word16 num_env_bands, /* i : Number coded envelope bands */ + const Word16 nb_sfm, /* i : Number of envelope bands */ + const Word16 *sfmsize, /* i : band length */ + const Word16 *sfm_start, /* i : Start index of bands */ + const Word16 core_sfm /* i : index of the end band for core */ +); +#endif void hq_bwe_fx( const Word16 HQ_mode, /* i : HQ mode */ Word32 *coeff_out1, /* i/o: BWE i & temporary buffer */ @@ -717,7 +729,14 @@ void enforce_zero_for_min_envelope_fx( const Word16 *sfm_start, /* i : Sub band start indices Q0 */ const Word16 *sfm_end /* i : Sub band end indices Q0 */ ); - +void apply_envelope_enc_ivas_fx( + const Word16 *coeff, /* i/o: Coded/noisefilled normalized spectrum Q12 */ + const Word16 *norm, /* i : Envelope Q0 */ + const Word16 num_sfm, /* i : Total number of bands Q0 */ + const Word16 *sfm_start, /* i : Sub band start indices Q0 */ + const Word16 *sfm_end, /* i : Sub band end indices Q0 */ + Word32 *coeff_out /* o : coded/noisefilled spectrum Q12 */ +); void apply_envelope_fx( const Word16 *coeff, /* i : Coded/noisefilled normalized spectrum Q12 */ const Word16 *norm, /* i : Envelope */ @@ -4660,7 +4679,16 @@ void fine_gain_quant_fx( Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ const Word16 *gopt /* i : Optimal gains Q12 */ ); - +#ifdef IVAS_FLOAT_FIXED +void fine_gain_quant_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ + const Word16 *gopt /* i : Optimal gains Q12 */ +); +#endif void get_max_pulses_fx( const Word16 *band_start, /* i : Sub band start indices */ const Word16 *band_end, /* i : Sub band end indices */ @@ -10531,4 +10559,10 @@ void writeTCXparam_fx( Word16 p_param[2], /* i/o: pointer to parameters from previous bs writing */ const Word16 target_bitsTCX10[2], const Word16 pre_past_flag ); + +void calculate_hangover_attenuation_gain_ivas_fx( + Encoder_State *st, /* i : encoder state structure */ + Word16 *att, /* o : attenuation factor */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); #endif diff --git a/lib_com/pvq_com_fx.c b/lib_com/pvq_com_fx.c index 16892d5e59fe54f5f1c4a23552483a32cce756a3..dc353b95c641e567b43f09b4296fe7fc9f3e1da8 100644 --- a/lib_com/pvq_com_fx.c +++ b/lib_com/pvq_com_fx.c @@ -4,6 +4,7 @@ #include #include "options.h" /* Compilation switches */ #include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "cnst.h" /* Common constants */ #include "rom_com.h" /* Static table prototypes */ @@ -509,7 +510,75 @@ void apply_gain_fx( * * Fine gain quantization *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void fine_gain_quant_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ + const Word16 *gopt /* i : Optimal gains Q12 */ +) +{ + Word16 band; + Word16 gbits; + Word16 idx; + Word16 gain_db, gain_dbq; + Word16 err; + Word16 tmp1, tmp2, exp1, exp2; + Word32 L_tmp; + UWord16 lsb; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + FOR( band = 0; band < num_sfm; band++ ) + { + gbits = gain_bits[ord[band]]; + move16(); + test(); + IF( fg_pred[band] != 0 && gbits > 0 ) + { + exp1 = norm_s( gopt[band] ); + exp1 = sub( exp1, 1 ); + tmp1 = shl( gopt[band], exp1 ); + exp2 = norm_s( fg_pred[band] ); + tmp2 = shl( fg_pred[band], exp2 ); + exp1 = add( 15, sub( exp1, exp2 ) ); + err = div_s( tmp1, tmp2 ); + tmp1 = norm_s( err ); + exp2 = Log2_norm_lc( L_deposit_h( shl( err, tmp1 ) ) ); + tmp1 = sub( 14, tmp1 ); + tmp1 = sub( tmp1, exp1 ); + L_tmp = L_Comp( tmp1, exp2 ); + Mpy_32_16_ss( L_tmp, 24660, &L_tmp, &lsb ); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */ +#ifdef BASOP_NOGLOB + gain_db = round_fx_sat( L_shl_o( L_tmp, 17, &Overflow ) ); +#else /* BASOP_NOGLOB */ + gain_db = round_fx( L_shl( L_tmp, 17 ) ); +#endif + + idx = squant_fx( gain_db, &gain_dbq, finegain_fx[gbits - 1], gain_cb_size[gbits - 1] ); + push_indice( hBstr, IND_PVQ_FINE_GAIN, idx, gbits ); + + L_tmp = L_mult0( gain_dbq, 21771 ); /* 21771=0.05*log2(10) */ /* 14+17=31 */ + L_tmp = L_shr( L_tmp, 15 ); + tmp1 = L_Extract_lc( L_tmp, &exp1 ); + tmp1 = abs_s( tmp1 ); + tmp1 = extract_l( Pow2( 14, tmp1 ) ); + exp1 = sub( 14, exp1 ); + + L_tmp = L_mult0( fg_pred[band], tmp1 ); /*12+exp1 */ + fg_pred[band] = round_fx( L_shl( L_tmp, sub( 16, exp1 ) ) ); /*12+exp1+16-exp1-16=12 */ + move16(); + } + } + + return; +} +#endif void fine_gain_quant_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 *ord, /* i : Indices for energy order */ diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index c4774c8cca457a019b9967b7c6ea07ed36dd4d24..3eb6bdf92c2f83894f6272a5be64c5fde271bfc1 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1090,7 +1090,9 @@ extern const int32_t manPkEnrg_tbl[45]; extern const int32_t E_max5_tbl[40]; extern const float thren_pg[44]; - +#ifdef IVAS_FLOAT_FIXED +extern const Word32 thren_pg_fx[44]; +#endif extern const float dicn[40]; extern const Word32 dicn_fx[40]; extern const float dicn_inv[40]; diff --git a/lib_enc/bw_detect_fx.c b/lib_enc/bw_detect_fx.c index 3cc6784de9b795e56998411f326094f11979fb4e..2d69854e5d28443861d599cb842ea2718c3fef91 100644 --- a/lib_enc/bw_detect_fx.c +++ b/lib_enc/bw_detect_fx.c @@ -925,14 +925,13 @@ void set_bw_fx( st->bwidth = st->input_bwidth; move16(); - total_brate_fx = L_add( st->total_brate, 0 ); - + total_brate_fx = st->total_brate; + move32(); /* change the encoded bandwidth, if not supported at particular bitrate */ test(); test(); test(); test(); - test(); IF( GT_16( element_mode, IVAS_SCE ) ) { // PMT("this IVAS_SCE section has not been verified ") @@ -949,12 +948,15 @@ void set_bw_fx( IF( GE_32( element_brate, MIN_BRATE_FB_STEREO ) ) { st->bwidth = s_min( st->bwidth, FB ); + move16(); } ELSE { st->bwidth = s_min( st->bwidth, SWB ); + move16(); } st->bwidth = s_max( st->bwidth, WB ); + move16(); } ELSE { @@ -965,6 +967,10 @@ void set_bw_fx( } ELSE IF( EQ_16( element_mode, IVAS_SCE ) ) { + test(); + test(); + test(); + test(); test(); IF( LT_32( element_brate, MIN_BRATE_SWB_SCE ) || LT_16( st->bwidth, WB ) ) { @@ -1016,16 +1022,19 @@ void set_bw_fx( BREAK; } } - if ( n == FRAME_SIZE_NB ) + if ( EQ_16( n, FRAME_SIZE_NB ) ) { assert( !"Bitrate not supported: not part of EVS" ); } tmpbandwidthMin = FrameSizeConfig[n].bandwidth_min; + move16(); if ( EQ_16( st->rf_mode, 1 ) ) { tmpbandwidthMin = WB; + move16(); } st->bwidth = s_max( s_min( st->input_bwidth, FrameSizeConfig[n].bandwidth_max ), tmpbandwidthMin ); + move16(); } } #ifdef IVAS_CODE_BWD diff --git a/lib_enc/cng_enc_fx.c b/lib_enc/cng_enc_fx.c index 496b65b3ab0525df99ecc01c6507e77c89ad92fd..c3f7e789339a6b93c9092545024ecde6c2c454e5 100644 --- a/lib_enc/cng_enc_fx.c +++ b/lib_enc/cng_enc_fx.c @@ -1607,3 +1607,60 @@ void calculate_hangover_attenuation_gain_fx( } return; } + +#ifdef IVAS_FLOAT_FIXED +void calculate_hangover_attenuation_gain_ivas_fx( + Encoder_State *st, /* i : encoder state structure */ + Word16 *att, /* o : attenuation factor */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word16 lim, result_e; + + *att = 32767; + move16(); + + test(); + test(); + test(); + test(); + IF( st->hTdCngEnc != NULL && ( vad_hover_flag != 0 ) && GT_16( st->hTdCngEnc->burst_ho_cnt, 0 ) && ( NE_16( st->bwidth, NB ) || GT_16( st->element_mode, EVS_MONO ) ) ) + { + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + Word32 exp = Mpy_32_16_1( L_mult( 26214 /*26214 = 1 / 160.f in Q22*/, st->hTdCngEnc->burst_ho_cnt ), st->hTdCngEnc->CNG_att_fx ); /* Q20 */ + + Word32 L_tmp = BASOP_Util_fPow( 1342177280 /* 10 in Q27 */, 4, exp, 11, &result_e ); + *att = extract_h( L_shl( L_tmp, result_e ) ); + move16(); + } + ELSE + { + test(); + IF( EQ_16( st->bwidth, WB ) && st->hDtxEnc->CNG_mode >= 0 ) + { + lim = HO_ATT_FX[st->hDtxEnc->CNG_mode]; + } + ELSE + { + lim = 19660; /* 0.6 in Q15*/ + } + move16(); + + *att = mult_r( lim, 5461 ); /* 1/6.f in Q15*/ + move16(); + *att = divide1616( 32767, add( 2048, imult1616( *att, st->hTdCngEnc->burst_ho_cnt ) ) ); /* 2048 = 1 in Q11*/ + move16(); + + if ( LT_16( *att, lim ) ) + { + *att = lim; + move16(); + } + } + } + + return; +} +#endif diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c index 77da3cd29fbdec4d3f9b06be5791473340db4bc6..4af1da2cd57a07268a5eb13ae42e322f242d2ecd 100644 --- a/lib_enc/cod_tcx.c +++ b/lib_enc/cod_tcx.c @@ -43,6 +43,8 @@ #include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_com.h" +#include "prot_fx_enc.h" +#include "prot_fx.h" /*-------------------------------------------------------------------* * HBAutocorrelation() @@ -1096,6 +1098,7 @@ void QuantizeTCXSpectrum( int16_t NumIndexBits, signaling_bits, sqTargetBits, sqBits, ctxHmBits, resQBits, resQTargetBits; int16_t *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *sqQ, *prm_target; float att; + Word16 att_fx; int32_t total_brate; /*-----------------------------------------------------------* @@ -1549,7 +1552,21 @@ void QuantizeTCXSpectrum( if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { +#ifndef IVAS_FLOAT_FIXED calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + } +#endif + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + att = fix16_to_float( att_fx, Q15 ); +#endif +#endif *gain_tcx *= att; } diff --git a/lib_enc/hq_classifier_enc_fx.c b/lib_enc/hq_classifier_enc_fx.c index 1c5c1de71a0ada816d16ce5ade7dc17b7dd52ebc..d7d30149a46abb567a9542ac46362e2f02ea4a66 100644 --- a/lib_enc/hq_classifier_enc_fx.c +++ b/lib_enc/hq_classifier_enc_fx.c @@ -149,7 +149,6 @@ static Word16 hf_spectrum_sparseness_fx( *crest_mod_lp_fx = L_add( Mpy_32_32( HQ_CREST_FAC_SM_FX, ( *crest_mod_lp_fx ) ), Mpy_32_32( L_sub( ONE_IN_Q31, HQ_CREST_FAC_SM_FX ), crest_mod_fx ) ); // Q12 - inv_rms32_e Word32 hq_crest_threshold = L_shr( HQ_CREST_THRESHOLD_FX, sub( Q28, sub( Q12, inv_rms32_e ) ) ); Word32 hq_crest_mod_threshold = L_shr( HQ_CREST_MOD_THRESHOLD_FX, sub( Q29, sub( Q12, inv_rms32_e ) ) ); - test(); test(); if ( GT_32( ( *crest_lp_fx ), hq_crest_threshold ) && GT_32( ( *crest_mod_lp_fx ), hq_crest_mod_threshold ) && GT_16( low_count_fx, LOW_COUNT_THRESHOLD ) ) @@ -366,6 +365,7 @@ Word16 hq_classifier_enc_ivas_fx( /* o : Consumed bi max_brate = HQ_32k; move32(); + if ( st_fx->element_mode > EVS_MONO ) { max_brate = HQ_48k; @@ -391,7 +391,6 @@ Word16 hq_classifier_enc_ivas_fx( /* o : Consumed bi IF( !is_transient && EQ_16( st_fx->bwidth, st_fx->last_bwidth ) ) { /* Detect HQ_HARMONIC mode */ - *hqswb_clas = peak_avrg_ratio_ivas_fx( st_fx->total_brate, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12 ); harmonic_decision = hf_spectrum_sparseness_fx( st_fx, coefs ); @@ -547,7 +546,6 @@ Word16 peak_avrg_ratio_ivas_fx( hqswb_clas = HQ_HARMONIC; move16(); } - return hqswb_clas; } #endif @@ -955,6 +953,7 @@ void hvq_classifier_ivas_fx( IF( LT_32( L_input_abs[i], L_thr[i] ) ) { L_input_abs[i] = L_deposit_l( 0 ); + move32(); } ELSE @@ -967,6 +966,7 @@ void hvq_classifier_ivas_fx( } } + peak_th = (Word16) BASOP_Util_Divide3232_Scale( L_add( W_extract_l( W_mult0_32_32( L_core_brate, HVQ_PEAKS_PER_DELTA_THR ) ), HVQ_PEAKS_PER_DELTA_THR_OFFS ), HVQ_PEAKS_BPS_DELTA, &temp_e ); peak_th = shr( peak_th, sub( 15, temp_e ) ); /* Find peaks */ diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c index da055a340ce577eee46043f55c69e841615597dd..0caa1ea0d5702ba8a5ba603c00c941f2974691e4 100644 --- a/lib_enc/hq_core_enc.c +++ b/lib_enc/hq_core_enc.c @@ -248,8 +248,30 @@ void hq_core_enc( else { #ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + Word16 temp_e; + + f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); + st->hHQ_core->crest_lp_q = 31 - temp_e; + f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); + st->hHQ_core->crest_mod_lp_q = 31 - temp_e; + } +#endif /* HQ high rate encoder */ - hq_hr_enc( st, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag ); + hq_hr_enc_ivas_fx( st, t_audio_fx, L_spec, &num_bits, is_transient, vad_hover_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + + st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); + st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); + } + fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k ); +#endif #else hq_hr_enc( st, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag ); #endif diff --git a/lib_enc/hq_hr_enc.c b/lib_enc/hq_hr_enc.c index d1aecb8a8830c096f008578e7f1672bb6015982c..23c7fa739227b5b1731fadb03d152d4e1b0a59ff 100644 --- a/lib_enc/hq_hr_enc.c +++ b/lib_enc/hq_hr_enc.c @@ -257,97 +257,71 @@ void hq_hr_enc( } #else -void hq_hr_enc( - Encoder_State *st, /* i/o: encoder state structure */ - float *t_audio, /* i/o: transform-domain coefficients */ - const int16_t length, /* i : length of spectrum */ - int16_t *num_bits, /* i/o: number of available bits */ - const int16_t is_transient, /* i : transient flag */ - const int16_t vad_hover_flag /* i : VAD hangover flag */ +void hq_hr_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word32 *t_audio_fx, /* i/o: transform-domain coefficients */ + const Word16 length, /* i : length of spectrum */ + Word16 *num_bits, /* i/o: number of available bits */ + const Word16 is_transient, /* i : transient flag */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ ) { - int16_t nb_sfm; - int16_t sum, hcode_l; - int16_t difidx[NB_SFM]; - int16_t normqlg2[NB_SFM], ynrm[NB_SFM]; - int16_t nf_idx; + Word16 nb_sfm; + Word16 sum, hcode_l; + Word16 difidx[NB_SFM]; + Word16 normqlg2[NB_SFM], ynrm[NB_SFM]; + Word16 nf_idx; Word16 bits; - int16_t LCmode; - int16_t shape_bits, num_sfm, numnrmibits; - int16_t hqswb_clas; - int16_t num_env_bands; - int16_t Npeaks, start_norm; - int16_t difidx_org[NB_SFM]; - int16_t R[NB_SFM]; - int16_t peaks[HVQ_MAX_PEAKS]; - int16_t sfmsize[NB_SFM], sfm_start[NB_SFM], sfm_end[NB_SFM]; - int16_t npulses[NB_SFM], maxpulse[NB_SFM]; - int16_t Rsubband[NB_SFM]; /* Q3 */ - float t_audio_q[L_SPEC48k_EXT]; - float nf_gains[HVQ_NF_GROUPS], pe_gains[HVQ_NF_GROUPS]; - float noise_level[HVQ_BWE_NOISE_BANDS]; + Word16 LCmode; + Word16 shape_bits, num_sfm, numnrmibits; + Word16 hqswb_clas; + Word16 num_env_bands; + Word16 Npeaks, start_norm; + Word16 difidx_org[NB_SFM]; + Word16 R[NB_SFM]; + Word16 peaks[HVQ_MAX_PEAKS]; + Word16 sfmsize[NB_SFM], sfm_start[NB_SFM], sfm_end[NB_SFM]; + Word16 npulses[NB_SFM], maxpulse[NB_SFM]; + Word16 Rsubband[NB_SFM]; /* Q3 */ + Word32 t_audio_q_fx[L_SPEC48k_EXT]; Word16 noise_level_fx[HVQ_BWE_NOISE_BANDS]; - int16_t hq_generic_offset; - float hq_generic_fenv[HQ_FB_FENV]; - int16_t hq_generic_exc_clas = 0; - int16_t core_sfm; - int16_t har_freq_est1 = 0, har_freq_est2 = 0; - int16_t flag_dis = 1; - const int16_t *subband_search_offset; - int16_t wBands[2]; - int16_t b_delta_env; - // float att; + Word16 hq_generic_offset; + Word16 hq_generic_exc_clas = 0; + move16(); + Word16 core_sfm; + Word16 har_freq_est1 = 0, har_freq_est2 = 0; + move16(); + move16(); + Word16 flag_dis = 1; + move16(); + const Word16 *subband_search_offset; + Word16 wBands[2]; + Word16 b_delta_env; HQ_ENC_HANDLE hHQ_core = st->hHQ_core; BSTR_ENC_HANDLE hBstr = st->hBstr; -#ifdef IVAS_FLOAT_FIXED Word16 att_fx; + Word16 t_audio_norm[L_FRAME48k_EXT]; + Word16 t_audio_q_norm[L_FRAME48k_EXT]; Word32 nf_gains_fx[HVQ_NF_GROUPS], pe_gains_fx[HVQ_NF_GROUPS]; - Word32 t_audio_fx[L_FRAME48k_EXT]; Word16 hq_generic_fenv_fx[HQ_FB_FENV]; -#endif /*------------------------------------------------------------------* * Initializations *------------------------------------------------------------------*/ Npeaks = 0; - set_s( npulses, 0, NB_SFM ); - set_s( maxpulse, 0, NB_SFM ); - set_s( difidx_org, 0, NB_SFM ); - set_f( t_audio_q, 0.0f, L_FRAME48k ); - set_f( nf_gains, 0.0f, HVQ_NF_GROUPS ); - set_f( pe_gains, 0.0f, HVQ_NF_GROUPS ); - set_l( nf_gains_fx, 0, HVQ_NF_GROUPS ); - set_l( pe_gains_fx, 0, HVQ_NF_GROUPS ); + move16(); + set16_fx( npulses, 0, NB_SFM ); + set16_fx( maxpulse, 0, NB_SFM ); + set16_fx( difidx_org, 0, NB_SFM ); + set32_fx( t_audio_q_fx, 0, L_FRAME48k ); + set32_fx( nf_gains_fx, 0, HVQ_NF_GROUPS ); + set32_fx( pe_gains_fx, 0, HVQ_NF_GROUPS ); /*------------------------------------------------------------------* * Classification *------------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Word32 coefs_fx[960]; - floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); - IF( NE_16( st->element_mode, EVS_MONO ) ) - { - Word16 temp_e; - - f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); - st->hHQ_core->crest_lp_q = 31 - temp_e; - f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); - st->hHQ_core->crest_mod_lp_q = 31 - temp_e; - } -#endif - bits = hq_classifier_enc_ivas_fx( st, length, t_audio_fx, is_transient, &Npeaks, peaks, pe_gains_fx, nf_gains_fx, &hqswb_clas ); *num_bits = sub( *num_bits, bits ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - IF( NE_16( st->element_mode, EVS_MONO ) ) - { - - st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); - st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); - } - fixedToFloat_arrL32( nf_gains_fx, nf_gains, Q12, HVQ_NF_GROUPS ); - fixedToFloat_arrL32( pe_gains_fx, pe_gains, Q12, HVQ_NF_GROUPS ); -#endif - + move16(); /*------------------------------------------------------------------* * Set quantization parameters @@ -362,19 +336,12 @@ void hq_hr_enc( IF( is_transient ) { interleave_spectrum_ivas_fx( t_audio_fx, length ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k_EXT ); -#endif } test(); - IF( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) { - calculate_hangover_attenuation_gain_fx( st, &att_fx, vad_hover_flag ); - // att = fix16_to_float( att_fx, Q15 ); + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); v_multc_att32( t_audio_fx, att_fx, t_audio_fx, sfm_end[sub( num_sfm, 1 )] ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k_EXT ); -#endif } /*------------------------------------------------------------------* @@ -383,30 +350,15 @@ void hq_hr_enc( *------------------------------------------------------------------*/ /* calculate and quantize norms */ - // calc_norm_fx( t_audio_fx, 12, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); calc_norm_ivas_fx( t_audio_fx, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); - // calc_norm( t_audio, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); -#if 0 - FILE *fp = fopen( "Fixed_code_ynrm.txt", "ab+" ); - FILE *fp1 = fopen( "Fixed_code_normqlg2.txt", "ab+" ); - for (int i = 0; i < 44; i++) - { - - //fprintf( fp, "%d\t%d\t", frame,i ); - fprintf( fp, "%d\n", ynrm[i] ); - //fprintf( fp1, "%d\t%d\t", frame, i ); - fprintf( fp1, "%d\n", normqlg2[i] ); - } - fclose( fp ); - fclose( fp1 ); -#endif /* create differential code of quantized norm indices */ diff_envelope_coding_fx( is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx ); /* Find norm coding mode and calculate number of bits */ hcode_l = encode_envelope_indices_ivas_fx( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); - //*num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; + *num_bits = sub( *num_bits, add( hcode_l, NORM0_BITS + FLAGS_BITS ) ); + move16(); /* Encode norm indices */ encode_envelope_indices_ivas_fx( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); @@ -417,19 +369,8 @@ void hq_hr_enc( test(); IF( EQ_16( hqswb_clas, HQ_GEN_SWB ) || EQ_16( hqswb_clas, HQ_GEN_FB ) ) { -#ifdef IVAS_FLOAT_FIXED - //#ifdef MSAN_FIX - // floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k ); - //#else - // floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); - //#endif hq_generic_hf_encoding_fx( t_audio_fx, hq_generic_fenv_fx, hq_generic_offset, st, &hq_generic_exc_clas, length ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( hq_generic_fenv_fx, hq_generic_fenv, Q1, HQ_FB_FENV ); -#endif -#else - hq_generic_hf_encoding( t_audio, hq_generic_fenv, hq_generic_offset, st, &hq_generic_exc_clas, length ); -#endif + IF( EQ_16( hq_generic_exc_clas, HQ_GENERIC_SP_EXC ) ) { *num_bits = add( *num_bits, 1 ); /* conditional 1 bit saving for representing FD3 BWE excitation class */ @@ -443,63 +384,81 @@ void hq_hr_enc( *------------------------------------------------------------------*/ ivas_hq_bit_allocation_fx( st->core_brate, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level_fx, R, Rsubband, &sum, &core_sfm, num_env_bands ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( noise_level_fx, noise_level, Q15, HVQ_BWE_NOISE_BANDS ); -#endif + /*------------------------------------------------------------------* * Normalize coefficients with quantized norms *------------------------------------------------------------------*/ - if ( hqswb_clas != HQ_HVQ ) + IF( NE_16( hqswb_clas, HQ_HVQ ) ) { - if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + test(); + IF( EQ_16( hqswb_clas, HQ_GEN_SWB ) || EQ_16( hqswb_clas, HQ_GEN_FB ) ) { - b_delta_env = calc_nor_delta_hf( hBstr, t_audio, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); - sum -= b_delta_env; + b_delta_env = calc_nor_delta_hf_ivas_fx( hBstr, t_audio_fx, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); + sum = sub( sum, b_delta_env ); } - normalizecoefs( t_audio, ynrm, nb_sfm, sfm_start, sfm_end ); + normalizecoefs_fx( t_audio_fx, ynrm, nb_sfm, sfm_start, sfm_end, t_audio_norm ); } - + Word16 Q_audio = 12, Q_shift; /*------------------------------------------------------------------* * Quantize/code spectral fine structure using PVQ or HVQ *------------------------------------------------------------------*/ - - if ( hqswb_clas == HQ_HVQ ) + IF( EQ_16( hqswb_clas, HQ_HVQ ) ) { - sum = hvq_enc( hBstr, st->bwidth, st->core_brate, *num_bits, Npeaks, ynrm, R, peaks, nf_gains, noise_level, pe_gains, t_audio, t_audio_q ); - *num_bits -= sum; + sum = hvq_enc_ivas_fx( st, st->core_brate, *num_bits, Npeaks, ynrm, R, peaks, nf_gains_fx, noise_level_fx, pe_gains_fx, t_audio_fx, t_audio_q_fx ); + *num_bits = sub( *num_bits, sum ); + move16(); } - else + ELSE { - shape_bits = pvq_core_enc( hBstr, t_audio, t_audio_q, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, npulses, maxpulse, HQ_CORE ); - *num_bits += ( sum - shape_bits ); + shape_bits = pvq_core_enc_ivas_fx( hBstr, t_audio_norm, t_audio_q_norm, &Q_audio, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, npulses, maxpulse, HQ_CORE ); + *num_bits = add( *num_bits, sub( sum, shape_bits ) ); + move16(); } - if ( hqswb_clas == HQ_HVQ || hqswb_clas == HQ_HARMONIC ) + test(); + IF( EQ_16( hqswb_clas, HQ_HVQ ) || EQ_16( hqswb_clas, HQ_HARMONIC ) ) { subband_search_offset = subband_search_offsets_13p2kbps_Har; wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; - - har_est( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &hHQ_core->prev_frm_hfe2, subband_search_offset, wBands, &hHQ_core->prev_stab_hfe2 ); + move16(); + move16(); + IF( EQ_16( hqswb_clas, HQ_HARMONIC ) ) + { + Q_shift = sub( SWB_BWE_LR_Qs, Q_audio ); + FOR( Word16 i = 0; i < 300; i++ ) + { + t_audio_q_fx[i] = L_shl( L_deposit_l( t_audio_q_norm[i] ), Q_shift ); /* Q12 */ + move32(); + } + } + har_est_fx( t_audio_q_fx, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &hHQ_core->prev_frm_hfe2, subband_search_offset, wBands, &hHQ_core->prev_stab_hfe2 ); hHQ_core->prev_frm_hfe2 = har_freq_est2; + move16(); } /* reset LR-HQ memories */ hHQ_core->prev_frm_hfe2 = 0; /*reset*/ hHQ_core->prev_stab_hfe2 = 0; - + move16(); + move16(); nf_idx = 0; - if ( !is_transient && hqswb_clas != HQ_HVQ && !( length == L_FRAME16k && st->core_brate <= HQ_32k ) ) + move16(); + test(); + test(); + test(); + IF( NE_16( is_transient, 1 ) && NE_16( hqswb_clas, HQ_HVQ ) && !( EQ_16( length, L_FRAME16k ) && LE_32( st->core_brate, HQ_32k ) ) ) { - if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + test(); + IF( EQ_16( hqswb_clas, HQ_GEN_SWB ) || EQ_16( hqswb_clas, HQ_GEN_FB ) ) { - nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, max( core_sfm, num_env_bands - 1 ) ); + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, s_max( core_sfm, sub( num_env_bands, 1 ) ) ); push_indice( hBstr, IND_NF_IDX, nf_idx, 2 ); } - else + ELSE { - nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, core_sfm ); + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, core_sfm ); push_indice( hBstr, IND_NF_IDX, nf_idx, 2 ); } } @@ -507,20 +466,19 @@ void hq_hr_enc( /* updates */ hHQ_core->prev_hqswb_clas = hqswb_clas; - + move16(); /* Prepare synthesis for LB generation in case of switch to ACELP */ - if ( hqswb_clas != HQ_HVQ ) + IF( NE_16( hqswb_clas, HQ_HVQ ) ) { - apply_envelope_enc( t_audio_q, ynrm, num_sfm, sfm_start, sfm_end ); + apply_envelope_enc_ivas_fx( t_audio_q_norm, ynrm, num_sfm, sfm_start, sfm_end, t_audio_q_fx ); } - if ( is_transient ) + IF( is_transient ) { - de_interleave_spectrum( t_audio_q, length ); + ivas_de_interleave_spectrum_fx( t_audio_q_fx, length ); } - mvr2r( t_audio_q, t_audio, length ); - + MVR2R_WORD32( t_audio_q_fx, t_audio_fx, length ); return; } diff --git a/lib_enc/hvq_enc_fx.c b/lib_enc/hvq_enc_fx.c index b2adfef24cd5adf5d658e1900c966b5bc79a4520..f0852cda6da30ea3ad802fb93daa6defe76ded2f 100644 --- a/lib_enc/hvq_enc_fx.c +++ b/lib_enc/hvq_enc_fx.c @@ -8,6 +8,7 @@ //#include "prot_fx.h" #include "rom_com.h" #include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #define HVQ_ENC_NOISE_DELTA ( (Word16) 3277 ) /* 0.1 in Q15 */ @@ -20,7 +21,201 @@ static Word16 quant_lc( const Word16, Word16 * ); * * Harmonic VQ encoder *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word16 hvq_enc_ivas_fx( /*o : Consumed bits */ + Encoder_State *st_fx, /*i/o: encoder state structure */ + const Word32 core_brate, /*i : Total bit rate */ + const Word16 hvq_bits, /*i : HVQ bit budget */ + const Word16 Npeaks, /*i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains Q12*/ + Word16 *noise_level, /* o : Quantized noise level Q15*/ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q12 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q12 */ +) +{ + const Word32 *pCoefs; + Word16 bin_th, j, i, n; + Word16 nf_cnt; + Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS]; + Word16 q_noise_level[HVQ_BWE_NOISE_BANDS]; + Word32 d, nf_mean; + Word32 nf, pe, pe_mean; + Word16 bits_used, nBits; + Word16 lb_nfpe; + UWord16 dontCare; + Word32 acc, numerator, denominator; + Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3; + Word16 manPeMean, manNfMean, manNfpe, man; + Word16 tmp16, adjust; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + bits_used = 0; + move16(); + + IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) ) + { + bin_th = HVQ_THRES_BIN_24k; + move16(); + n = ( L_FRAME32k - HVQ_THRES_BIN_24k ) / HVQ_BWE_NOISE_BANDS; + move16(); + } + ELSE + { + bin_th = HVQ_THRES_BIN_32k; + move16(); + n = ( L_FRAME32k - HVQ_THRES_BIN_32k ) / HVQ_BWE_NOISE_BANDS; + move16(); + } + + nf = 800 * 4096L; /* Q12 */ + move32(); + pe = 800 * 4096L; /* Q12 */ + move32(); + pCoefs = &coefs[bin_th]; + + /* Find HB noise level */ + FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ ) + { + nf_cnt = 0; + move16(); + nf_mean = L_deposit_l( 0 ); + pe_mean = L_deposit_l( 0 ); + FOR( j = 0; j < n; j++ ) + { + d = L_abs( *pCoefs++ ); /* Q12 */ + + IF( GT_32( d, pe ) ) + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub( pe, d ); + Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare ); + pe = L_add( acc, d ); /* in Q12 and always positive */ + } + ELSE + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub( pe, d ); + Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare ); + pe = L_add( acc, d ); /* in Q12 and always positive */ + + IF( GT_32( d, nf ) ) + { + acc = L_sub( nf, d ); + Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare ); + nf = L_add( acc, d ); /* in Q12 and always positive */ + } + ELSE + { + acc = L_sub( nf, d ); + Mpy_32_16_ss( acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare ); + nf = L_add( acc, d ); /* in Q12 always positive */ + } + nf_mean = L_add( nf_mean, nf ); /* in Q12 and always positive */ + nf_cnt = add( nf_cnt, 1 ); /* Q0 */ + } + +#ifdef BASOP_NOGLOB + pe_mean = L_add_o( pe_mean, pe, &Overflow ); /* in Q12 and always positive */ +#else + pe_mean = L_add( pe_mean, pe ); /* in Q12 and always positive */ +#endif + } + + IF( pe_mean > 0 ) + { + expPeMean = norm_l( pe_mean ); /* exponent */ + manPeMean = extract_h( L_shl( pe_mean, expPeMean ) ); /* mantissa */ + expNfMean = norm_l( nf_mean ); /* exponent */ + manNfMean = extract_h( L_shl( nf_mean, expNfMean ) ); /* mantissa */ + + numerator = L_mult0( manNfMean, n ); + IF( nf_cnt > 0 ) + { + denominator = L_mult0( manPeMean, nf_cnt ); /* in Q15 */ + } + ELSE + { + denominator = L_mult0( manPeMean, 1 ); /* in Q15 */ + } + manNfpe = ratio( numerator, denominator, &expo ); /* manNfpe in Q14 */ + expNfpe = add( sub( expNfMean, expPeMean ), expo ); + + tmp16 = mult_r( manNfpe, manNfpe ); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r( tmp16, manNfpe ); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult( tmp16, HVQ_NFPE_FACTOR_CUBE_FX ); /* in Q(12+6+1) = Q19 */ + expNfpe3 = extract_l( L_mult0( expNfpe, 3 ) ); /* Cube operation */ + /* Number of bits required to adjust to Q15 */ + adjust = add( 19 - ( 15 + 16 ), expNfpe3 ); /* +16 is due to the following extract_h(). */ +#ifdef BASOP_NOGLOB + noise_level[i] = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */ + move16(); +#else + noise_level[i] = extract_h( L_shr( acc, adjust ) ); /* noise_level[] in Q15 */ +#endif + q_noise_level_idx[i] = quant_lc( noise_level[i], &q_noise_level[i] ); + move16(); + } + ELSE + { + q_noise_level_idx[i] = 0; + move16(); + q_noise_level[i] = 0; + move16(); + } + push_indice( st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 ); + bits_used = add( bits_used, 2 ); + + noise_level[i] = q_noise_level[i]; /* in Q15 */ + move16(); + } + + FOR( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + IF( pe_gains[i] != 0 ) + { + /* Neither pe_gains[] nor nf_gains[] is zero. */ + man = ratio( nf_gains[i], pe_gains[i], &expo ); /* man in Q14 */ + tmp16 = mult_r( man, man ); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r( tmp16, man ); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult( tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX ); /* in Q(12+9+1) = Q22 */ + expo3 = extract_l( L_mult0( expo, 3 ) ); /* Cube operation. */ + /* Number of bits required to adjust to Q15 */ + adjust = add( 22 - ( 15 + 16 ), expo3 ); /* +16 is due to the following extract_h(). */ +#ifdef BASOP_NOGLOB + lb_nfpe = extract_h( L_shr_o( acc, adjust, &Overflow ) ); /* noise_level[] in Q15 */ +#else + lb_nfpe = extract_h( L_shr( acc, adjust ) ); /* noise_level[] in Q15 */ +#endif + IF( GT_16( lb_nfpe, 16384 ) ) /* in Q15 */ + { + lb_nfpe = 16384; + move16(); + } +#ifdef BASOP_NOGLOB + Mpy_32_16_ss( nf_gains[i], shl_o( lb_nfpe, 1, &Overflow ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */ +#else + Mpy_32_16_ss( nf_gains[i], shl( lb_nfpe, 1 ), &nf_gains[i], &dontCare ); /* nf_gains[] in Q12 */ +#endif + } + ELSE + { + nf_gains[i] = 0; + move16(); + } + } + nBits = peak_vq_enc_ivas_fx( st_fx->hBstr, st_fx->bwidth, coefs, coefs_out, core_brate, sub( hvq_bits, bits_used ), + Npeaks, ynrm, R, peaks, &nf_gains[0] ); + bits_used = add( bits_used, nBits ); + return bits_used; +} +#endif Word16 hvq_enc_fx( /*o : Consumed bits */ Encoder_State *st_fx, /*i/o: encoder state structure */ const Word32 core_brate, /*i : Total bit rate */ diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 29ef2aa21ecba1cbb71bfba92cb41bbbeb0c70bb..0315a8c5cfdadcb093ad29703b57aad3e050d526 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -3473,6 +3473,7 @@ void IGFEncApplyMono( { float *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ float att = 1.0f; + Word16 att_fx; int16_t last_core_acelp; last_core_acelp = ( st->last_core == ACELP_CORE ); @@ -3483,9 +3484,22 @@ void IGFEncApplyMono( if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { +#ifndef IVAS_FLOAT_FIXED calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); - } +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + } +#endif + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + att = fix16_to_float( att_fx, Q15 ); +#endif +#endif + } IGF_CalculateEnvelope( st->hIGFEnc, pMDCTSpectrum, pPowerSpectrumParameter, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, st->element_mode, att ); diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index 33a06a43a3c91a4db81c42cd24bc4e9773e24cd7..a8761182af62b8041440c58a4aaac09cff9babae 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -78,6 +78,8 @@ static void calculate_energy_buffer_fx( CPE_ENC_HANDLE hCPE, Word64 enerBuffer_d * Front Pre-processing for IVAS * (resampling, spectral analysis, LP analysis, VAD, OL pitch calculation, classification) *--------------------------------------------------------------------*/ + +#ifndef IVAS_FLOAT_FIXED ivas_error pre_proc_front_ivas( SCE_ENC_HANDLE hSCE, /* i/o: SCE encoder structure */ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ @@ -849,7 +851,7 @@ ivas_error pre_proc_front_ivas( pop_wmops(); return error; } -#ifdef IVAS_FLOAT_FIXED +#else ivas_error pre_proc_front_ivas_fx( SCE_ENC_HANDLE hSCE, /* i/o: SCE encoder structure */ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ @@ -896,30 +898,30 @@ ivas_error pre_proc_front_ivas_fx( const int32_t ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ ) { - float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ - float *wsp; /* weighted input signal buffer */ - float Etot; /* total energy */ - float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ - float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ - float tmpN[NB_BANDS]; /* Temporary noise update */ - float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ - float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ - float non_staX_LR; /* non-stationarity for sp/mus classifier */ - float ncharX_LR; /* noise character for sp/mus classifier */ - float sp_div_LR; /* spectral diversity feature */ - float S_map_LR[L_FFT / 2]; /* short-term correlation map */ - float corr_shiftL; /* correlation shift */ - float corr_shiftR; /* correlation shift */ - int16_t loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ - int16_t lr_vad_enabled; /* LR VAD indicator */ - float ee[2]; /* Spectral tilt */ - float corr_shift; /* correlation shift */ - float sp_div, PS[128]; /* speech/music clasif. parameters */ - int16_t L_look; /* length of look-ahead */ + float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ + float *wsp; /* weighted input signal buffer */ + float Etot; /* total energy */ + float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ + float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + float tmpN[NB_BANDS]; /* Temporary noise update */ + float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ + float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ + float non_staX_LR; /* non-stationarity for sp/mus classifier */ + float ncharX_LR; /* noise character for sp/mus classifier */ + float sp_div_LR; /* spectral diversity feature */ + float S_map_LR[L_FFT / 2]; /* short-term correlation map */ + float corr_shiftL; /* correlation shift */ + float corr_shiftR; /* correlation shift */ + int16_t loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ + int16_t lr_vad_enabled; /* LR VAD indicator */ + float ee[2]; /* Spectral tilt */ + float corr_shift; /* correlation shift */ + float sp_div, PS[128]; /* speech/music clasif. parameters */ + int16_t L_look; /* length of look-ahead */ #if 1 - float snr_sum_he; /* HE SAD parameters */ + float snr_sum_he; /* HE SAD parameters */ #endif float mem_decim_dummy[2 * L_FILT_MAX]; /* dummy decimation filter memory */ float temp1F_icatdmResampBuf[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ @@ -1139,8 +1141,8 @@ ivas_error pre_proc_front_ivas_fx( L_look = L_LOOK_12k8; /* lookahead at 12.8kHz */ - new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ - inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ + new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ #ifdef IVAS_FLOAT_FIXED new_inp_12k8_fx = old_inp_12k8_fx + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ #if 0 @@ -1375,8 +1377,8 @@ ivas_error pre_proc_front_ivas_fx( /*------------------------------------------------------------------* * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ -#if 0 // Disabled due to high mld -#if 0 // EVS-Version +#if 0 // Disabled due to high mld +#if 0 // EVS-Version Word16 headroom = 1; IF( ( ( EQ_16( st->bwidth, NB ) ) || ( EQ_16( st->max_bwidth, NB ) ) ) && ( GT_32( st->input_Fs, 8000 ) ) ) { @@ -1453,7 +1455,7 @@ ivas_error pre_proc_front_ivas_fx( move16(); st->Q_old = Q_new; move16(); -#else // IVAS-Version +#else // IVAS-Version IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { @@ -1462,7 +1464,7 @@ ivas_error pre_proc_front_ivas_fx( st->mem_preemph_DFT_fx = (Word16) st->mem_preemph_DFT; Copy( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw_fx, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ -#if 1 // TOBE removed later +#if 1 // TOBE removed later mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; #endif @@ -1741,7 +1743,11 @@ ivas_error pre_proc_front_ivas_fx( IF( NE_16( element_mode, IVAS_CPE_MDCT ) ) /* in MDCT stereo, set_bw_stereo() is used instead */ { +#ifndef IVAS_FLOAT_FIXED set_bw( element_mode, element_brate, st, MODE1 ); +#else + set_bw_fx( element_mode, element_brate, st, MODE1 ); +#endif } /* set the BW of the TD secondary channel in LRTD mode same as BW of the primary channel (only at higher bitrates) */ @@ -1762,13 +1768,42 @@ ivas_error pre_proc_front_ivas_fx( { noise_est_down( fr_bands_LR[0], hCPE->hFrontVad[0]->hNoiseEst->bckr, tmpN_LR[0], tmpE_LR[0], st->min_band, st->max_band, &hCPE->hFrontVad[0]->hNoiseEst->totalNoise, Etot_LR[0], &hCPE->hFrontVad[0]->hNoiseEst->Etot_last, &hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2 ); noise_est_down( fr_bands_LR[1], hCPE->hFrontVad[1]->hNoiseEst->bckr, tmpN_LR[1], tmpE_LR[1], st->min_band, st->max_band, &hCPE->hFrontVad[1]->hNoiseEst->totalNoise, Etot_LR[1], &hCPE->hFrontVad[1]->hNoiseEst->Etot_last, &hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2 ); +#ifndef IVAS_FLOAT_FIXED corr_shiftL = correlation_shift( hCPE->hFrontVad[0]->hNoiseEst->totalNoise ); corr_shiftR = correlation_shift( hCPE->hFrontVad[1]->hNoiseEst->totalNoise ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 corr_shiftL_fx, corr_shiftR_fx; + // performing float to fix conversion of (totalNoise) + hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); +#endif + corr_shiftL_fx = correlation_shift_fx( hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx ); + corr_shiftR_fx = correlation_shift_fx( hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing fix to float conversion of (corr_shift_fx) + corr_shiftL = fix16_to_float( corr_shiftL_fx, 15 ); + corr_shiftR = fix16_to_float( corr_shiftR_fx, 15 ); +#endif +#endif } *relE = Etot - st->lp_speech; +#ifndef IVAS_FLOAT_FIXED corr_shift = correlation_shift( st->hNoiseEst->totalNoise ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 corr_shift_fx; + // performing float to fix conversion of (totalNoise) + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, 8 ); +#endif + corr_shift_fx = correlation_shift_fx( st->hNoiseEst->totalNoise_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing fix to float conversion of (corr_shift_fx) + corr_shift = fix16_to_float( corr_shift_fx, 15 ); +#endif +#endif /*----------------------------------------------------------------* * FD-CNG Noise Estimator @@ -1962,9 +1997,11 @@ ivas_error pre_proc_front_ivas_fx( *-----------------------------------------------------------------*/ st->clas = signal_clas( st, inp_12k8, ee, *relE, L_look, tdm_SM_last_clas ); - +#ifndef IVAS_FLOAT_FIXED select_TC( MODE1, st->tc_cnt, &st->coder_type, st->localVAD ); - +#else + select_TC_fx( MODE1, st->tc_cnt, &st->coder_type, st->localVAD ); +#endif if ( st->Opt_SC_VBR ) { st->hSC_VBR->Local_VAD = st->localVAD; @@ -1991,14 +2028,58 @@ ivas_error pre_proc_front_ivas_fx( * Update of old per-band energy spectrum *----------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED long_enr( st, Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); - +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Etot16_fx; + // conv params from float to fix + Etot_fx = float_to_fix( Etot, 8 ); + Etot16_fx = extract_l( Etot_fx ); + st->lp_speech_fx = float_to_fix16( st->lp_speech, 8 ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, 8 ); + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, 8 ); + st->hNoiseEst->Etot_last_fx = float_to_fix16( st->hNoiseEst->Etot_last, 8 ); +#endif + ivas_long_enr_fx( st, Etot16_fx, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from fix to float + st->lp_speech = fix16_to_float( st->lp_speech_fx, 8 ); + st->lp_noise = fix16_to_float( st->lp_noise_fx, 8 ); + st->hNoiseEst->Etot_last = fix16_to_float( st->hNoiseEst->Etot_last_fx, 8 ); +#endif +#endif mvr2r( fr_bands + NB_BANDS, st->hNoiseEst->enrO, NB_BANDS ); if ( lr_vad_enabled && st->idchan == 0 ) { +#ifndef IVAS_FLOAT_FIXED long_enr( st, -1, localVAD_HE_SAD, high_lpn_flag, hCPE->hFrontVad, CPE_CHANNELS, localVAD_HE_SAD_LR, Etot_LR ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from float to fix + Word16 Etot_LR_fx[2]; + Etot_LR_fx[0] = float_to_fix16( Etot_LR[0], 8 ); + Etot_LR_fx[1] = float_to_fix16( Etot_LR[1], 8 ); + hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); + hCPE->hFrontVad[0]->lp_speech_fx = float_to_fix16( hCPE->hFrontVad[0]->lp_speech, 8 ); + hCPE->hFrontVad[1]->lp_speech_fx = float_to_fix16( hCPE->hFrontVad[1]->lp_speech, 8 ); + hCPE->hFrontVad[0]->lp_noise_fx = float_to_fix16( hCPE->hFrontVad[0]->lp_noise, 8 ); + hCPE->hFrontVad[1]->lp_noise_fx = float_to_fix16( hCPE->hFrontVad[1]->lp_noise, 8 ); +#endif + ivas_long_enr_fx( st, -1, localVAD_HE_SAD, high_lpn_flag, hCPE->hFrontVad, CPE_CHANNELS, localVAD_HE_SAD_LR, Etot_LR_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from fix to float + hCPE->hFrontVad[0]->lp_speech = fix16_to_float( hCPE->hFrontVad[0]->lp_speech_fx, 8 ); + hCPE->hFrontVad[1]->lp_speech = fix16_to_float( hCPE->hFrontVad[1]->lp_speech_fx, 8 ); + hCPE->hFrontVad[0]->lp_noise = fix16_to_float( hCPE->hFrontVad[0]->lp_noise_fx, 8 ); + hCPE->hFrontVad[1]->lp_noise = fix16_to_float( hCPE->hFrontVad[1]->lp_noise_fx, 8 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_last = fix16_to_float( hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_last = fix16_to_float( hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx, 8 ); +#endif +#endif mvr2r( fr_bands_LR[0] + NB_BANDS, hCPE->hFrontVad[0]->hNoiseEst->enrO, NB_BANDS ); mvr2r( fr_bands_LR[1] + NB_BANDS, hCPE->hFrontVad[1]->hNoiseEst->enrO, NB_BANDS ); } diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index c473752dc6bf1a6faf92671d53d47d12de6dc266..a016003f5c8c4b5b3f442fd04e56dfa9475dd6b5 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -837,10 +837,17 @@ ivas_error ivas_cpe_enc( * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED if ( sts[0]->core_brate == SID_2k40 ) { ivas_write_format_sid( ivas_format, hCPE->element_mode, sts[0]->hBstr ); } +#else + IF( EQ_32( sts[0]->core_brate, SID_2k40 ) ) + { + ivas_write_format_sid_fx( ivas_format, hCPE->element_mode, sts[0]->hBstr ); + } +#endif /*----------------------------------------------------------------* * DFT Stereo residual coding diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index d73ec1ea50405a2fc2703484ff699af4911f35a3..cfdfe2b66b918d66f89e1ca0f074cac72f89089b 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -763,9 +763,11 @@ ivas_error ivas_enc( /*----------------------------------------------------------------* * write IVAS format signaling *----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_write_format( st_ivas ); - +#else + ivas_write_format_fx( st_ivas ); +#endif /*----------------------------------------------------------------* * Encoding *----------------------------------------------------------------*/ @@ -1066,7 +1068,7 @@ ivas_error ivas_enc( ivas_lfe_enc_fx( st_ivas->hLFE, data_fx[LFE_CHANNEL], st_ivas->q_data_fx, input_frame, st_ivas->hLFE->hBstr ); } -#if 1 // To be removed +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // To be removed fixedToFloat_arrL( data_fx[LFE_CHANNEL], data_f[LFE_CHANNEL], st_ivas->q_data_fx, input_frame ); #endif diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index 10fae03212f1cef0e55672acdee4cef3a557988d..14f1f6e5e4854eda313dfcb6530e011afb4c4c8a 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -52,6 +52,7 @@ * Write IVAS format signaling *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void ivas_write_format( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) @@ -126,7 +127,99 @@ void ivas_write_format( return; } +#else +void ivas_write_format_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + Word16 ind, nBits, extra_bits; + + ind = 0; + move16(); + + nBits = IVAS_FORMAT_SIGNALING_NBITS; + move16(); + + extra_bits = sub( IVAS_FORMAT_SIGNALING_NBITS_EXTENDED, IVAS_FORMAT_SIGNALING_NBITS ); + + switch ( st_ivas->hEncoderConfig->ivas_format ) + { + case STEREO_FORMAT: + ind = 0; + move16(); + BREAK; + case ISM_FORMAT: + ind = 2; + move16(); + IF( GE_32( st_ivas->hEncoderConfig->ivas_total_brate, IVAS_24k4 ) ) + { + ind = 4; + move16(); + + nBits = add( nBits, extra_bits ); + } + BREAK; + case MC_FORMAT: + ind = 1; + move16(); + BREAK; + case SBA_FORMAT: + ind = 6; + move16(); + + nBits = add( nBits, extra_bits ); + BREAK; + case MASA_FORMAT: + ind = 7; + move16(); + + nBits = add( nBits, extra_bits ); + BREAK; + case MASA_ISM_FORMAT: + IF( st_ivas->ism_mode == ISM_MODE_NONE ) + { + ind = 7; /* send MASA format */ + move16(); + nBits = add( nBits, extra_bits ); + } + ELSE + { + ind = 10; + move16(); + nBits = add( nBits, add( extra_bits, IVAS_COMBINED_FORMAT_SIGNALLING_BITS ) ); + } + BREAK; + case SBA_ISM_FORMAT: + IF( LT_32( st_ivas->hEncoderConfig->ivas_total_brate, IVAS_24k4 ) ) + { + ind = 6; /* send SBA format */ + move16(); + nBits = add( nBits, extra_bits ); + } + ELSE + { + ind = 11; /* 1011 */ + move16(); + nBits = add( nBits, add( extra_bits, IVAS_COMBINED_FORMAT_SIGNALLING_BITS ) ); + } + BREAK; + default: + assert( !"Invalid format. Aborting." ); + BREAK; + } + + IF( st_ivas->hSCE[0] != NULL ) + { + push_indice( st_ivas->hSCE[0]->hCoreCoder[0]->hBstr, IND_IVAS_FORMAT, ind, nBits ); + } + ELSE IF( st_ivas->hCPE[0] != NULL ) + { + push_indice( st_ivas->hCPE[0]->hCoreCoder[0]->hBstr, IND_IVAS_FORMAT, ind, nBits ); + } + return; +} +#endif /*-------------------------------------------------------------------* * ivas_write_format_sid() @@ -134,6 +227,7 @@ void ivas_write_format( * Write IVAS format signaling in SID frames *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void ivas_write_format_sid( const IVAS_FORMAT ivas_format, /* i : IVAS format */ const int16_t element_mode, /* i : element bitrate */ @@ -197,7 +291,80 @@ void ivas_write_format_sid( return; } +#else +void ivas_write_format_sid_fx( + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const Word16 element_mode, /* i : element bitrate */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ +) +{ + Word16 ind = 0; /* to avoid compilation warning */ + move16(); + SWITCH( ivas_format ) + { + case STEREO_FORMAT: + IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) + { + ind = SID_MDCT_STEREO; + move16(); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + ind = SID_DFT_STEREO; + move16(); + } + ELSE + { + assert( !"Wrong stereo mode for SID format signaling" ); + } + BREAK; + case ISM_FORMAT: + ind = SID_ISM; + move16(); + BREAK; + case MC_FORMAT: + ind = SID_MULTICHANNEL; + move16(); + BREAK; + case SBA_FORMAT: + SWITCH( element_mode ) + { + case IVAS_SCE: + ind = SID_SBA_1TC; + move16(); + BREAK; + case IVAS_CPE_MDCT: + ind = SID_SBA_2TC; + move16(); + BREAK; + default: + assert( !"Wrong element mode for SBA DTX!" ); + BREAK; + } + BREAK; + case MASA_FORMAT: + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + ind = SID_MASA_1TC; + move16(); + } + ELSE + { + ind = SID_MASA_2TC; + move16(); + } + BREAK; + default: + assert( !"Reserved SID format symbol written." ); + BREAK; + } + + push_indice( hBstr, IND_IVAS_FORMAT, ind, SID_FORMAT_NBITS ); + + return; +} +#endif /*-------------------------------------------------------------------* * getNumChanAnalysis() diff --git a/lib_enc/ivas_ism_dtx_enc.c b/lib_enc/ivas_ism_dtx_enc.c index eea3314d86edb30c9d4bff7e3a5abcc61add93cc..c1947034d2e220fcda293509076dc37eb67af061 100644 --- a/lib_enc/ivas_ism_dtx_enc.c +++ b/lib_enc/ivas_ism_dtx_enc.c @@ -342,7 +342,7 @@ Word16 ivas_ism_dtx_enc_fx( return dtx_flag; } -#endif // IVAS_FLOAT_FIXED +#else // IVAS_FLOAT_FIXED int16_t ivas_ism_dtx_enc( ISM_DTX_HANDLE hISMDTX, /* i/o: ISM DTX handle */ @@ -546,6 +546,7 @@ int16_t ivas_ism_dtx_enc( return dtx_flag; } +#endif /*-------------------------------------------------------------------* * ivas_ism_get_sce_id_dtx() diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index d1e9d43c32793542e26da26a30025f5ef6d70219..33250b015b6ed8cff9acdffa276156bdcd52ba8f 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -268,11 +268,17 @@ ivas_error ivas_ism_enc( st = st_ivas->hSCE[0]->hCoreCoder[0]; +#ifndef IVAS_FLOAT_FIXED if ( sid_flag ) { ivas_write_format_sid( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); } - +#else + IF( sid_flag ) + { + ivas_write_format_sid_fx( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); + } +#endif /*only metadata encoding is needed for this case*/ if ( st_ivas->hEncoderConfig->ivas_format == SBA_ISM_FORMAT ) { @@ -814,7 +820,7 @@ st = st_ivas->hSCE[0]->hCoreCoder[0]; IF( sid_flag ) { - ivas_write_format_sid( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); + ivas_write_format_sid_fx( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); } /*only metadata encoding is needed for this case*/ diff --git a/lib_enc/ivas_omasa_enc.c b/lib_enc/ivas_omasa_enc.c index 09fb8777c5a877e44f3e3c313b2589b2ad87839d..d6c786811ba4ccb478bd3a7a2a61a0c8f418a0ad 100644 --- a/lib_enc/ivas_omasa_enc.c +++ b/lib_enc/ivas_omasa_enc.c @@ -279,7 +279,11 @@ ivas_error ivas_omasa_enc_config( reset_indices_enc( st_ivas->hCPE[0]->hCoreCoder[0]->hBstr, st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->nb_bits_tot ); } +#ifndef IVAS_FLOAT_FIXED ivas_write_format( st_ivas ); +#else + ivas_write_format_fx( st_ivas ); +#endif if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->hOMasa == NULL ) { diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index dd9f092c3d9a2ebc28cb784a07a3a73b0e63d891..48033d6701db0b2598aacaecdcb7a395cfb16736 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -234,10 +234,17 @@ ivas_error ivas_sce_enc( * Write IVAS format signaling in SID frames *----------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED if ( st->core_brate == SID_2k40 ) { ivas_write_format_sid( ivas_format, IVAS_SCE, st->hBstr ); } +#else + IF( EQ_32( st->core_brate, SID_2k40 ) ) + { + ivas_write_format_sid_fx( ivas_format, IVAS_SCE, st->hBstr ); + } +#endif /*----------------------------------------------------------------* * Core codec configuration diff --git a/lib_enc/long_enr_fx.c b/lib_enc/long_enr_fx.c index cc6291cee38d879561b2e0febb1b3d32088be3c3..b119478a64d2d954499bb08b3099de590819d0a3 100644 --- a/lib_enc/long_enr_fx.c +++ b/lib_enc/long_enr_fx.c @@ -17,14 +17,14 @@ *-------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED void ivas_long_enr_fx( - Encoder_State *st_fx, /* i/o: state structure */ - const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) */ - const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ - Word16 high_lpn_flag, /* i : sp/mus LPN flag */ - FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ - const Word16 n_chan, /* i : number of channels */ - const Word16 localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover LR channels */ - const Word16 Etot_LR[] /* i : total channel energy LR channels */ + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) Q8 */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + Word16 high_lpn_flag, /* i : sp/mus LPN flag */ + FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ + const Word16 n_chan, /* i : number of channels */ + const Word16 localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover LR channels */ + const Word16 Etot_LR[] /* i : total channel energy LR channels Q8 */ ) { @@ -44,6 +44,7 @@ void ivas_long_enr_fx( FOR( n = 0; n < n_chan; n++ ) { hFrontVad[n]->lp_noise_fx = hFrontVad[n]->hNoiseEst->totalNoise_fx; + move16(); tmp = add( hFrontVad[n]->lp_noise_fx, 2560 ); IF( LT_16( hFrontVad[n]->lp_speech_fx, tmp ) ) @@ -61,26 +62,33 @@ void ivas_long_enr_fx( { smooth_prev = 31130; smooth_curr = 1638; + move16(); + move16(); } ELSE { smooth_prev = 32113; smooth_curr = 655; + move16(); + move16(); } FOR( n = 0; n < n_chan; n++ ) { hFrontVad[n]->lp_noise_fx = add( mult_r( smooth_prev, hFrontVad[n]->lp_noise_fx ), mult_r( smooth_curr, hFrontVad[n]->hNoiseEst->totalNoise_fx ) ); - + move16(); + test(); IF( localVAD_HE_SAD_LR[n] && !high_lpn_flag ) { IF( LT_16( sub( hFrontVad[n]->lp_speech_fx, Etot_LR[n] ), 2560 ) ) { hFrontVad[n]->lp_speech_fx = add( mult_r( 32113, hFrontVad[n]->lp_speech_fx ), mult_r( 655, Etot_LR[n] ) ); + move16(); } ELSE { hFrontVad[n]->lp_speech_fx = sub( hFrontVad[n]->lp_speech_fx, 13 ); + move16(); } } } @@ -99,6 +107,7 @@ void ivas_long_enr_fx( move16(); tmp = add( st_fx->lp_noise_fx, 2560 ); /*10.0 in Q8*/ st_fx->lp_speech_fx = s_max( st_fx->lp_speech_fx, tmp ); + move16(); } ELSE { @@ -115,7 +124,7 @@ void ivas_long_enr_fx( move16(); /* 0.05 Q15 */ } st_fx->lp_noise_fx = noise_est_AR1_Qx( hNoiseEst->totalNoise_fx, st_fx->lp_noise_fx, alpha ); /* Q8 state, alpha in Q15 */ - + move16(); test(); IF( ( localVAD_HE_SAD != 0 ) && ( high_lpn_flag == 0 ) ) { @@ -123,13 +132,18 @@ void ivas_long_enr_fx( { /* st->lp_speech = 0.98f * st->lp_speech + 0.02f * Etot; */ st_fx->lp_speech_fx = noise_est_AR1_Qx( Etot, st_fx->lp_speech_fx, 655 ); /* Q8 state, 0.02 in Q15 */ + move16(); } ELSE { st_fx->lp_speech_fx = sub( st_fx->lp_speech_fx, 13 ); /* st->lp_speech = st->lp_speech - 0.05f; linear decay*/ + move16(); } } } + /* Update */ + st_fx->hNoiseEst->Etot_last_fx = Etot; + move16(); } /*-----------------------------------------------------------------* diff --git a/lib_enc/peak_vq_enc_fx.c b/lib_enc/peak_vq_enc_fx.c index 5a1fe61d1eb9c8bc37f9608ec35906f144f99d81..2d2028492133be369545e790bba461f4a6b2b63d 100644 --- a/lib_enc/peak_vq_enc_fx.c +++ b/lib_enc/peak_vq_enc_fx.c @@ -11,6 +11,7 @@ #include "rom_com_fx.h" #include "rom_com.h" #include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ /*-------------------------------------------------------------------------- @@ -20,13 +21,442 @@ static void quant_peaks_fx( BSTR_ENC_HANDLE hBstr, const Word32 *, Word32 *, const Word32 *, Word16 *, const Word16, const Word32, const Word16 ); static Word16 hvq_code_pos_fx( BSTR_ENC_HANDLE hBstr, const Word16 *inp, const Word16 length, const Word16 num_peaks ); static Word16 sparse_code_pos_fx( const Word16 *inp, const Word16 length, Word16 *result ); +#ifdef IVAS_FLOAT_FIXED +static Word16 hvq_code_pos_ivas_fx( BSTR_ENC_HANDLE hBstr, const Word16 *inp, const Word16 length, const Word16 num_peaks ); +static void quant_peaks_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word32 *vect_in, /* i : Target vector in Q12 */ + Word32 *vect_out, /* i/o: Quantized vector in Q12 */ + const Word32 *peak_gain, /* i : Peak gain vector in Q12 */ + Word16 *vq_idx, /* o : Codebook index */ + const Word16 overlap, /* i : Overlap indicator */ + const Word32 core_brate, /* i : Core bitrate */ + const Word16 Npeaks /* i : Number of peaks */ +); +#endif /*-------------------------------------------------------------------------- * peak_vq_enc_fx() * * Vector Quantization of MDCT peaks *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word16 peak_vq_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bwidth, /* i : audio bandwidth */ + const Word32 *coefs, /* i : Input coefficient vector Q12 */ + Word32 *coefs_out, /* o : Quantized output vector Q12 */ + const Word32 core_brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* i : Peak index vector */ + Word32 *nf_gains /* i : Estimated noise floor gains Q12 */ +) +{ + Word16 pos_bits; + Word32 normq; + Word32 pgain_q[HVQ_MAX_PEAKS]; + Word32 peak_gains[HVQ_MAX_PEAKS]; + Word16 coefs_pvq[HVQ_PVQ_BUF_LEN], *pCoefsPvq; /* Q12 */ + Word32 pvq_vector[HVQ_PVQ_BUF_LEN], *pPvqVector; + Word32 *pPvqVectorBandStart; + Word16 pvq_vector_norm[HVQ_PVQ_BUF_LEN]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 i, j, k, m, r, pvq_bands, num_overlap_bins; + Word16 hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th, bin_th2; + Word16 bits; + Word16 nf_seed; + Word16 pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; /* Q0 */ + Word16 pvq_norm[MAX_PVQ_BANDS]; + Word16 pvq_bits, bit_budget; + Word16 pos_vec[HVQ_THRES_BIN_32k]; + Word16 npulses[MAX_PVQ_BANDS]; + Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN]; + Word16 k_sort[MAX_PVQ_BANDS]; + Word16 Rk[MAX_PVQ_BANDS]; + Word16 gopt[NB_SFM]; + Word16 tmp1, exp1; + Word16 Q_coefs; + + + Word16 indx, vqPeaksMinus1, tmp16, whiteNoise; + Word16 *pPgainDifIdx, *pPgainCbIdx, *pVqPeakIdx, *pPosVec; + Word32 *pPeakGains, *pCoefsOut; + const Word32 *pCoefs; + Word32 acc; + UWord16 dontCare16; + Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */ + Word16 expE_peak, expPeakGains, expPkEnrg; + Word16 *pSelBnds; + Word16 sel_bnds[HVQ_NUM_SFM_24k]; + Word16 hvq_band_end[MAX_PVQ_BANDS]; + Word16 hvq_band_start[MAX_PVQ_BANDS]; + Word16 hvq_band_width[MAX_PVQ_BANDS]; + Word16 n_sel_bnds; + UWord32 lsb; + + assert( ( core_brate > HQ_16k40 && core_brate <= HQ_48k ) && "HVQ rate not supported" ); + + + max_peaks = extract_l( Mpy_32_32( L_add( imult3216( core_brate, HVQ_PEAKS_PER_DELTA ), HVQ_PEAKS_PER_DELTA_OFFS ), 282564 ) ); /* 1/HVQ_PEAKS_BPS_DELTA in Q31 */ + + bits = 0; + move16(); + nf_seed = RANDOM_INITSEED; + move16(); + + + set16_fx( coefs_pvq, 0, HVQ_PVQ_BUF_LEN ); + set32_fx( pvq_vector, 0, HVQ_PVQ_BUF_LEN ); + set16_fx( pvq_vector_norm, 0, HVQ_PVQ_BUF_LEN ); + set16_fx( npulses, 0, MAX_PVQ_BANDS ); + + bin_th = HVQ_THRES_BIN_32k; + move16(); + bin_th2 = HVQ_THRES_BIN_32k / HVQ_NF_GROUPS; + move16(); + /* Set bit-rate dependent variables */ + IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) ) + { + bin_th = HVQ_THRES_BIN_24k; + move16(); + bin_th2 = HVQ_THRES_BIN_24k / HVQ_NF_GROUPS; + move16(); + } + + FOR( i = 0; i < bin_th; i++ ) + { + pos_vec[i] = 0; + move16(); + } + + /* Quantize noise floor gains */ + FOR( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + logqnorm_ivas_fx( &nf_gains[i], 12, &indx, 32, 1, &thren_HQ_fx[0] ); + /* De-quantization */ + acc = L_add( dicn_fx[indx], 0 ); /* Q14 */ + nf_gains[i] = L_shr( acc, 1 + 2 ); /* nf_gains in Q12. dicn_fx is in Q14. Need extra shift +2. */ + move32(); + push_indice( hBstr, IND_HVQ_NF_GAIN, (int) indx, 5 ); + bits = add( bits, 5 ); + } + + /* Signal number of peaks */ + i = sub( max_peaks, vq_peaks ); + push_indice( hBstr, IND_NUM_PEAKS, (int) i, 5 ); + bits = add( bits, 5 ); + + /* Identify position of first peak and arrange peak gains by position */ + pVqPeakIdx = &vq_peak_idx[0]; + low_peak_bin = bin_th; + move16(); + FOR( i = 0; i < vq_peaks; i++ ) + { + indx = *pVqPeakIdx++; + move16(); + IF( LT_16( indx, low_peak_bin ) ) + { + low_peak_bin = indx; + move16(); + } + /* Store the sign information. */ + IF( coefs[indx] < 0 ) + { + pos_vec[indx] = -1; /* Negative. */ + move16(); + } + ELSE + { + pos_vec[indx] = 1; /* Positive */ + move16(); + } + } + + pPeakGains = &peak_gains[0]; + pVqPeakIdx = &vq_peak_idx[0]; + pPosVec = &pos_vec[0]; + pCoefs = &coefs[0]; + FOR( i = 0; i < bin_th; i++ ) + { + acc = *pCoefs++; + move32(); + IF( *pPosVec++ != 0 ) + { + *pPeakGains++ = L_abs( acc ); /* in Q12 */ + move32(); + *pVqPeakIdx++ = i; + move16(); + } + } + + /* Scale down peak gains */ + /* Divided by 4 is equivalent to consider peak_gains to be in Q14 from Q12. + * No physical bit shift is actually required. + */ + + /* Quantize peak gains */ + pPeakGains = &peak_gains[0]; + pPgainCbIdx = &pgain_cb_idx[0]; + logqnorm_ivas_fx( pPeakGains++, 14, pPgainCbIdx++, 32, 1, &thren_pg_fx[0] ); + vqPeaksMinus1 = sub( vq_peaks, 1 ); + FOR( i = 0; i < vqPeaksMinus1; i++ ) + { + logqnorm_ivas_fx( pPeakGains++, 14, pPgainCbIdx++, 45, 1, &thren_pg_fx[0] ); + } + + /* Code quantized peak gain indices + * and also scale up peak gains. */ + diffcod_fx( vq_peaks, pgain_cb_idx, &pgain_difidx[1] ); + /* Accumulate peak energy. */ + manE_peak = L_deposit_l( 0 ); + expE_peak = 32; + move16(); + FOR( i = 0; i < vq_peaks; i++ ) + { + indx = pgain_cb_idx[i]; + move16(); + /* Scale up peak gains */ + pgain_q[i] = L_shl( dicn_pg_fx[indx], 2 ); /* pgain_q in Q12 */ + move32(); + /* Use floating point operation to deal with wide dynamic range.l + * 32-bit mantissa is used here. It should be even more accurate than + * the floating-point reference code with 24-bit mantissa! */ + expPeakGains = norm_l( pgain_q[i] ); + manPeakGains = L_shl( pgain_q[i], expPeakGains ); + Mpy_32_32_ss( manPeakGains, manPeakGains, &manPkEnrg, &lsb ); /* peak_gains square */ + expPkEnrg = shl( expPeakGains, 1 ); /* Multiply by 2 due to squaring. */ + /* True floating value = manPkEng x 2^(32 - 1 - expPkEnrg - 2*12). + * In this context, the 32-bit manPkEng is in Q0. + * 32 is due to Mpy_32_32() only providing the 32 MSBs of the 64 bits product. + * -1 is due fractional mode Multiply. 2*12 is due to square of Q12. */ + floating_point_add( &manE_peak, &expE_peak, manPkEnrg, expPkEnrg ); + } + pgain_difidx[0] = pgain_cb_idx[0]; + move16(); + + /* Huffman coding */ + hcode_l = 0; + move16(); + pPgainDifIdx = &pgain_difidx[1]; + FOR( i = 0; i < vqPeaksMinus1; i++ ) + { + indx = *pPgainDifIdx++; + move16(); + hcode_l = add( hcode_l, pgain_huffsizn[indx] ); + } + + FlagN = HUFCODE; + move16(); + + tmp16 = extract_l( L_mult0( GAINI_BITS, vqPeaksMinus1 ) ); + IF( GE_16( hcode_l, tmp16 ) ) + { + hcode_l = tmp16; + move16(); + FlagN = NOHUFCODE; + move16(); + } + + push_indice( hBstr, IND_FLAGN, (int) FlagN, 1 ); + push_indice( hBstr, IND_PG_IDX, (int) pgain_difidx[0], GAIN0_BITS ); + + IF( FlagN ) + { + pPgainDifIdx = &pgain_difidx[1]; + FOR( i = 0; i < vqPeaksMinus1; i++ ) + { + j = *pPgainDifIdx++; + move16(); + m = pgain_huffnorm[j]; + move16(); + r = pgain_huffsizn[j]; + move16(); + + push_indice( hBstr, IND_PG_IDX, (int) m, r ); + } + } + ELSE + { + pPgainDifIdx = &pgain_difidx[1]; + FOR( i = 0; i < vqPeaksMinus1; i++ ) + { + push_indice( hBstr, IND_PG_IDX, (int) ( *pPgainDifIdx++ ), GAINI_BITS ); + } + } + + /* Number of bits used for peak gain quantization */ + bits = add( bits, add( FLAGN_BITS + GAIN0_BITS, hcode_l ) ); + + /* Add sign for peak shape normalization */ + FOR( i = 0; i < vq_peaks; i++ ) + { + indx = vq_peak_idx[i]; + move16(); + peak_gains[i] = pgain_q[i]; /* Q12 */ + move32(); + IF( pos_vec[indx] < 0 ) + { + peak_gains[i] = L_negate( peak_gains[i] ); /* Q12 */ + } + } + + /* Quantize peak shapes */ + FOR( i = 0; i < vqPeaksMinus1; i++ ) + { + num_overlap_bins = sub( 5, sub( vq_peak_idx[i + 1], vq_peak_idx[i] ) ); + indx = sub( vq_peak_idx[i], 2 ); + quant_peaks_ivas_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, num_overlap_bins, core_brate, vq_peaks ); + push_indice( hBstr, IND_HVQ_PEAKS, (UWord16) vq_cb_idx, 8 ); + bits = add( bits, 9 ); + } + + indx = sub( vq_peak_idx[i], 2 ); + quant_peaks_ivas_fx( hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, 0, core_brate, vq_peaks ); + push_indice( hBstr, IND_HVQ_PEAKS, (UWord16) vq_cb_idx, 8 ); + bits = add( bits, 9 ); + + /* Quantize peak positions and sign with HVQ */ + pos_bits = hvq_code_pos_ivas_fx( hBstr, pos_vec, bin_th, vq_peaks ); + + bits = add( bits, pos_bits ); + bit_budget = sub( num_bits, bits ); + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc_fx( bit_budget, core_brate, bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds ); + + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands_fx( pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end ); + + /* Quantize PVQ bands */ + pCoefsOut = coefs_out; + pCoefs = coefs; + pPvqVector = pvq_vector; + pSelBnds = sel_bnds; + m = bin_th; + move16(); + FOR( k = 0; k < pvq_bands; k++ ) + { + IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) ) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefs = coefs + i; + pCoefsOut = coefs_out + i; + } + k_sort[k] = k; + move16(); + j = 0; + move16(); + pPvqVectorBandStart = pPvqVector; + WHILE( LT_16( j, hvq_band_width[k] ) ) + { + IF( *pCoefsOut++ == 0 ) + { + *pPvqVector++ = *pCoefs; /* Q12 */ + move32(); + j = add( j, 1 ); + } + pCoefs++; + } + logqnorm_ivas_fx( pPvqVectorBandStart, 12, &pvq_norm[k], 40, hvq_band_width[k], &thren_HQ_fx[0] ); + } + + /* Normalize coefficients */ + normalizecoefs_fx( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end, pvq_vector_norm ); + Q_coefs = 12; + move16(); + + bit_budget = sub( bit_budget, i_mult2( HVQ_PVQ_GAIN_BITS, pvq_bands ) ); + + pvq_bits = bit_budget; + move16(); + set16_fx( npulses, 0, MAX_PVQ_BANDS ); + + pvq_encode_frame_ivas_fx( hBstr, pvq_vector_norm, Q_coefs, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands, + Rk, pvq_bits, HQ_CORE ); + + FOR( i = 0; i < pvq_bands; i++ ) + { + k_sort[i] = i; + move16(); + } + + + fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, pvq_bands, coefs_pvq, + pvq_inp_vector, fg_pred, HQ_CORE ); + + pCoefsOut = &coefs_out[0]; + pSelBnds = &sel_bnds[0]; + pCoefsPvq = &coefs_pvq[0]; + FOR( k = 0; k < pvq_bands; k++ ) + { + indx = pvq_norm[k]; + tmp1 = ratio( gopt[k], fg_pred[k], &exp1 ); + tmp1 = shr( tmp1, sub( 1, exp1 ) ); /* Q13 */ + Mpy_32_16_ss( dicn_fx[indx], tmp1, &normq, &dontCare16 ); /* dicn_fx in Q14, sorted_pvq_gain_pred_err_fx in Q13. */ + + logqnorm_fx( &normq, 12, &pvq_norm[k], 40, 1, 0 ); /* normq in Q(14+(16+13)+1-32)=Q12 */ + pvq_norm[k] = sub( pvq_norm[k], 8 ); + move16(); + IF( pvq_norm[k] < 0 ) + { + pvq_norm[k] = 0; + move16(); + } + + push_indice( hBstr, IND_HVQ_PVQ_GAIN, pvq_norm[k], HVQ_PVQ_GAIN_BITS ); + pvq_bits = add( pvq_bits, HVQ_PVQ_GAIN_BITS ); + + pvq_norm[k] = add( pvq_norm[k], 8 ); + move16(); + indx = pvq_norm[k]; + move16(); + normq = L_add( dicn_fx[indx], 0 ); /* in Q14 */ + j = 0; + move16(); + IF( GE_16( k, sub( pvq_bands, n_sel_bnds ) ) ) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefsOut = coefs_out + i; + } + WHILE( LT_16( j, hvq_band_width[k] ) ) + { + IF( *pCoefsOut == 0 ) + { + acc = L_mult( *pCoefsPvq++, fg_pred[k] ); /* in Q(15 + 1 + 12 = 28) */ + tmp16 = extract_h( acc ); /* in Q(28 - 16 = 12) */ + Mpy_32_16_ss( normq, tmp16, &acc, &dontCare16 ); /* acc(Q11), normq(Q14), tmp16(Q12) */ + *pCoefsOut = L_shl( acc, 12 - 11 ); /* Q12 */ + move32(); + j = add( j, 1 ); + } + pCoefsOut++; + } + } + bits = add( bits, pvq_bits ); + + /* Noise fill unqantized coeffs with one gain per group */ + pCoefsOut = &coefs_out[-1]; + FOR( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + FOR( j = 0; j < bin_th2; j++ ) + { + IF( *( ++pCoefsOut ) == 0 ) + { + whiteNoise = Random( &nf_seed ); /* Q15 */ + Mpy_32_16_ss( nf_gains[i], whiteNoise, pCoefsOut, &dontCare16 ); /* nf_gains in Q12. *pCoefsOut in Q12 */ + } + } + } + + return bits; +} +#endif Word16 peak_vq_enc_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 bwidth, /* i : audio bandwidth */ @@ -442,7 +872,162 @@ Word16 peak_vq_enc_fx( * * Applies VQ on input vector *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void quant_peaks_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word32 *vect_in, /* i : Target vector in Q12 */ + Word32 *vect_out, /* i/o: Quantized vector in Q12 */ + const Word32 *peak_gain, /* i : Peak gain vector in Q12 */ + Word16 *vq_idx, /* o : Codebook index */ + const Word16 overlap, /* i : Overlap indicator */ + const Word32 core_brate, /* i : Core bitrate */ + const Word16 Npeaks /* i : Number of peaks */ +) +{ + Word16 x[4]; /* Qx */ + Word16 xq[4]; /* Q15 */ + Word16 weights[4]; /* Q0 */ + Word16 *pWeights; + Word16 i, cb_class, search_overlap, indx, cbSize; + Word16 expPeakGain, manPeakGain, expIn, manIn; + Word32 vectIn, absPeakGain1, absPeakGain; + UWord16 dontCare; + Word16 Qx_vec[4]; + Word16 Qx = 15; + move16(); + set16_fx( weights, 1, 4 ); + + /* Divide vect_in[] by peak_gain to yield x[]. */ + expPeakGain = norm_l( *peak_gain ); /* exponent */ + manPeakGain = extract_h( L_shl( *peak_gain, expPeakGain ) ); /* mantissa */ + manPeakGain = abs_s( manPeakGain ); /* Prepare for div_s() only accepting +ve. */ + FOR( i = 0; i < 4; i++ ) + { + indx = hvq_index_mapping_fx[i]; + move16(); + vectIn = L_add( vect_in[indx], 0 ); + expIn = norm_l( vectIn ); /* exponent */ + expIn = sub( expIn, 1 ); + expIn = s_min( expIn, expPeakGain ); /* highest Q is Q15 */ + manIn = extract_h( L_shl( vectIn, expIn ) ); /* mantissa */ + manIn = abs_s( manIn ); /* Prepare for div_s() only accepting +ve. */ + + x[i] = div_s( manIn, manPeakGain ); /* in Q(15+expIn-expPeakGain) */ + move16(); + Qx_vec[i] = add( 15, sub( expIn, expPeakGain ) ); + move16(); + Qx = s_min( Qx, Qx_vec[i] ); + + /* Restore the sign destroyed by abs operations. */ + IF( L_xor( vectIn, *peak_gain ) < 0 ) /* Check the sign bits (MSB). */ + { + x[i] = negate( x[i] ); + move16(); + } + } + FOR( i = 0; i < 4; i++ ) + { + IF( NE_16( Qx_vec[i], Qx ) ) + { + x[i] = shr( x[i], sub( Qx_vec[i], Qx ) ); /* Qx */ + move16(); + } + } + absPeakGain = L_abs( peak_gain[0] ); + IF( vect_out[0] != 0 ) + { + absPeakGain1 = L_abs( peak_gain[-1] ); + IF( GT_32( absPeakGain1, absPeakGain ) ) + { + weights[0] = 0; + move16(); + if ( vect_out[1] != 0 ) + { + weights[1] = 0; + move16(); + } + } + } + IF( overlap > 0 ) + { + absPeakGain1 = L_abs( peak_gain[1] ); + IF( GT_32( absPeakGain1, absPeakGain ) ) + { + indx = sub( 4, overlap ); + pWeights = &weights[indx]; + FOR( i = 0; i < overlap; i++ ) + { + *pWeights++ = 0; + move16(); + } + } + } + + /* Classify */ + cb_class = w_vquant_fx( x, Qx, weights, 0, hvq_class_c_fx, HVQ_NUM_CLASS, 0 ); + IF( LT_32( core_brate, HQ_BWE_CROSSOVER_BRATE ) ) + { + indx = sub( HVQ_MAX_PEAKS_24k, Npeaks ); + search_overlap = hvq_cb_search_overlap24k[indx]; + move16(); + } + ELSE + { + indx = sub( HVQ_MAX_PEAKS_32k, Npeaks ); + search_overlap = hvq_cb_search_overlap32k[indx]; + move16(); + } + + /* Quantize */ + cbSize = add( HVQ_CB_SIZE / 2, search_overlap ); + IF( cb_class == 0 ) + { + *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 0 ); + move16(); + push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16( cb_class, 1 ) ) + { + indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) ); + *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 0 ); + move16(); + *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) ); + move16(); + push_indice( hBstr, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16( cb_class, 2 ) ) + { + indx = sub( HVQ_CB_SIZE * 2, shl( search_overlap, 2 ) ); + *vq_idx = w_vquant_fx( x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 1 ); + move16(); + *vq_idx = add( *vq_idx, sub( HVQ_CB_SIZE / 2, search_overlap ) ); + move16(); + push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 ); + } + ELSE + { + *vq_idx = w_vquant_fx( x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 1 ); + move16(); + push_indice( hBstr, IND_HVQ_PEAKS, 1, 1 ); + } + + FOR( i = 0; i < 4; i++ ) + { + indx = hvq_index_mapping_fx[i]; + move16(); + IF( weights[i] != 0 ) + { + Mpy_32_16_ss( *peak_gain, xq[i], &vect_out[indx], &dontCare ); /* peak_gains in Q12, xq in Q15 -> Q12. */ + move32(); + } + } + vect_out[2] = *peak_gain; + move32(); /* vect_out in Q12 */ + + return; +} +#endif static void quant_peaks_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word32 *vect_in, /* i : Target vector in Q12 */ @@ -673,7 +1258,120 @@ static Word16 sparse_code_pos_fx( * * Code pulse positions *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 hvq_code_pos_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *inp, + const Word16 length, + const Word16 num_peaks ) +{ + Word16 sparse_result[4 * HVQ_THRES_BIN_32k / HVQ_CP_L1_LEN]; + Word16 delta[HVQ_MAX_PEAKS]; + Word16 peak_idx[HVQ_MAX_PEAKS]; + Word16 inp_abs[HVQ_THRES_BIN_32k]; + Word16 inp_sign[HVQ_MAX_PEAKS]; + + Word16 i, j; + Word16 bits; + Word16 delta_max; + Word16 delta_bits, sparse_bits; + Word16 tmp; + + bits = 0; + move16(); + + /* Extract sorted peak index vector and sign vector */ + j = 0; + move16(); + FOR( i = 0; i < length; i++ ) + { + inp_abs[i] = abs_s( inp[i] ); + move16(); + IF( inp[i] != 0 ) + { + peak_idx[j] = i; + move16(); + inp_sign[j] = inp[i]; + move16(); + j = add( j, 1 ); + } + } + + /* Calculate delta */ + delta[0] = add( peak_idx[0], HVQ_CP_HUFF_OFFSET ); + move16(); + delta_max = delta[0]; + move16(); + FOR( i = 1; i < num_peaks; i++ ) + { + delta[i] = sub( sub( peak_idx[i], peak_idx[i - 1] ), HVQ_CP_HUFF_OFFSET ); + move16(); + if ( LT_16( delta_max, delta[i] ) ) + { + delta_max = delta[i]; + move16(); + } + } + + /* Calculate bits needed for huffman coding of deltas */ + delta_bits = -1; + move16(); + IF( LE_16( delta_max, HVQ_CP_HUFF_MAX ) ) + { + delta_bits = 0; + move16(); + FOR( i = 0; i < num_peaks; i++ ) + { + delta_bits = add( delta_bits, hvq_cp_huff_len[delta[i]] ); + } + } + + /* Calculate bits neeed for sparse coding */ + sparse_bits = sparse_code_pos_fx( inp_abs, length, sparse_result ); + + /* Decide which coding mode to use */ + test(); + IF( GT_16( delta_bits, sparse_bits ) || delta_bits < 0 ) + { + push_indice( hBstr, IND_POS_IDX, HVQ_CP_SPARSE, 1 ); + + FOR( i = 0; i < sparse_bits; i++ ) + { + push_indice( hBstr, IND_POS_IDX, sparse_result[i], 1 ); + } + bits = add( add( bits, sparse_bits ), 1 ); + } + ELSE + { + push_indice( hBstr, IND_POS_IDX, HVQ_CP_DELTA, 1 ); + + FOR( i = 0; i < num_peaks; i++ ) + { + j = delta[i]; + move16(); + push_indice( hBstr, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j] ); + } + bits = add( add( bits, delta_bits ), 1 ); + } + + /* Send sign */ + FOR( i = 0; i < num_peaks; i++ ) + { + tmp = 1; + move16(); + if ( inp_sign[i] < 0 ) + { + tmp = 0; + move16(); + } + push_indice( hBstr, IND_POS_IDX, tmp, 1 ); + } + bits = add( bits, num_peaks ); + return bits; +} + +#endif static Word16 hvq_code_pos_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 *inp, diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index ddac54b52736e125dab066d64fc924d73316ca51..21ef9508695d2afdcb3ca487aded0f130a3b40ce 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -249,13 +249,13 @@ void long_enr_fx( #ifdef IVAS_FLOAT_FIXED void ivas_long_enr_fx( Encoder_State *st_fx, /* i/o: state structure */ - const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) */ + const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) Q=8*/ const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ Word16 high_lpn_flag, /* i : sp/mus LPN flag */ FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ const Word16 n_chan, /* i : number of channels */ const Word16 localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover LR channels */ - const Word16 Etot_LR[] /* i : total channel energy LR channels */ + const Word16 Etot_LR[] /* i : total channel energy LR channels Q=8*/ ); #endif @@ -3052,7 +3052,24 @@ Word16 pvq_core_enc_fx( Word16 *maxpulse, /* i : maximum pulse per band */ const Word16 core /* i : number of bands */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 pvq_core_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ + Word16 coefs_quant[], /* o : quantized coefficients */ + Word16 *Q_coefs, + const Word16 bits_tot, /* i : total number of bits */ + const Word16 nb_sfm, /* i : number of bands */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 *sfmsize, /* i : subband width */ + Word16 *R, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16 *Rs, /* i/o: Integer bit allocation */ + Word16 *npulses, /* o : number of pulses */ + Word16 *maxpulse, /* i : maximum pulse per band */ + const Word16 core /* i : number of bands */ +); +#endif void core_switching_hq_prepare_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word16 *num_bits, /* i/o: bit budget update */ @@ -3068,6 +3085,15 @@ void hq_lr_enc_fx( const Word16 is_transient_fx /* i : Q0 : transient flag */ ); +void hq_hr_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word32 *t_audio, /* i/o: transform-domain coefficients Q12*/ + const Word16 length, /* i : length of spectrum */ + Word16 *num_bits, /* i/o: number of available bits */ + const Word16 is_transient, /* i : transient flag */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); + void hq_lr_enc_ivas_fx( Encoder_State *st_fx, /* i/o: : encoder state structure */ Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ @@ -3185,7 +3211,22 @@ Word16 hvq_enc_fx( /* o : Consumed bits */ const Word32 *coefs, /* i : spectrum coefficients in Q14 */ Word32 *coefs_out /* o : encoded spectrum coefficients in Q14 */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 hvq_enc_ivas_fx( /*o : Consumed bits */ + Encoder_State *st_fx, /*i/o: encoder state structure */ + const Word32 core_brate, /*i : Total bit rate */ + const Word16 hvq_bits, /*i : HVQ bit budget */ + const Word16 Npeaks, /*i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains Q12 */ + Word16 *noise_level, /* o : Quantized noise level Q15 */ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q12 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q12 */ +); +#endif Word16 pvq_core_enc_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ @@ -3270,7 +3311,21 @@ void diffcod_lrmdct_fx( Word16 *difidx, /* o : differential code */ const Word16 is_transient /* i : transient flag */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 peak_vq_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bwidth, /* i : audio bandwidth */ + const Word32 *coefs, /* i : Input coefficient vector Q12 */ + Word32 *coefs_out, /* o : Quantized output vector Q12 */ + const Word32 core_brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* i : Peak index vector */ + Word32 *nf_gains /* i : Estimated noise floor gains Q12 */ +); +#endif Word16 peak_vq_enc_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 bwidth, /* i : audio bandwidth */ @@ -3439,7 +3494,24 @@ void pvq_encode_frame_fx( const Word16 pvq_bits, /* i : number of bits avaiable */ const Word16 core /* i : core */ ); - +#ifdef IVAS_FLOAT_FIXED +void pvq_encode_frame_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, /* i : Q-point of coefs_norm[] */ + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *gopt, /* o : optimal shape gains */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band Q3 */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +); +#endif Word16 Interpol_4( /* o : interpolated value */ Word16 *x, /* i : i vector */ Word16 frac /* i : fraction (-4..+3) */ @@ -3469,7 +3541,19 @@ void pvq_encode_fx( const Word16 dim, /* i: Length of vector */ const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0 ..1 */ ); - +#ifdef IVAS_FLOAT_FIXED +void pvq_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0 ..1 */ +); +#endif void rc_enc_init_fx( PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ Word16 tot_bits /* i : Total bit budget */ @@ -3479,7 +3563,13 @@ void rc_enc_finish_fx( BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ ); +#ifdef IVAS_FLOAT_FIXED +void rc_enc_finish_ivas_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ +); +#endif void rc_encode_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -3487,7 +3577,21 @@ void rc_encode_fx( UWord32 sym_freq, /* i : Symbol probability */ UWord32 tot /* i : Total cumulative frequency */ ); - +#ifdef IVAS_FLOAT_FIXED +void rc_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +); +void rc_enc_uniform_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +); +#endif void rc_enc_uniform_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -3501,7 +3605,14 @@ void rc_enc_bits_fx( UWord32 value, /* i : Value to encode */ Word16 bits /* i : Number of bits used */ ); - +#ifdef IVAS_FLOAT_FIXED +void rc_enc_bits_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +); +#endif void re8_compute_base_index_fx( const Word16 *x, /* i : Elemen of Q2, Q3 or Q4 */ const Word16 ka, /* i : Identifier of the absolute leader related to x */ diff --git a/lib_enc/pvq_core_enc_fx.c b/lib_enc/pvq_core_enc_fx.c index 040853d5da1b6f106794aa6487535117f90061aa..445d75491630e9d6af2b9e02f2390bd90ef6d155 100644 --- a/lib_enc/pvq_core_enc_fx.c +++ b/lib_enc/pvq_core_enc_fx.c @@ -16,12 +16,126 @@ *--------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED static Word16 calc_pvq_splits_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 band_bits, const Word16 sfmsize, const Word16 *y, const Word16 Q_y, Word16 *bits ); - +static Word16 calc_pvq_splits_ivas_fx( /* o : Number of segments */ + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 band_bits, /* i : Band bit rate */ + const Word16 sfmsize, /* i : Band width */ + const Word16 *y, /* i : Target vector */ + const Word16 Q_y, /* i : Q point of y */ + Word16 *bits /* o : Consumed bits */ +); +static void densityIndexSymbolEncode_ivas_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 density, const Word16 r_dim, const Word16 l_dim, const Word16 index_phi ); static void densityIndexSymbolEncode_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 density, const Word16 r_dim, const Word16 l_dim, const Word16 index_phi ); static void encode_energies_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 *coefs, const Word16 Q_coefs, Word16 Np, Word16 *dim_part, Word32 *E_part, Word16 *bits_part, Word16 *g_part, Word16 qband, Word16 *bits_left, Word32 enr, Word16 dim, const Word16 strict_bits ); +static void encode_energies_ivas_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 *coefs, const Word16 Q_coefs, Word16 Np, Word16 *dim_part, Word32 *E_part, Word16 *bits_part, Word16 *g_part, Word16 qband, Word16 *bits_left, Word32 enr, Word16 dim, const Word16 strict_bits ); /* Encode band with PVQ */ +#ifdef IVAS_FLOAT_FIXED +static void pvq_encode_band_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *coefs_norm, /* i : normalized vector to encode */ + const Word16 Q_coefs, + Word16 *pulse_vector, /* o : quantized vector, integer */ + Word16 *npulses, /* o : number of pulses */ + Word16 *coefs_quant, /* o : quantized vector Q=12*/ + const Word16 sfmsize, /* i : length of vector */ + const Word16 band_bits, /* i : assigned bits */ + Word16 *bits_left, /* o : bits remaining */ + const Word16 strict_bits /* i : conservative rounding flag */ +) +{ + + Word16 K_val; + Word16 j, Np; + Word32 enr, E_part[MAX_SPLITS + 1]; + Word16 part_start[MAX_SPLITS + 1], dim_part[MAX_SPLITS + 1], bits_part[MAX_SPLITS + 1]; + Word16 pool_tot, pool_part, dim_parts; + Word16 g_part[MAX_SPLITS]; + Word16 g_part_neg[MAX_SPLITS]; + Word16 sg_part[MAX_SPLITS + 1]; + Word16 idx_sort[MAX_SPLITS + 1]; + Word16 js, band_bits_tot, split_bit; + Word16 tmp; + Word32 L_coefs_quant_fx[PVQ_MAX_BAND_SIZE]; + + Np = calc_pvq_splits_ivas_fx( hBstr, hPVQ, band_bits, sfmsize, coefs_norm, Q_coefs, &split_bit ); + band_bits_tot = sub( band_bits, split_bit ); + + enr = L_deposit_l( 0 ); + FOR( j = 0; j < sfmsize; j++ ) + { + /* This is of paramount importance that the number of bits down-shift here + * MUST BE IDENTICAL to that used to compute "l_enr" in encode_energies_fx(). + * If the number of bits down-shift is changed here, that in encode_energies_fx() + * must be changed to the same amount as well! + */ + tmp = shr( coefs_norm[j], 2 ); + enr = L_mac0( enr, tmp, tmp ); + } + + dim_parts = extract_h( L_mult( negate( sfmsize ), lim_neg_inv_tbl_fx[Np] ) ); + set16_fx( dim_part, dim_parts, sub( Np, 1 ) ); + dim_part[Np - 1] = sub( sfmsize, i_mult2( dim_parts, sub( Np, 1 ) ) ); + move16(); + + part_start[0] = 0; + move16(); + FOR( j = 1; j < Np; j++ ) + { + part_start[j] = add( part_start[j - 1], dim_part[j - 1] ); + move16(); + } + + /* Encode energies */ + set16_fx( g_part_neg, -32768, Np ); /* -1.0 in Q15 */ + IF( GT_16( Np, 1 ) ) + { + encode_energies_ivas_fx( hBstr, hPVQ, coefs_norm, Q_coefs, Np, dim_part, E_part, bits_part, g_part_neg, band_bits_tot, bits_left, enr, sfmsize, strict_bits ); + } + ELSE + { + bits_part[0] = band_bits_tot; + move16(); + } + + pool_tot = 0; /* Word16 */ + move16(); + pool_part = 0; /* Word16 */ + move16(); + + FOR( j = 0; j < Np; j++ ) + { + g_part[j] = negate( g_part_neg[j] ); + move16(); + } + srt_vec_ind16_fx( g_part, sg_part, idx_sort, Np ); + FOR( j = 0; j < Np; j++ ) + { + js = idx_sort[Np - 1 - j]; + move16(); + pool_part = shrtCDivSignedApprox( pool_tot, sub( Np, j ) ); + bits_part[js] = s_max( 0, s_min( add( bits_part[js], pool_part ), 256 ) ); + move16(); + conservativeL1Norm_fx( dim_part[js], bits_part[js], strict_bits, *bits_left, pool_tot, *npulses, /* inputs */ + &K_val, bits_left, &pool_tot, npulses ); /* outputs */ + + IF( K_val > 0 ) + { + pvq_encode_ivas_fx( hBstr, hPVQ, coefs_norm + part_start[js], pulse_vector + part_start[js], + coefs_quant + part_start[js], L_coefs_quant_fx, K_val, dim_part[js], g_part_neg[js] ); + } + ELSE + { + set16_fx( coefs_quant + part_start[js], 0, dim_part[js] ); + set16_fx( pulse_vector + part_start[js], 0, dim_part[js] ); + } + } + return; +} +#endif static void pvq_encode_band_fx( BSTR_ENC_HANDLE hBstr, /* i/o: Encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -121,7 +235,136 @@ static void pvq_encode_band_fx( return; } +#ifdef IVAS_FLOAT_FIXED +void pvq_encode_frame_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, /* i : Q-point of coefs_norm[] */ + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *gopt, /* o : optimal shape gains */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band Q3 */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +) +{ + Word16 i, j; + Word16 band_bits, bits_left; + + Word16 bit_pool = 0; + move16(); + Word16 coded_bands, bands_to_code; + Word16 bits; + Word16 R_sort[NB_SFM]; + Word16 is, i_sort[NB_SFM]; + Word16 strict_bits; + Word16 exp, tmp, shift; + Word32 xy_corr, yy_corr; + PVQ_ENC_DATA pvq_enc; + PVQ_ENC_HANDLE hPVQ = &pvq_enc; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + rc_enc_init_fx( hPVQ, pvq_bits ); + + bits = shl( sub( pvq_bits, RC_BITS_RESERVED ), 3 ); + + bands_to_code = 0; + move16(); + FOR( i = 0; i < nb_sfm; i++ ) + { + IF( R[i] > 0 ) + { + bands_to_code = add( bands_to_code, 1 ); + } + } + + IF( core == ACELP_CORE ) + { + strict_bits = 1; + move16(); + srt_vec_ind16_fx( R, R_sort, i_sort, nb_sfm ); + } + ELSE + { + strict_bits = 0; + move16(); + FOR( i = 0; i < nb_sfm; i++ ) + { + i_sort[i] = i; + move16(); + } + } + + coded_bands = 0; + move16(); + FOR( i = 0; i < nb_sfm; i++ ) + { + is = i_sort[i]; + move16(); + gopt[is] = 0; + move16(); + IF( R[is] > 0 ) + { + bandBitsAdjustment_fx( hPVQ->rc_num_bits, hPVQ->rc_range, bits, bands_to_code, bands_to_code - coded_bands, sfmsize[is], R[is], bit_pool, /* inputs */ + &band_bits, &bits_left, &bit_pool ); /* outputs */ + pvq_encode_band_ivas_fx( hBstr, hPVQ, &coefs_norm[sfm_start[is]], Q_coefs, &pulse_vector[sfm_start[is]], + &npulses[is], &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits ); + + xy_corr = L_deposit_l( 0 ); + yy_corr = L_deposit_l( 1 ); + shift = band_len_ener_shift[band_len_idx[shr( sfmsize[is], 3 )]]; + move16(); + FOR( j = 0; j < sfmsize[i]; j++ ) + { + tmp = shr( coefs_quant[sfm_start[is] + j], shift ); + xy_corr = L_mac0( xy_corr, shr( coefs_norm[sfm_start[is] + j], 1 ), tmp ); /* Q_coefs-1+15-shift */ + yy_corr = L_mac0( yy_corr, tmp, tmp ); /* 2*(15-shift) */ + } + + tmp = ratio( xy_corr, yy_corr, &exp ); +#ifdef BASOP_NOGLOB + gopt[is] = shl_o( tmp, sub( sub( sub( 14, Q_coefs ), shift ), exp ), &Overflow ); + move16(); +#else /* BASOP_NOGLOB */ + gopt[is] = shl( tmp, sub( sub( sub( 14, Q_coefs ), shift ), exp ) ); +#endif + + if ( gopt[is] == 0 ) + { + gopt[is] = 1; + move16(); + } + + /* Updates */ + coded_bands = add( coded_bands, 1 ); + } + ELSE + { + FOR( j = sfm_start[is]; j < sfm_end[is]; j++ ) + { + coefs_quant[j] = 0; + move16(); + pulse_vector[j] = 0; + move16(); + } + } + } + + rc_enc_finish_ivas_fx( hBstr, hPVQ ); + + return; +} +#endif void pvq_encode_frame_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 *coefs_norm, /* i : normalized coefficients to encode */ @@ -252,8 +495,8 @@ void pvq_encode_frame_fx( * * Main Generic Audio Encoder Routine *---------------------------------------------------------------------*/ - -Word16 pvq_core_enc_fx( +#ifdef IVAS_FLOAT_FIXED +Word16 pvq_core_enc_ivas_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ Word16 coefs_quant[], /* o : quantized coefficients */ @@ -286,7 +529,7 @@ Word16 pvq_core_enc_fx( gain_bits_tot = assign_gain_bits_fx( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); pvq_bits = shr( R_upd, 3 ); - pvq_encode_frame_fx( hBstr, coefs_norm, *Q_coefs, coefs_quant, gopt, npulses, pulse_vector, sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + pvq_encode_frame_ivas_fx( hBstr, coefs_norm, *Q_coefs, coefs_quant, gopt, npulses, pulse_vector, sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); IF( Rs != NULL ) @@ -318,20 +561,93 @@ Word16 pvq_core_enc_fx( fine_gain_pred_fx( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, nb_sfm, coefs_quant, pulse_vector, fg_pred, core ); - fine_gain_quant_fx( hBstr, ord, nb_sfm, gain_bits_array, fg_pred, gopt ); + fine_gain_quant_ivas_fx( hBstr, ord, nb_sfm, gain_bits_array, fg_pred, gopt ); apply_gain_fx( ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant ); *Q_coefs = 12; - + move16(); return add( pvq_bits, gain_bits_tot ); - ; } +#endif +Word16 pvq_core_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ + Word16 coefs_quant[], /* o : quantized coefficients */ + Word16 *Q_coefs, + const Word16 bits_tot, /* i : total number of bits */ + const Word16 nb_sfm, /* i : number of bands */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 *sfmsize, /* i : subband width */ + Word16 *R, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16 *Rs, /* i/o: Integer bit allocation */ + Word16 *npulses, /* o : number of pulses */ + Word16 *maxpulse, /* i : maximum pulse per band */ + const Word16 core /* i : number of bands */ +) +{ + Word16 i; + Word16 R_upd; /* Q3 */ + Word16 ord[NB_SFM_MAX]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 pvq_bits; -static void encode_energies_fx( - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ - PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ - const Word16 *coefs, /* In block-floating point format with a common block-exponent - not used in this function. Hence, the block-exponent is + Word16 pulse_vector[L_SPEC48k_EXT]; + Word16 gopt[NB_SFM]; + Word16 gain_bits_array[NB_SFM]; + Word16 gain_bits_tot; + + + R_upd = shl( bits_tot, 3 ); + gain_bits_tot = assign_gain_bits_fx( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + pvq_bits = shr( R_upd, 3 ); + + pvq_encode_frame_fx( hBstr, coefs_norm, *Q_coefs, coefs_quant, gopt, npulses, pulse_vector, sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + + + IF( Rs != NULL ) + { + FOR( i = 0; i < nb_sfm; i++ ) + { + if ( npulses[i] <= 0 ) + { + Rs[i] = 0; + move16(); /* Update Rs in case no pulses were assigned */ + } + } + } + + FOR( i = 0; i < nb_sfm; i++ ) + { + ord[i] = i; + move16(); + if ( npulses[i] <= 0 ) + { + R[i] = 0; + move16(); /* Update in case no pulses were assigned */ + } + } + + get_max_pulses_fx( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + /* Fine gain prediction */ + fine_gain_pred_fx( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, nb_sfm, + coefs_quant, pulse_vector, fg_pred, core ); + + fine_gain_quant_fx( hBstr, ord, nb_sfm, gain_bits_array, fg_pred, gopt ); + + apply_gain_fx( ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant ); + *Q_coefs = 12; + move16(); + return add( pvq_bits, gain_bits_tot ); + ; +} + +static void encode_energies_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *coefs, /* In block-floating point format with a common block-exponent + not used in this function. Hence, the block-exponent is not in the parameter list. */ const Word16 Q_coefs, Word16 Np, /* i : number of parts */ @@ -466,7 +782,230 @@ static void encode_energies_fx( return; } +#ifdef IVAS_FLOAT_FIXED +static void encode_energies_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *coefs, /* In block-floating point format with a common block-exponent + not used in this function. Hence, the block-exponent is + not in the parameter list. */ + const Word16 Q_coefs, + Word16 Np, /* i : number of parts */ + Word16 *dim_part, /* o : sizes of parts */ + Word32 *E_part, /* o : energies of parts 32-bit Q15 */ + Word16 *bits_part, /* o : assigned bits per part */ + Word16 *g_part, /* o : gains Q15 */ + Word16 qband, /* i : assigned quanta per band */ + Word16 *bits_left, /* o : remaining bits */ + Word32 enr, /* i : energy of vector */ + Word16 dim, /* i : size of vector */ + const Word16 strict_bits /* i : conservative rounding flag */ +) +{ + Word16 i, j, l_Np, r_Np; + Word16 l_bits, r_bits, l_dim, r_dim; + Word32 l_enr, r_enr; + Word16 l_gain, r_gain; + Word16 il, ir; + Word16 density; + Word16 phi; + Word16 index_phi = -1; + move16(); + Word16 oppRQ3, qzero; + Word16 angle; + Word32 sqrt_r_enr, sqrt_l_enr; + Word16 exp1, exp2, tmp; + l_Np = shr( Np, 1 ); + r_Np = sub( Np, l_Np ); + l_enr = L_deposit_l( 0 ); + l_bits = 0; + move16(); + l_dim = 0; + move16(); + FOR( i = 0; i < l_Np; i++ ) + { + l_dim = add( l_dim, dim_part[i] ); + } + FOR( j = 0; j < l_dim; j++ ) + { + /* This is of paramount importance that the number of bits down-shift + * must be identical to that used to compute "enr" in pvq_encode_band_fx(). + * Otherwise, the subsequent "r_enr" will be computed incorrectly. + */ + tmp = shr( coefs[j], 2 ); + l_enr = L_mac0( l_enr, tmp, tmp ); + } + r_enr = L_sub( enr, l_enr ); + r_dim = sub( dim, l_dim ); + + obtainEnergyQuantizerDensity_fx( dim, qband, &density ); + sqrt_r_enr = Sqrt_l( r_enr, &exp1 ); + sqrt_l_enr = Sqrt_l( l_enr, &exp2 ); + + IF( LT_16( exp1, exp2 ) ) + { + sqrt_l_enr = L_shr( sqrt_l_enr, shr( sub( exp2, exp1 ), 1 ) ); + } + ELSE IF( LT_16( exp2, exp1 ) ) + { + sqrt_r_enr = L_shr( sqrt_r_enr, shr( sub( exp1, exp2 ), 1 ) ); + exp1 = exp2; + move16(); + } + + exp1 = add( shl( sub( Q_coefs, 2 ), 1 ), add( 31, exp1 ) ); /* 2x exponent */ + IF( EQ_16( s_and( exp1, 1 ), 1 ) ) + { + sqrt_r_enr = Mult_32_16( sqrt_r_enr, 23170 ); /* Q(exp1/2) */ + sqrt_l_enr = Mult_32_16( sqrt_l_enr, 23170 ); /* Q(exp1/2) */ + } + + IF( sqrt_r_enr != 0 ) + { + angle = atan2_fx( sqrt_r_enr, sqrt_l_enr ); /* Q14 */ + } + ELSE + { + angle = 0; + move16(); + } + + phi = mult_r( angle, 20861 ); + + rangeCoderFinalizationFBits_fx( hPVQ->rc_num_bits, (UWord32) hPVQ->rc_range, &qzero ); + densityAngle2RmsProjEnc_fx( density, phi, &index_phi, &ir, &il, &oppRQ3 ); + densityIndexSymbolEncode_ivas_fx( hBstr, hPVQ, density, r_dim, l_dim, index_phi ); + + + l_gain = il; /* Q15 */ + move16(); + r_gain = ir; /* Q15 */ + move16(); + + FOR( i = 0; i < l_Np; i++ ) + { + g_part[i] = mult_r( l_gain, g_part[i] ); + move16(); + } + + FOR( i = l_Np; i < Np; i++ ) + { + g_part[i] = mult_r( r_gain, g_part[i] ); + move16(); + } + + NearOppSplitAdjustment_fx( qband, qzero, hPVQ->rc_num_bits, hPVQ->rc_range, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np - 1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left ); + + IF( GT_16( l_Np, 1 ) ) + { + encode_energies_ivas_fx( hBstr, hPVQ, coefs, Q_coefs, l_Np, dim_part, E_part, bits_part, g_part, l_bits, bits_left, l_enr, l_dim, strict_bits ); + } + ELSE + { + E_part[0] = l_enr; + move32(); + bits_part[0] = l_bits; + move16(); + } + IF( GT_16( r_Np, 1 ) ) + { + encode_energies_ivas_fx( hBstr, hPVQ, &coefs[l_dim], Q_coefs, r_Np, &dim_part[l_Np], &E_part[l_Np], &bits_part[l_Np], &g_part[l_Np], r_bits, bits_left, r_enr, r_dim, strict_bits ); + } + ELSE + { + E_part[1] = r_enr; + move32(); + bits_part[1] = r_bits; + move16(); + } + + return; +} +static void densityIndexSymbolEncode_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 density, /* i : Current density */ + const Word16 r_dim, /* i : Opposite size */ + const Word16 l_dim, /* i : Near size */ + const Word16 index_phi /* i : Index */ +) +{ + Word16 angle, c, densitySubIndex, densitySubC; + Word32 sym_freq, cum_freq, tot; + Word32 acc; + UWord16 lsb; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + sym_freq = L_deposit_l( 1 ); + + IF( s_and( (Word16) 0xFFFE, density ) != 0 ) /* even */ + { + angle = atan2_fx( SQRT_DIM_fx[r_dim], SQRT_DIM_fx[l_dim] ); +#ifdef BASOP_NOGLOB + angle = shl_o( angle, 1, &Overflow ); +#else + angle = shl( angle, 1 ); +#endif + angle = mult_r( angle, 20861 ); + c = mult_r( density, angle ); + + densitySubIndex = sub( density, index_phi ); + densitySubC = sub( density, c ); + + IF( c == 0 ) + { + tot = L_mac0( 1L, density, add( density, 1 ) ); + sym_freq = L_deposit_l( add( shl( sub( density, index_phi ), 1 ), 1 ) ); + cum_freq = L_mac0( L_mult( index_phi, density ), index_phi, 1 ); + } + ELSE IF( EQ_16( c, density ) ) + { + tot = L_mac0( 1L, density, add( density, 1 ) ); + sym_freq = L_deposit_l( add( shl( index_phi, 1 ), 1 ) ); + cum_freq = L_mult0( index_phi, index_phi ); + } + ELSE + { + acc = L_mult0( density, c ); /* density*c */ + Mpy_32_16_ss( acc, densitySubC, &acc, &lsb ); /* density*c*(density - c) */ + acc = L_or( L_shl( acc, 16 ), L_and( lsb, 0xffffL ) ); /* Concatenate acc and lsb forming 48-bit; upshift 16 bits; keep 32 MSB. */ + acc = L_shr( acc, 1 ); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + tot = L_add( L_add( acc, (Word32) density ), 1L ); /* density*c*(density - c) + density + 1 */ + IF( LE_16( index_phi, c ) ) + { + sym_freq = L_mac( 1L, index_phi, densitySubC ); + acc = L_mult0( densitySubC, sub( index_phi, 1 ) ); + acc = L_add( acc, 1 ); + Mpy_32_16_ss( acc, index_phi, &acc, &lsb ); + acc = L_or( L_shl( acc, 16 ), L_and( lsb, 0xffffL ) ); + cum_freq = L_shr( acc, 1 ); + } + ELSE + { + sym_freq = L_mac( 1L, densitySubIndex, c ); + acc = L_mult0( densitySubIndex, add( densitySubIndex, 1 ) ); + Mpy_32_16_ss( acc, c, &acc, &lsb ); + acc = L_or( L_shl( acc, 16 ), L_and( lsb, 0xffffL ) ); + acc = L_shr( acc, 1 ); + acc = L_sub( acc, (Word32) index_phi ); + acc = L_add( add( density, 1 ), acc ); + cum_freq = L_sub( tot, acc ); + } + } + + rc_encode_ivas_fx( hBstr, hPVQ, cum_freq, sym_freq, tot ); + } + + return; +} +#endif static void densityIndexSymbolEncode_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ @@ -553,7 +1092,111 @@ static void densityIndexSymbolEncode_fx( * * Calculate the number of segments needed *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 calc_pvq_splits_ivas_fx( /* o : Number of segments */ + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 band_bits, /* i : Band bit rate */ + const Word16 sfmsize, /* i : Band width */ + const Word16 *y, /* i : Target vector */ + const Word16 Q_y, /* i : Q point of y */ + Word16 *bits /* o : Consumed bits */ +) +{ + Word16 Np; + Word16 Npart; + Word16 i, j; + Word16 E[MAX_SPLITS]; + Word16 Emean, eTotal; + Word16 tmp, expo; + const Word16 *pY; + Word16 max_dev, qPoint; + Word32 acc, acc1; + + IF( band_bits == 0 ) + { + Np = 1; + move16(); + } + ELSE + { + acc = L_mult0( band_bits, 0x7a44 ); + Np = extract_l( L_shr( acc, 23 ) ); /* Get integer part. */ + if ( L_and( acc, 0x7fffffL ) != 0 ) /* If fractional part != 0, add 1. */ + { + Np = add( Np, 1 ); /* ceiling operation */ + } + } + *bits = 0; + move16(); + IF( LT_16( Np, MAX_SPLITS ) ) + { + acc = L_mult0( 8 * THR_ADD_SPLIT, sfmsize ); + IF( GT_32( band_bits, acc ) ) + { + Npart = extract_l( (Word32) intLimCDivPos_fx( UL_deposit_l( (UWord16) sfmsize ), Np ) ); + *bits = 8; + move16(); + eTotal = 0; + move16(); + pY = y; + qPoint = shl( Q_y, 1 ); /* acc in 2*Q_y */ + FOR( i = 0; i < Np; i++ ) + { + acc = L_deposit_l( 0 ); + FOR( j = 0; j < Npart; j++ ) + { + acc = L_mac0( acc, *pY, *pY ); + pY++; + } + acc = L_shr( acc, qPoint ); + + E[i] = sub( 30, norm_l( L_max( 1L, acc ) ) ); /* L_max needed to handle low subvector levels */ + move16(); + eTotal = add( eTotal, E[i] ); + } + + Emean = ratio( eTotal, Np, &expo ); + Emean = shr( Emean, add( 14 - 8, expo ) ); /* Emean in Q8 */ + + max_dev = -1; + move16(); + FOR( i = 0; i < Np; i++ ) + { + tmp = abs_s( sub( shl( E[i], 8 ), Emean ) ); /* in Q8 */ + max_dev = s_max( tmp, max_dev ); + } + + acc = L_sub( L_shl( Np, 5 + 3 + 8 ), L_shl( band_bits, 8 ) ); /* NB: max_dev in Q8 */ + acc1 = L_shl( L_mult0( Np, max_dev ), 3 ); + + tmp = 0; + move16(); + IF( GT_32( acc1, acc ) ) + { + tmp = 1; + move16(); + } + rc_enc_bits_ivas_fx( hBstr, hPVQ, tmp, 1 ); + Np = add( Np, tmp ); + } + } + + /* Check constraints for number of splits */ + /* The following code assumes that PVQ_MAX_BAND_SIZE is 64 */ + i = shr( sfmsize, 6 ); /* 6 = log2(64) = log2(PVQ_MAX_BAND_SIZE) */ + IF( s_and( sfmsize, 0x3f ) != 0 ) + { + i = add( i, 1 ); /* ceiling operation */ + } + + Np = s_max( i, Np ); + Np = s_min( MAX_SPLITS, Np ); + Np = s_min( sfmsize, Np ); /* The code line assumes that MIN_BAND_SIZE is 1 */ + return Np; +} +#endif static Word16 calc_pvq_splits_fx( /* o : Number of segments */ BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ diff --git a/lib_enc/pvq_encode_fx.c b/lib_enc/pvq_encode_fx.c index 1cee445e0e4646822e64ab085e3cbbd62ccb7007..4ebc0c35f6eb45b9378b00f6912c1328e5369235 100644 --- a/lib_enc/pvq_encode_fx.c +++ b/lib_enc/pvq_encode_fx.c @@ -174,6 +174,225 @@ static Word16 one_pulse_search( * Function pvq_encode_fx() * * * *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void pvq_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 fot eval */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0..1 */ +) +{ + Word16 i; + Word16 pulse_tot; + Word16 xabs[PVQ_MAX_BAND_SIZE]; + Word16 max_xabs; + Word32 L_xsum; + Word32 L_proj_fac; + Word32 L_yy, L_xy; + Word16 max_amp_y, imax; + Word16 k, en_margin, en_dn_shift, high_prec_active; + + Word32 L_num, L_tmp; + Word16 proj_fac, tmp, shift_den, shift_num, shift_delta, num, den; + + UWord16 u16_tmp; + Word16 dim_m1; + Word32 L_isqrt; + Word16 neg_gain_norm, shift_tot; + Word16 high_pulse_density_flag; + PvqEntry entry; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + L_proj_fac = 4096; + move32(); + L_xsum = L_deposit_h( 0 ); + max_xabs = -1; + move16(); + + FOR( i = 0; i < dim; i++ ) + { + xabs[i] = abs_s( x[i] ); + move16(); /* Q12 */ + max_xabs = s_max( max_xabs, xabs[i] ); /* for efficient search correlation scaling */ + L_xsum = L_mac0( L_xsum, 1, xabs[i] ); /* stay in Q12 */ + y[i] = 0; + move16(); /* init, later only non-zero values need to be normalized */ + } + + test(); + IF( L_xsum == 0 || neg_gain == 0 ) + { + pulse_tot = pulses; + move16(); + dim_m1 = sub( dim, 1 ); + y[dim_m1] = 0; + move16(); + y[0] = shr( pulses, 1 ); + move16(); + y[dim_m1] = add( y[dim_m1], sub( pulses, y[0] ) ); + move16(); + L_yy = L_mult( y[0], y[0] ); /* L_yy needed for normalization */ + IF( dim_m1 != 0 ) + { + L_yy = L_mac( L_yy, y[dim_m1], y[dim_m1] ); /* (single basop) */ + } + } + ELSE + { + + num = sub( pulses, PYR_OFFSET ); + high_pulse_density_flag = pyramidSearchProjInit_fx( dim, pulses ); + + test(); + IF( ( num > 0 ) && ( high_pulse_density_flag != 0 ) ) + { + shift_den = norm_l( L_xsum ); /* x_sum input Q12 */ + den = extract_h( L_shl( L_xsum, shift_den ) ); /* now in Q12+shift_den */ + + L_num = L_deposit_l( num ); + shift_num = sub( norm_l( L_num ), 1 ); + L_num = L_shl( L_num, shift_num ); /* now in Q0 +shift_num -1 */ + proj_fac = div_l( L_num, den ); /* L_num always has to be less than den<<16 */ + + shift_delta = sub( shift_num, shift_den ); +#ifdef BASOP_NOGLOB + L_proj_fac = L_shl_sat( L_deposit_l( proj_fac ), sub( 9, shift_delta ) ); /* bring to a fixed Q12 */ +#else + L_proj_fac = L_shl( L_deposit_l( proj_fac ), sub( 9, shift_delta ) ); /* bring to a fixed Q12 */ +#endif + } + + pulse_tot = 0; + move16(); + L_yy = L_deposit_l( 0 ); + L_xy = L_deposit_l( 0 ); + test(); + IF( ( num > 0 ) && ( high_pulse_density_flag != 0 ) ) + { + FOR( i = 0; i < dim; i++ ) /* max 64 */ + { + Mpy_32_16_ss( L_proj_fac, xabs[i], &L_tmp, &u16_tmp ); /*Q12 *Q12 +1 */ + y[i] = extract_l( L_shr( L_tmp, 12 + 12 - 16 + 1 ) ); + move16(); /* Q12 *Q12 -> Q0 */ + + pulse_tot = add( pulse_tot, y[i] ); /* Q0 */ + L_yy = L_mac( L_yy, y[i], y[i] ); /* Energy, result will scale up by 2 by L_mac */ + L_xy = L_mac( L_xy, xabs[i], y[i] ); /* Corr, Q0*Q12 +1 --> Q13 */ + } + } + + + L_yy = L_shr( L_yy, 1 ); + IF( LE_16( pulses, 127 ) ) + { + /* LC inner loop, enters here always for dimensions 6 and higher, and also sometimes for dimensions 1 .. 5 */ + /* ( if high energy precision is inactive, max_amp_y is not needed , no max_amp_y(k-1) update ) */ + FOR( k = pulse_tot; k < pulses; k++ ) + { + L_yy = L_add( L_yy, 1 ); + imax = one_pulse_search( dim, xabs, y, &pulse_tot, &L_xy, &L_yy, 0, 0, max_xabs ); + } + } + ELSE + { /* HC or LC+HC inner loops */ + max_amp_y = max_val_fx( y, dim ); /* this loops over max 5 values (as pulses are dimension restricted) */ + /* max_amp_y from projected y is needed when pulses_sum exceeds 127 */ + + /* First section with 32 bit energy inactive, max_amp_y kept updated though */ + FOR( k = pulse_tot; k < 128; k++ ) + { + L_yy = L_add( L_yy, 1 ); + imax = one_pulse_search( dim, xabs, y, &pulse_tot, &L_xy, &L_yy, 0, 0, max_xabs ); + max_amp_y = s_max( max_amp_y, y[imax] ); + } + + /* Second section with higher number of pulses, 32 bit energy precission adaptively selected, max_amp_y kept updated */ + FOR( k = pulse_tot; k < pulses; k++ ) + { + L_yy = L_add( L_yy, 1 ); + en_margin = norm_l( L_mac( L_yy, 1, max_amp_y ) ); /* find max current energy "addition", margin, ~ 2 ops */ + en_dn_shift = sub( 16, en_margin ); /* calc. shift to lower byte for fixed use of extract_l */ + + high_prec_active = 1; + move16(); + if ( en_dn_shift <= 0 ) + { + /* only use 32 bit energy if actually needed */ + high_prec_active = 0; + move16(); + } + /* 32 bit energy and corr adaptively active, max_amp_y kept updated */ + imax = one_pulse_search( dim, xabs, y, &pulse_tot, &L_xy, &L_yy, high_prec_active, en_dn_shift, max_xabs ); + max_amp_y = s_max( max_amp_y, y[imax] ); + } + } + L_yy = L_shl( L_yy, 1 ); /* compensate search loop analysis energy downshift by 1, + to make energy right for unit/inverse gain calculation */ + } + + /* Apply unit energy normalization scaling, always at least one pulse so no div-by-zero check is needed */ + L_isqrt = L_deposit_l( 0 ); + IF( neg_gain != 0 ) + { + L_isqrt = Isqrt( L_shr( L_yy, 1 ) ); /* Note: one single gain factor as not computed */ + } + + shift_num = norm_s( pulse_tot ); /* account for max possible pulse amplitude in y, + can be used even when max_amp_y is not avail. */ + shift_den = norm_s( neg_gain ); /* account for gain downscaling shift */ + neg_gain_norm = shl( neg_gain, shift_den ); /* up to 10 dB loss without this norm */ + shift_tot = sub( add( shift_num, shift_den ), 15 ); + + L_isqrt = L_negate( L_isqrt ); + FOR( i = 0; i < dim; i++ ) + { + tmp = shl( y[i], shift_num ); /* upshifted abs(y[i]) used in scaling */ + if ( x[i] < 0 ) + { + tmp = negate( tmp ); /* apply sign */ + } + + IF( y[i] != 0 ) + { + y[i] = shr( tmp, shift_num ); + move16(); /* updates sign of y[i} , ~range -512 + 512), array move */ + } + Mpy_32_16_ss( L_isqrt, tmp, &L_tmp, &u16_tmp ); /* Q31*Q(0+x) +1 */ + Mpy_32_16_ss( L_tmp, neg_gain_norm, &L_tmp, &u16_tmp ); /* Q31*Q(0+x) *Q15 +1 */ +#ifdef BASOP_NOGLOB + L_tmp = L_shr_o( L_tmp, shift_tot, &Overflow ); /* Q31+x */ + xq[i] = round_fx_o( L_tmp, &Overflow ); /* Q15, array move */ + move16(); +#else + L_tmp = L_shr( L_tmp, shift_tot ); /* Q31+x */ + xq[i] = round_fx( L_tmp ); /* Q15, array move */ +#endif + L_xq[i] = L_tmp; /* Q31 currently unused */ + move32(); + } + + /* index the found PVQ vector into short codewords */ + entry = mpvq_encode_vec_fx( y, dim, pulses ); + + /* send the short codeword(s) to the range encoder */ + rc_enc_bits_ivas_fx( hBstr, hPVQ, UL_deposit_l( entry.lead_sign_ind ), 1 ); /* 0 or 1 */ + IF( NE_16( dim, 1 ) ) + { + rc_enc_uniform_ivas_fx( hBstr, hPVQ, entry.index, entry.size ); + } + + return; +} + +#endif void pvq_encode_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ diff --git a/lib_enc/range_enc_fx.c b/lib_enc/range_enc_fx.c index b05b2cf99fbe8ede4f1bdacde5e637bf19e2a3ac..5c691c3a20b026c946e5105a73686e7d2da1cdf5 100644 --- a/lib_enc/range_enc_fx.c +++ b/lib_enc/range_enc_fx.c @@ -10,12 +10,16 @@ #include "rom_com.h" /* Static table prototypes */ //#include "prot_fx.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ static void rc_enc_shift_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ ); static void rc_enc_write_fx( BSTR_ENC_HANDLE hBstr, Word16 byte, Word16 bits ); - +#ifdef IVAS_FLOAT_FIXED +static void rc_enc_shift_ivas_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ ); +static void rc_enc_write_ivas_fx( BSTR_ENC_HANDLE hBstr, Word16 byte, Word16 bits ); +#endif /*-------------------------------------------------------------------* * rc_enc_init() * @@ -51,7 +55,46 @@ void rc_enc_init_fx( * * Encode symbol with range coder *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void rc_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +) +{ + UWord32 r, tmp, inv_tot, lsb; + Word16 exp; + UWord16 carry; + + inv_tot = UL_inverse( tot, &exp ); + Mpy_32_32_uu( hPVQ->rc_range, inv_tot, &tmp, &lsb ); /*0+exp-32 */ + r = UL_lshr( tmp, sub( exp, 32 ) ); /* exp-32-exp3+32 = 0 */ + tmp = UL_Mpy_32_32( r, cum_freq ); + + hPVQ->rc_low = UL_addNs( hPVQ->rc_low, tmp, &carry ); + move32(); + if ( carry != 0 ) + { + hPVQ->rc_carry = carry; + move16(); + } + hPVQ->rc_range = UL_Mpy_32_32( r, sym_freq ); + move32(); + WHILE( LT_64( hPVQ->rc_range, 1 << 24 ) ) + { + hPVQ->rc_range = UL_lshl( hPVQ->rc_range, 8 ); + move32(); + hPVQ->rc_num_bits = add( hPVQ->rc_num_bits, 8 ); + move16(); + rc_enc_shift_ivas_fx( hBstr, hPVQ ); + } + + return; +} +#endif void rc_encode_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -94,7 +137,92 @@ void rc_encode_fx( * * Finalize range coder *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void rc_enc_finish_ivas_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ + +) +{ + UWord32 val, mask, high; + Word16 bits; + UWord16 over1, over2; + + bits = add( norm_ul( hPVQ->rc_range ), 1 ); + mask = UL_lshr( 0xffffffff, bits ); + + val = UL_addNs( hPVQ->rc_low, mask, &over1 ); + high = UL_addNs( hPVQ->rc_low, hPVQ->rc_range, &over2 ); + val = L_and( val, ~mask ); + L_xor( 0, 0 ); /* For bit not */ + + IF( ( L_xor( over1, over2 ) ) == 0 ) + { + L_sub( 0, 0 ); /* For comparision in if */ + IF( UL_addNsD( val, mask ) >= high ) + { + bits = add( bits, 1 ); + mask = UL_lshr( mask, 1 ); + val = UL_and( UL_addNsD( hPVQ->rc_low, mask ), ~mask ); + L_xor( 0, 0 ); /* For bit not */ + } + + if ( LT_32( val, hPVQ->rc_low ) ) + { + hPVQ->rc_carry = 1; + move16(); + } + } + + hPVQ->rc_low = val; + move32(); + + IF( GT_16( bits, sub( hPVQ->rc_tot_bits, hPVQ->rc_num_bits ) ) ) + { + bits = sub( hPVQ->rc_tot_bits, hPVQ->rc_num_bits ); + } + + hPVQ->rc_num_bits = add( hPVQ->rc_num_bits, bits ); + move16(); + FOR( ; bits > 0; bits -= 8 ) + { + rc_enc_shift_ivas_fx( hBstr, hPVQ ); + } + bits = add( bits, 8 ); + + IF( hPVQ->rc_carry_count > 0 ) + { + rc_enc_write_ivas_fx( hBstr, add( hPVQ->rc_cache, hPVQ->rc_carry ), 8 ); + + FOR( ; hPVQ->rc_carry_count > 1; hPVQ->rc_carry_count-- ) + { + rc_enc_write_ivas_fx( hBstr, add( hPVQ->rc_carry, 0xff ), 8 ); + } + rc_enc_write_ivas_fx( hBstr, s_and( add( hPVQ->rc_carry, 0xff ), sub( lshl( 1, bits ), 1 ) ), bits ); + } + ELSE + { + rc_enc_write_ivas_fx( hBstr, lshr( add( hPVQ->rc_cache, hPVQ->rc_carry ), sub( 8, bits ) ), bits ); + } + + bits = hPVQ->rc_num_bits; + move16(); + WHILE( LT_16( bits, sub( hPVQ->rc_tot_bits, 16 ) ) ) + { + rc_enc_write_ivas_fx( hBstr, 0, 16 ); + bits = add( bits, 16 ); + } + + bits = sub( hPVQ->rc_tot_bits, bits ); + IF( bits > 0 ) + { + rc_enc_write_ivas_fx( hBstr, 0, bits ); + } + + return; +} +#endif void rc_enc_finish_fx( BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ @@ -184,7 +312,42 @@ void rc_enc_finish_fx( * * Shift a byte out to bitstream *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void rc_enc_shift_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ +) +{ + test(); + L_sub( 0, 0 ); /* For comparision in if */ + IF( LT_64( hPVQ->rc_low, 0xff000000UL ) || EQ_16( hPVQ->rc_carry, 1 ) ) + { + IF( hPVQ->rc_cache >= 0 ) + { + rc_enc_write_ivas_fx( hBstr, add( hPVQ->rc_cache, hPVQ->rc_carry ), 8 ); + } + + WHILE( hPVQ->rc_carry_count > 0 ) + { + rc_enc_write_ivas_fx( hBstr, s_and( add( hPVQ->rc_carry, 0xff ), 255 ), 8 ); + hPVQ->rc_carry_count = sub( hPVQ->rc_carry_count, 1 ); + move16(); + } + hPVQ->rc_cache = u_extract_l( UL_lshr( hPVQ->rc_low, 24 ) ); + hPVQ->rc_carry = 0; + move16(); + } + ELSE + { + hPVQ->rc_carry_count = add( hPVQ->rc_carry_count, 1 ); + move16(); + } + hPVQ->rc_low = UL_lshl( hPVQ->rc_low, 8 ); + move32(); + return; +} +#endif static void rc_enc_shift_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ @@ -223,7 +386,41 @@ static void rc_enc_shift_fx( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void rc_enc_bits_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +) +{ + IF( LE_16( add( rc_get_bits2_fx( hPVQ->rc_num_bits, hPVQ->rc_range ), bits ), hPVQ->rc_tot_bits ) ) + { + hPVQ->rc_num_bits = add( hPVQ->rc_num_bits, bits ); + move16(); + IF( GT_16( bits, 16 ) ) + { + push_indice( hBstr, sub( IND_RC_END, hPVQ->rc_offset ), u_extract_l( UL_lshr( value, 16 ) ), sub( bits, 16 ) ); + hPVQ->rc_offset = add( hPVQ->rc_offset, 1 ); + move16(); + push_indice( hBstr, sub( IND_RC_END, hPVQ->rc_offset ), u_extract_l( UL_and( value, 0x0000ffff ) ), 16 ); + hPVQ->rc_offset = add( hPVQ->rc_offset, 1 ); + move16(); + } + ELSE + { + push_indice( hBstr, sub( IND_RC_END, hPVQ->rc_offset ), u_extract_l( value ), bits ); + hPVQ->rc_offset = add( hPVQ->rc_offset, 1 ); + move16(); + } + } + ELSE + { + } + return; +} +#endif void rc_enc_bits_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -260,7 +457,32 @@ void rc_enc_bits_fx( * * Encode with uniform distribution *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void rc_enc_uniform_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +) +{ + Word16 n; + + n = sub( 32, norm_ul( UL_subNsD( tot, 1 ) ) ); + IF( LE_16( n, 8 ) ) + { + rc_encode_ivas_fx( hBstr, hPVQ, value, 1, tot ); + } + ELSE + { + n = sub( n, 8 ); + rc_encode_ivas_fx( hBstr, hPVQ, UL_lshr( value, n ), 1, UL_addNsD( UL_lshr( tot, n ), 1 ) ); + rc_enc_bits_ivas_fx( hBstr, hPVQ, UL_and( value, UL_subNsD( UL_lshl( 1, n ), 1 ) ), n ); + } + + return; +} +#endif void rc_enc_uniform_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ @@ -291,7 +513,18 @@ void rc_enc_uniform_fx( * * Write a byte to bitstream *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void rc_enc_write_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 byte, /* i : Byte to write */ + Word16 bits /* i : Number of bits */ +) +{ + push_indice( hBstr, IND_RC_START, byte, bits ); + return; +} +#endif static void rc_enc_write_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ Word16 byte, /* i : Byte to write */ diff --git a/lib_enc/rom_enc.c b/lib_enc/rom_enc.c index 49ea00a498f97a80d156fce03a163f6dae007ba0..c8fe848f5fd95f8118e0d1abccd2f5db3168cbea 100644 --- a/lib_enc/rom_enc.c +++ b/lib_enc/rom_enc.c @@ -1671,7 +1671,55 @@ const float SF_8k[N_FEATURES*2] = 0.0598f, 0.8967f, 0.0631f, 0 }; - +#ifdef IVAS_FLOAT_FIXED +const Word32 thren_pg_fx[44] = +{//Q14 + 1969251200, + 1655936256, + 1392470912, + 1170923776, + 984625600, + 827968128, + 696235456, + 585461888, + 492312800, + 413984064, + 319225344, + 225726416, + 159612672, + 112863208, + 79806336, + 56431604, + 39903168, + 28215802, + 19951584, + 14107901, + 9975792, + 7053950, + 4987896, + 3526975, + 2493948, + 1763487, + 1246974, + 881743, + 623487, + 440871, + 311743, + 220435, + 155871, + 110217, + 77935, + 55108, + 38967, + 27554, + 19483, + 13777, + 9741, + 6888, + 4870, + 3444, +}; +#endif /* searching thresholds for quantization of peak gains */ const float thren_pg[44] = diff --git a/lib_enc/sig_clas_fx.c b/lib_enc/sig_clas_fx.c index 36d1c5052d0b7eb51c848c088d8f91e7f4b851e9..96d244783f393001528c73c2ebe3d1345d030ab2 100644 --- a/lib_enc/sig_clas_fx.c +++ b/lib_enc/sig_clas_fx.c @@ -315,7 +315,7 @@ void select_TC_fx( * Select TC coder type for appropriate frames which is in general VOICED_TRANSITION, * VOICED_CLAS or ONSET frames following UNVOICED_CLAS frames *---------------------------------------------------------------------*/ - + test(); IF( localVAD != 0 && GE_16( tc_cnt, 1 ) ) { IF( EQ_16( tc_cnt, 1 ) ) diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 43921ea1a9ea5906ccc3353711d4278df8f0185e..e008f1dd8c7d2c96c2073a2cf51d656b310877de 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -493,6 +493,7 @@ typedef struct td_cng_enc_structure int16_t shb_cng_ini_cnt; int16_t last_SID_bwidth; int16_t shb_NO_DATA_cnt; + Word16 CNG_att_fx; } TD_CNG_ENC_DATA, *TD_CNG_ENC_HANDLE;