From a88b495c34a6c0c9d060fa8257de4c1e2b49b65c Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 24 Jul 2024 21:52:52 +0530 Subject: [PATCH 1/2] Encoder functions converted to fixed point [x] Converted apply_MCT_enc and its sub-functions in ivas_mct_enc_mct.c [x] Removed redundant flags from TCX_ENC_DATA [x] igf_enc.c functions converted to fixed point [x] Encoder related functions in lsf_tools converted to fixed point --- lib_com/bitstream.c | 51 +- lib_com/cnst.h | 2 + lib_com/codec_tcx_common_flt.c | 2 +- lib_com/enh64.c | 2 +- lib_com/enh64.h | 2 - lib_com/ivas_prot.h | 23 +- lib_com/ivas_prot_fx.h | 30 + lib_com/lsf_tools.c | 52 ++ lib_com/prot.h | 80 +- lib_com/prot_fx.h | 40 + lib_com/tools.c | 70 +- lib_enc/arith_coder_enc.c | 30 +- lib_enc/arith_coder_enc_fx.c | 2 +- lib_enc/bw_detect_fx.c | 56 +- lib_enc/cod_tcx.c | 6 +- lib_enc/cod_tcx_fx.c | 18 +- lib_enc/core_enc_2div_fx.c | 8 +- lib_enc/core_enc_init.c | 7 +- lib_enc/core_enc_init_fx.c | 2 +- lib_enc/core_enc_ol_fx.c | 4 +- lib_enc/core_enc_reconf.c | 4 +- lib_enc/core_enc_reconf_fx.c | 4 +- lib_enc/ext_sig_ana_fx.c | 4 +- lib_enc/fd_cng_enc.c | 29 +- lib_enc/igf_enc.c | 970 ++++++++++++++++++++++- lib_enc/igf_enc_fx.c | 28 +- lib_enc/init_enc.c | 5 + lib_enc/ivas_mct_core_enc.c | 538 ++++++++++++- lib_enc/ivas_mct_enc.c | 162 +++- lib_enc/ivas_mct_enc_mct.c | 1124 ++++++++++++++++++++++++--- lib_enc/ivas_stat_enc.h | 8 + lib_enc/ivas_stereo_mdct_core_enc.c | 39 +- lib_enc/ivas_stereo_switching_enc.c | 6 + lib_enc/prot_fx_enc.h | 18 +- lib_enc/stat_enc.h | 20 +- lib_enc/tcx_utils_enc.c | 105 ++- lib_enc/tcx_utils_enc_fx.c | 2 +- 37 files changed, 3303 insertions(+), 250 deletions(-) diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index 9f9159a34..975dd3293 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -1571,6 +1571,8 @@ ivas_error push_indice( /* updates */ hBstr->nb_ind_tot = add( hBstr->nb_ind_tot, 1 ); hBstr->nb_bits_tot = add( hBstr->nb_bits_tot, nb_bits ); + move16(); + move16(); return error; } @@ -1632,7 +1634,54 @@ ivas_error push_indice( * * Push a new indice into the buffer at the next position *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error push_next_indice( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +) +{ + Word16 prev_id; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + /* check the limits of the list of indices */ + IF( ( error = check_ind_list_limits( hBstr ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* get the id of the previous indice -> it will be re-used */ + IF( hBstr->nb_ind_tot > 0 ) + { + prev_id = hBstr->ind_list[hBstr->nb_ind_tot - 1].id; + } + ELSE + { + prev_id = 0; + } + move16(); + + /* store the values in the list */ + hBstr->ind_list[hBstr->nb_ind_tot].id = prev_id; + hBstr->ind_list[hBstr->nb_ind_tot].value = value; + hBstr->ind_list[hBstr->nb_ind_tot].nb_bits = nb_bits; + move16(); + move16(); + move16(); + + /* updates */ + hBstr->nb_ind_tot = add( hBstr->nb_ind_tot, 1 ); + hBstr->nb_bits_tot = add( hBstr->nb_bits_tot, nb_bits ); + move16(); + move16(); + + return error; +} +#else ivas_error push_next_indice( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ uint16_t value, /* i : value of the quantized indice */ @@ -1672,7 +1721,7 @@ ivas_error push_next_indice( return error; } - +#endif /*-------------------------------------------------------------------* * push_next_bits() diff --git a/lib_com/cnst.h b/lib_com/cnst.h index f1ce84dde..53b1d4723 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -156,6 +156,8 @@ #define RANDOM_INITSEED 21845 /* Seed for random generators */ #ifndef FLT_MIN #define FLT_MIN ( 1.175494351e-38F ) +#define FLT_MIN_10_EXP (-37) // min decimal exponent +#define FLT_MIN_EXP (-125) // min binary exponent #endif #ifndef FLT_MAX #define FLT_MAX ( 3.402823466e+38F ) diff --git a/lib_com/codec_tcx_common_flt.c b/lib_com/codec_tcx_common_flt.c index 12e7d8099..a9314e871 100644 --- a/lib_com/codec_tcx_common_flt.c +++ b/lib_com/codec_tcx_common_flt.c @@ -145,7 +145,7 @@ void tcxInvertWindowGrouping_flt( float xn_buf[], float spectrum[], const int16_t L_frame, - const int16_t fUseTns, + const int8_t fUseTns, const int16_t last_core, const int16_t index, const int16_t frame_cnt, diff --git a/lib_com/enh64.c b/lib_com/enh64.c index 66068baba..b59a9ef6c 100644 --- a/lib_com/enh64.c +++ b/lib_com/enh64.c @@ -1062,7 +1062,6 @@ Word64 W_msu_16_16( Word64 L64_var1, Word16 var2, Word16 var3 ) return L64_var_out; } -/* Below BASOP is not part of STL 2023 library, might be proposed in next update */ /*________________________________________________________________________________________________ | | | Function Name : W_mac_32_32 | @@ -1112,6 +1111,7 @@ Word64 W_mac_32_32( Word64 L64_var1, Word32 L_var2, Word32 L_var3 ) return L64_var_out; } + /*___________________________________________________________________________ | | | Function Name : W_shl_sat_l | diff --git a/lib_com/enh64.h b/lib_com/enh64.h index 8abfd0e80..efc58e83e 100644 --- a/lib_com/enh64.h +++ b/lib_com/enh64.h @@ -36,8 +36,6 @@ Word64 W_msu0_16_16( Word64 L64_acc, Word16 var1, Word16 var2 ); Word64 W_mult_16_16( Word16 var1, Word16 var2 ); Word64 W_mac_16_16( Word64 L64_acc, Word16 var1, Word16 var2 ); Word64 W_msu_16_16( Word64 L64_acc, Word16 var1, Word16 var2 ); - -/* BASOP W_mac_32_32 is not part of STL 2023 library, might be proposed in next update */ Word64 W_mac_32_32( Word64 L64_acc, Word32 var1, Word32 var2 ); Word64 W_deposit32_l( Word32 L_var1 ); diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 5c0c6a91f..80cdef0de 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -45,6 +45,10 @@ #include "ivas_stat_com.h" #include "ivas_error_utils.h" +#ifdef IVAS_FLOAT_FIXED +#define IVAS_FLOAT_FIXED_TO_BE_REMOVED +#endif // IVAS_FLOAT_FIXED + /* clang-format off */ /*----------------------------------------------------------------------------------* @@ -3278,7 +3282,7 @@ void ComputeSpectrumNoiseMeasure( const int16_t L_frame, const int16_t startLine, const int16_t resetMemory, - int16_t *noiseFlags, + int8_t *noiseFlags, const int16_t lowpassLine ); @@ -3962,6 +3966,23 @@ void getChannelEnergies( float nrg[MCT_MAX_CHANNELS], /* o : energies */ const int16_t nchan /* i : number of channels */ ); +#ifdef IVAS_FLOAT_FIXED +void mctStereoIGF_enc_fx( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ + Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + float *orig_spectrum[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ + float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ +); +#endif // IVAS_FLOAT_FIXED void mctStereoIGF_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 9ea7a8264..8ed4fd451 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -2516,6 +2516,36 @@ void stereo_coder_tcx_fx( Word32 *inv_mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ const Word16 mct_on, /* i : flag mct block (1) or stereo (0) */ Word16 q_spec ); + +// bw_detect_fx.c +Word16 set_bw_mct_fx( + CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ + const Word16 nCPE /* i : number of CPEs */ +); + + +// ivas_mct_enc_mct.c +void write_mct_bitstream_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + const Word16 nchan /* i : number of channels */ +); + +void getChannelEnergies_fx( + Encoder_State **sts, /* i/o: Encoder state structure */ + Word32 nrg[MCT_MAX_CHANNELS], /* o : buffer with energies for each channel */ + Word16 nrg_e[MCT_MAX_CHANNELS], /* o : exponents of energies for each channel */ + const Word16 nchan /* i : number of channels */ +); + +void apply_MCT_enc_fx( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ + Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ + Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ + const Word16 nchan /* i : number of channels */ +); #endif void ivas_spar_config_fx( diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index ddce7c199..f13362be5 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -2828,6 +2828,58 @@ void extend_dctN_input( return; } +#ifdef IVAS_FLOAT_FIXED +void extend_dctN_input_fx( + const Word32 *input, /* i : input in fdcng domain -> Q */ + const Word32 *dct_input, /* i : input in dctN(fdcng) domain -> Q */ + const Word16 in_dim, /* i : in_dim == N */ + Word32 *ext_sig, /* o : extended output in fdcng domain Q */ + const Word16 out_dim, /* i : output total dim */ + Word32 *matrix, /* i : idct synthesis matrix N rows, n_cols columns -> Q31*/ + const Word16 n_cols, /* i : number of columns == DCT truncation length */ + const DCTTYPE dcttype /* i : matrix operation type */ +) +{ + Word16 i, j, i_rev; + const Word32( *ptr )[FDCNG_VQ_DCT_MAXTRUNC] = (void *) matrix; + + /* stored format is an IDCT_Nx(FDCNG_VQ_DCT_MAXTRUNC) matrix */ + assert( in_dim < FDCNG_VQ_MAX_LEN ); + assert( out_dim <= FDCNG_VQ_MAX_LEN ); + assert( out_dim > in_dim ); + assert( n_cols == FDCNG_VQ_DCT_MAXTRUNC ); /* for *ptr[MAX_TRUNC] adressing*/ + assert( ( dcttype & 1 ) != 0 ); /* idct tables always in use for this basis vector extension */ + + Copy32( input, ext_sig, in_dim ); /* copy initial part, i.e. only last/tail parts are extended */ + set32_fx( &( ext_sig[in_dim] ), 0, out_dim - in_dim ); + + i_rev = in_dim; /*ptr init*/ + move16(); + + FOR( i = in_dim; i < out_dim; i++ ) + { /* for each extension sample */ + /* i = 21 22 23; + i_rev = 20 19 18; for odd dctII reflect basis vector + */ + i_rev = sub( i_rev, 1 ); + + FOR( j = 0; j < n_cols; j++ ) /* for each available DCT coeff */ + { + /* DCTcoeff * reflected basis vector */ +#define WMC_TOOL_SKIP + /* pure ptr MAC operations */ + ext_sig[i] = L_add( ext_sig[i], Mpy_32_32( dct_input[j], ptr[i_rev][j] ) ); /* sum up scaled and extended basis vector */ + move32(); + // Q31 + Q - Q31 -> Q + MAC( 1 ); +#undef WMC_TOOL_SKIP + } + } + + return; +} + +#endif /*-------------------------------------------------------------------* * create_IDCT_N_Matrix() diff --git a/lib_com/prot.h b/lib_com/prot.h index 1dbf548a6..a234bdbd9 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -475,17 +475,33 @@ ivas_error push_indice( int16_t nb_bits /* i : number of bits used to quantize the indice */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error push_next_indice( + BSTR_ENC_HANDLE hBstr, + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +); +#else ivas_error push_next_indice( BSTR_ENC_HANDLE hBstr, uint16_t value, /* i : value of the quantized indice */ int16_t nb_bits /* i : number of bits used to quantize the indice */ ); +#endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +ivas_error push_next_bits( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const UWord16 bits[], /* i : bit buffer to pack, sequence of single bits */ + const Word16 nb_bits /* i : number of bits to pack */ +); +#else ivas_error push_next_bits( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const uint16_t bits[], /* i : bit buffer to pack, sequence of single bits */ const int16_t nb_bits /* i : number of bits to pack */ ); +#endif // IVAS_FLOAT_FIXED /*! r: maximum number of indices */ int16_t get_ivas_max_num_indices( @@ -7244,7 +7260,7 @@ void TNSAnalysis( TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ const float ltp_gain, /* i : ltp gain */ STnsData *pTnsData, /* o : TNS data */ - int16_t *pfUseTns, /* o : Flag indicating if TNS is used */ + int8_t *pfUseTns, /* o : Flag indicating if TNS is used */ float *predictionGain /* o : TNS prediction gain */ ); @@ -7262,7 +7278,7 @@ void ShapeSpectrum( const int16_t L_frame_glob, /* i : frame length */ int16_t L_spec, /* i : length of the spectrum */ float spectrum[], /* i/o: MDCT spectrum */ - const int16_t fUseTns, /* i : Flag indicating if TNS is used */ + const int8_t fUseTns, /* i : Flag indicating if TNS is used */ Encoder_State *st, /* i/o: encoder state structure */ float *scf /* i : scale factors */ ); @@ -7430,6 +7446,27 @@ void ProcessIGF( const int16_t sp_aud_decision0, /* i : first stage switching decision */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ); +#ifdef IVAS_FLOAT_FIXED +void ProcessStereoIGF_fx( + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, + Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ + int16_t ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ +#if 1 + Word32 *pITFMDCTSpectrum_fx[CPE_CHANNELS][NB_DIV], /* i : MDCT spectrum fir ITF */ + Word32 *pPowerSpectrum_fx[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word32 *pPowerSpectrumMsInv_fx[CPE_CHANNELS][NB_DIV], /* i : inverse power spectrum */ + Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif + float *pITFMDCTSpectrum[CPE_CHANNELS][NB_DIV], /* i : MDCT spectrum fir ITF */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrumMsInv[CPE_CHANNELS][NB_DIV], /* i : inverse power spectrum */ + float *inv_spectrum[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ + const int16_t frameno, /* i : flag indicating index of current subfr. */ + const int16_t sp_aud_decision0, /* i : sp_aud_decision0 */ + const int32_t element_brate, /* i : element bitrate */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ +); +#endif // IVAS_FLOAT_FIXED void ProcessStereoIGF( STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, @@ -7514,12 +7551,12 @@ float SQ_gain_estimate( void tcx_scalar_quantization( - float *x, /* i : input coefficients */ - int16_t *xq, /* o : quantized coefficients */ - const int16_t L_frame, /* i : frame length */ - const float gain, /* i : quantization gain */ - const float offset, /* i : rounding offset (deadzone) */ - int16_t *memQuantZeros, /* o : coefficients set to 0 */ + float *x, /* i : input coefficients */ + int16_t *xq, /* o : quantized coefficients */ + const int16_t L_frame, /* i : frame length */ + const float gain, /* i : quantization gain */ + const float offset, /* i : rounding offset (deadzone) */ + int8_t *memQuantZeros, /* o : coefficients set to 0 */ const int16_t tcxonly ); int16_t tcx_scalar_quantization_rateloop( @@ -7528,7 +7565,7 @@ int16_t tcx_scalar_quantization_rateloop( const int16_t L_frame, /* i : frame length */ float *gain, /* i/o: quantization gain */ float offset, /* i : rounding offset (deadzone) */ - int16_t *memQuantZeros, /* o : coefficients set to 0 */ + int8_t *memQuantZeros, /* o : coefficients set to 0 */ int16_t *lastnz_out, /* i/o: last nonzero coeff index */ const int16_t target, /* i : target number of bits */ int16_t *nEncoded, /* o : number of encoded coeff */ @@ -9483,7 +9520,7 @@ void tcxInvertWindowGrouping_flt( float xn_buf[], float spectrum[], const int16_t L_frame, - const int16_t fUseTns, + const int8_t fUseTns, const int16_t last_core, const int16_t index, const int16_t frame_cnt, @@ -9964,10 +10001,31 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - const int16_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ const int16_t sp_aud_decision0, /* i : first stage switching decision */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ); +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyStereo_fx( + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo encoder structure */ + int16_t ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ + const IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS], /* i : instance handle of IGF Encoder */ + const int16_t igfGridIdx, /* i : IGF grid index */ + Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ + Word32 *pPowerSpectrum_fx[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word32 *pPowerSpectrumMsInv_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse power spectrum */ + Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#if 1 + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrumMsInv[CPE_CHANNELS][NB_DIV], /* i/o: inverse power spectrum */ + float *inv_spectrum[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif + const int16_t frameno, /* i : flag indicating index of current subfr. */ + const int16_t sp_aud_decision0, /* i : sp_aud_decision0 */ + const int32_t element_brate, /* i : element bitrate */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ +); +#endif // IVAS_FLOAT_FIXED void IGFEncApplyStereo( STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo encoder structure */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index b3e016846..b51d561b0 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -5650,6 +5650,15 @@ Word32 dotp_fixed_o( const Word16 n, /* i : vector length */ const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ Word16 *res_q ); + +Word32 dotp_fixed_32( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ + Word16 *res_q /*stores resultant Q*/ +); + #ifdef IVAS_FLOAT_FIXED Word32 dotp_fixed_guarded( const Word32 x[], /* i : vector x[] */ @@ -9877,6 +9886,17 @@ void dctT2_N_apply_matrix_fx( const DCTTYPE dcttype /* i : matrix operation type */ ); +void extend_dctN_input_fx( + const Word32 *input, /* i : input in fdcng domain */ + const Word32 *dct_input, /* i : input in dctN(fdcng) domain */ + const Word16 in_dim, /* i : in_dim == N */ + Word32 *ext_sig, /* o : extended output in fdcng domain */ + const Word16 out_dim, /* i : output total dim */ + Word32 *matrix, /* i : idct synthesis matrix N rows, n_cols columns */ + const Word16 n_cols, /* i : number of columns == DCT truncation length */ + const DCTTYPE dcttype /* i : matrix operation type */ +); + Word32 sum2_f_32_fx( const Word32 *vec, /* i : input vector */ const int16_t lvec, /* i : length of input vector */ @@ -10080,4 +10100,24 @@ void swb_pre_proc_ivas_fx( float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer */ CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); + +// tools.c +Word32 sum2_f_32_fx( /* o : Q(2x - 31 - gb) */ + const Word32 *vec, /* i : input vector, Qx */ + const Word16 lvec, /* i : length of input vector */ + Word16 gb /* i : guard bits */ +); + +Word32 sum2_32_exp_fx( + const Word32 *vec, /* i : input vector, Qx */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +); + +Word32 sum2_32_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 *e ); + #endif diff --git a/lib_com/tools.c b/lib_com/tools.c index a2912019d..dc2ee58fb 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -231,10 +231,41 @@ float sum2_f( } #ifdef IVAS_FLOAT_FIXED -Word32 sum2_f_32_fx( - const Word32 *vec, /* i : input vector */ - const Word16 lvec, /* i : length of input vector */ - Word16 gb ) +Word32 sum2_32_exp_fx( + const Word32 *vec, /* i : input vector, Qx */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +) +{ + Word16 i, s; + Word64 W_tmp; + + W_tmp = 0; + Word64 var_a = 0; + move64(); + move64(); + FOR( i = 0; i < lvec; i++ ) + { + var_a = W_mult0_32_32( vec[i], vec[i] ); // 2x + W_tmp = W_add( W_tmp, W_shr( var_a, gb ) ); // 2x-gb + } + + s = W_norm( W_tmp ); + W_tmp = W_shl( W_tmp, s ); // 2x - gb + s + + //*exp = 31 - (2*(31 - *exp) - gb + s) + 32; + *exp = add( sub( add( shl( *exp, 1 ), gb ), s ), 1 ); + move16(); + + return W_extract_h( W_tmp ); +} + +Word32 sum2_f_32_fx( /* o : Q(2x - 31 - gb) */ + const Word32 *vec, /* i : input vector, Qx */ + const Word16 lvec, /* i : length of input vector */ + Word16 gb /* i : guard bits */ +) { Word16 i; Word32 tmp; @@ -1174,6 +1205,37 @@ Word32 dotp_fixed_o( } return W_extract_l( suma ); } + +Word32 dotp_fixed_32( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ + Word16 *res_q /*stores resultant Q*/ +) +{ + Word16 i; + Word64 suma; /*resultant q= q(x)+q(y)-9-x such that q<=31*/ + + suma = W_shr( W_mult_32_32( x[0], y[0] ), log_len ); + + FOR( i = 1; i < n; i++ ) + { + suma = W_add( suma, W_shr( W_mult_32_32( x[i], y[i] ), log_len ) ); + } + *res_q = add( *res_q, add( sub( *res_q, log_len ), 1 ) ); + move16(); + test(); + test(); + WHILE( GT_64( suma, MAX_32 ) || LT_64( suma, MIN_32 ) || GT_16( *res_q, 31 ) ) + { + suma = W_shr( suma, 1 ); + *res_q = sub( *res_q, 1 ); + move16(); + } + return W_extract_l( suma ); +} + /*---------------------------------------------------------------------* * inv_sqrt() * diff --git a/lib_enc/arith_coder_enc.c b/lib_enc/arith_coder_enc.c index f531d9ed0..3b5c8dea9 100644 --- a/lib_enc/arith_coder_enc.c +++ b/lib_enc/arith_coder_enc.c @@ -248,11 +248,11 @@ static float tcx_arith_find_max_scale( /*! r: index of highest freq. nonzero line (-1 if all zeros) */ static int16_t tcx_arith_find_kMax( - const float abs_spectrum[], /* i : absolute MDCT coefficients */ - const int16_t L_frame, /* i : number of spectral lines */ - const float scale, /* i : scalar quantizer scale */ - const float deadzone, /* i : deadzone (0.5f = no deadzone) */ - const int16_t deadzone_flags[] /* i : line-wise deadzone control */ + const float abs_spectrum[], /* i : absolute MDCT coefficients */ + const int16_t L_frame, /* i : number of spectral lines */ + const float scale, /* i : scalar quantizer scale */ + const float deadzone, /* i : deadzone (0.5f = no deadzone) */ + const int8_t deadzone_flags[] /* i : line-wise deadzone control */ ) { int16_t kMax; @@ -275,15 +275,15 @@ static int16_t tcx_arith_find_kMax( /*! r: best scale */ static float tcx_arith_rateloop( - const float abs_spectrum[], /* i : absolute MDCT coefficients */ - const int16_t L_frame, /* i : number of spectral lines */ - const Word16 envelope[], /* i : scaled envelope (Q15-e) */ - const Word16 envelope_e, /* i : scaled envelope exponent (Q0) */ - const Word16 exps[], /* i : expfp_evs(-(integer)envelope[]/2) */ - const int16_t target_bits, /* i : target bit budget */ - const float deadzone, /* i : deadzone (0.5f = no deadzone) */ - const int16_t deadzone_flags[], /* i : line-wise deadzone control */ - float *target_bits_fac /* i/o: scale estimator compensation */ + const float abs_spectrum[], /* i : absolute MDCT coefficients */ + const int16_t L_frame, /* i : number of spectral lines */ + const Word16 envelope[], /* i : scaled envelope (Q15-e) */ + const Word16 envelope_e, /* i : scaled envelope exponent (Q0) */ + const Word16 exps[], /* i : expfp_evs(-(integer)envelope[]/2) */ + const int16_t target_bits, /* i : target bit budget */ + const float deadzone, /* i : deadzone (0.5f = no deadzone) */ + const int8_t deadzone_flags[], /* i : line-wise deadzone control */ + float *target_bits_fac /* i/o: scale estimator compensation */ ) { int16_t k, idx, kMax, q; @@ -594,7 +594,7 @@ void tcx_arith_encode_envelope( float scale; int16_t k, kMax; float deadzone; - const int16_t *deadzone_flags; + const int8_t *deadzone_flags; float gamma_w, gamma_uw; int16_t hm_bits; diff --git a/lib_enc/arith_coder_enc_fx.c b/lib_enc/arith_coder_enc_fx.c index ce9f146d8..6b137f31e 100644 --- a/lib_enc/arith_coder_enc_fx.c +++ b/lib_enc/arith_coder_enc_fx.c @@ -715,7 +715,7 @@ void tcx_arith_encode_envelope_fx( hTcxCfg = st->hTcxCfg; deadzone = hTcxCfg->sq_rounding; move16(); - deadzone_flags = hTcxEnc->memQuantZeros_fx; + deadzone_flags = hTcxEnc->memQuantZeros; *signaling_bits = 0; move16(); diff --git a/lib_enc/bw_detect_fx.c b/lib_enc/bw_detect_fx.c index 9660075e6..3cc6784de 100644 --- a/lib_enc/bw_detect_fx.c +++ b/lib_enc/bw_detect_fx.c @@ -5,13 +5,13 @@ #include #include "options.h" /* Compilation switches */ #include "cnst.h" /* Common constants */ -//#include "prot_fx.h" /* Function prototypes */ #include "rom_enc.h" /* Encoder static table prototypes */ #include "rom_com.h" #include "basop_util.h" #include "ivas_cnst.h" -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ /*-------------------------------------------------------------------* * Local constants @@ -1067,7 +1067,7 @@ void set_bw_stereo( return; } - +#endif /*-------------------------------------------------------------------* * set_bw_mct() * @@ -1075,54 +1075,58 @@ void set_bw_stereo( *-------------------------------------------------------------------*/ /*! r: flag indicating whether the coded BW has changed */ -int16_t set_bw_mct( +Word16 set_bw_mct_fx( CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ - const int16_t nCPE /* i : number of CPEs */ + const Word16 nCPE /* i : number of CPEs */ ) { - Encoder_State *sts[MCT_MAX_CHANNELS]; - int16_t ch, cpe_id; - int16_t mct_bwidth, last_mct_bwidth, bw_changed; + Encoder_State *st; + Word16 ch, cpe_id; + Word16 mct_bwidth, last_mct_bwidth, bw_changed; mct_bwidth = WB; /* minimum coded audio band-width */ last_mct_bwidth = hCPE[0]->hCoreCoder[0]->last_bwidth; /* supposes that LFE is not in the first channel */ + move16(); + move16(); - for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) + FOR( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - sts[ch] = hCPE[cpe_id]->hCoreCoder[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + st = hCPE[cpe_id]->hCoreCoder[ch]; + IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; } - mct_bwidth = max( mct_bwidth, sts[ch]->input_bwidth ); + mct_bwidth = s_max( mct_bwidth, st->input_bwidth ); } } - for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) + + FOR( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { - if ( hCPE[cpe_id]->element_brate > BWD_MAX_BRATE_WIDER_BW_MDCT ) + IF( GT_32( hCPE[cpe_id]->element_brate, BWD_MAX_BRATE_WIDER_BW_MDCT ) ) { - mct_bwidth = max( mct_bwidth, hCPE[cpe_id]->hCoreCoder[0]->max_bwidth ); + mct_bwidth = s_max( mct_bwidth, hCPE[cpe_id]->hCoreCoder[0]->max_bwidth ); } } + bw_changed = 0; - if ( mct_bwidth != last_mct_bwidth ) + move16(); + IF( NE_16( mct_bwidth, last_mct_bwidth ) ) { bw_changed = 1; + move16(); - for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) + FOR( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - sts[ch] = hCPE[cpe_id]->hCoreCoder[ch]; - sts[ch]->bwidth = mct_bwidth; + st = hCPE[cpe_id]->hCoreCoder[ch]; + st->bwidth = mct_bwidth; + move16(); } } } - return bw_changed; } - -#endif diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c index 96acb8f40..77da3cd29 100644 --- a/lib_enc/cod_tcx.c +++ b/lib_enc/cod_tcx.c @@ -580,7 +580,7 @@ void TNSAnalysis( TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ const float ltp_gain, /* i : ltp gain */ STnsData *pTnsData, /* o : TNS data */ - int16_t *pfUseTns, /* o : Flag indicating if TNS is used */ + int8_t *pfUseTns, /* o : Flag indicating if TNS is used */ float *predictionGain /* o : TNS prediction gain */ ) { @@ -615,7 +615,7 @@ void TNSAnalysis( } } - *pfUseTns = DetectTnsFilt( hTcxCfg->pCurrentTnsConfig, spectrum, hTranDet, transform_type != TCX_20, ltp_gain, pTnsData, predictionGain ); + *pfUseTns = (Word8) DetectTnsFilt( hTcxCfg->pCurrentTnsConfig, spectrum, hTranDet, transform_type != TCX_20, ltp_gain, pTnsData, predictionGain ); /* If TNS should be used then get the residual after applying it inplace in the spectrum */ @@ -661,7 +661,7 @@ void ShapeSpectrum( const int16_t L_frame_glob, /* i : frame length */ int16_t L_spec, /* i : length of the spectrum */ float spectrum[], /* i/o: MDCT spectrum */ - const int16_t fUseTns, /* i : Flag indicating if TNS is used */ + const int8_t fUseTns, /* i : Flag indicating if TNS is used */ Encoder_State *st, /* i/o: encoder state structure */ float *scf /* i : scale factors */ ) diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index 0b74d6de4..0a747b477 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -1406,7 +1406,7 @@ void QuantizeSpectrum_fx( L_spec, sqGain, sqGain_e, hTcxCfg->sq_rounding, - hTcxEnc->memQuantZeros_fx, + hTcxEnc->memQuantZeros, tcxonly ); /* Estimate original bitrate */ @@ -1500,7 +1500,7 @@ void QuantizeSpectrum_fx( L_spec, sqGain, sqGain_e, hTcxCfg->sq_rounding, - hTcxEnc->memQuantZeros_fx, + hTcxEnc->memQuantZeros, tcxonly ); /* Estimate bitrate */ @@ -1566,7 +1566,7 @@ void QuantizeSpectrum_fx( L_spec, &sqGain, &sqGain_e, hTcxCfg->sq_rounding, - hTcxEnc->memQuantZeros_fx, + hTcxEnc->memQuantZeros, prm_lastnz, /* lastnz */ sqTargetBits, &nEncoded, @@ -1698,7 +1698,7 @@ void QuantizeSpectrum_fx( L_spec, sqGain, sqGain_e, hTcxCfg->sq_rounding, - hTcxEnc->memQuantZeros_fx, + hTcxEnc->memQuantZeros, tcxonly ); move16(); @@ -2885,25 +2885,25 @@ void coder_tcx_fx( test(); SetTnsConfig( hTcxCfg, sub( L_frame_glob, st->L_frame ) == 0, st->last_core == 0 ); - TNSAnalysis_fx( hTcxCfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns_fx, &st->hIGFEnc->tns_predictionGain ); + TNSAnalysis_fx( hTcxCfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns, &st->hIGFEnc->tns_predictionGain ); } ELSE { - hTcxEnc->fUseTns_fx[0] = hTcxEnc->fUseTns_fx[1] = 0; + hTcxEnc->fUseTns[0] = hTcxEnc->fUseTns[1] = 0; move16(); move16(); } IF( st->igf ) { - ProcessIGF_fx( st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns_fx[0], ( st->last_core == ACELP_CORE ), 0 ); + ProcessIGF_fx( st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns[0], ( st->last_core == ACELP_CORE ), 0 ); } ShapeSpectrum_fx( hTcxCfg, A, gainlpc, gainlpc_e, L_frame_glob, L_spec, spectrum, - hTcxEnc->fUseTns_fx[0], + hTcxEnc->fUseTns[0], st ); if ( st->igf ) { @@ -2926,7 +2926,7 @@ void coder_tcx_fx( tcxonly, spectrum, spectrum_e, hTcxEnc->tnsData, - hTcxEnc->fUseTns_fx[0], + hTcxEnc->fUseTns[0], tnsSize, prm, n, diff --git a/lib_enc/core_enc_2div_fx.c b/lib_enc/core_enc_2div_fx.c index f0527f0eb..151561b09 100644 --- a/lib_enc/core_enc_2div_fx.c +++ b/lib_enc/core_enc_2div_fx.c @@ -178,7 +178,7 @@ void core_encode_twodiv_fx( shr( st->L_frame, 1 ), shr( st->hTcxCfg->tcx_coded_lines, 1 ), spectrum[n], - hTcxEnc->fUseTns_fx[n], + hTcxEnc->fUseTns[n], st ); st->last_core = st->core; @@ -238,7 +238,7 @@ void core_encode_twodiv_fx( spectrum[n], &spectrum_e[n], hTcxEnc->tnsData + n, - hTcxEnc->fUseTns_fx[n], + hTcxEnc->fUseTns[n], tnsSize[n], param_core + n * NPRM_DIV, n, @@ -274,7 +274,7 @@ void core_encode_twodiv_fx( st->L_frame, st->hTcxCfg->tcx_coded_lines, spectrum[0], - hTcxEnc->fUseTns_fx[0], + hTcxEnc->fUseTns[0], st ); /*_DIFF_FLOAT_FIX_ -> The line below is present in float */ @@ -314,7 +314,7 @@ void core_encode_twodiv_fx( spectrum[0], &spectrum_e[0], &hTcxEnc->tnsData[0], - hTcxEnc->fUseTns_fx[0], + hTcxEnc->fUseTns[0], tnsSize[0], param_core, 0, diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index e84ed8f3a..855ff8e89 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -255,6 +255,11 @@ static void init_tcx( TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ +#if 1 + hTcxEnc->spectrum_fx[0] = hTcxEnc->spectrum_long_fx; + hTcxEnc->spectrum_fx[1] = hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#endif + hTcxEnc->spectrum[0] = hTcxEnc->spectrum_long; hTcxEnc->spectrum[1] = hTcxEnc->spectrum_long + N_TCX10_MAX; #ifdef IVAS_FLOAT_FIXED @@ -271,7 +276,7 @@ static void init_tcx( hTcxEnc->noiseLevelMemory_cnt = 0; set_f( hTcxEnc->ltpGainMemory, 0.0f, N_LTP_GAIN_MEMS ); - set_s( hTcxEnc->memQuantZeros, 0, L_FRAME_PLUS ); + set_c( hTcxEnc->memQuantZeros, 0, L_FRAME_PLUS ); /* TCX-LTP */ hTcxEnc->tcxltp = getTcxLtp( st->sr_core ); diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index b3b305673..dba3ce835 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -340,7 +340,7 @@ static void init_tcx_fx( FOR( i = 0; i < L_FRAME_PLUS; i++ ) { - hTcxEnc->memQuantZeros_fx[i] = 0; + hTcxEnc->memQuantZeros[i] = 0; move16(); } diff --git a/lib_enc/core_enc_ol_fx.c b/lib_enc/core_enc_ol_fx.c index 4fe990ccb..9957ccdef 100644 --- a/lib_enc/core_enc_ol_fx.c +++ b/lib_enc/core_enc_ol_fx.c @@ -659,7 +659,7 @@ void core_encode_openloop_fx( && ( EQ_16( hTcxEnc->tcxltp_pitch_int, hRF->rf_tcxltp_pitch_int_past ) ) /*&& (st->tcxltp_pitch_int == st->rf_tcxltp_pitch_int_past)*/ && ( hRF->rf_last_tns_active == 0 ) /*!st->rf_last_tns_active*/ && ( hRF->rf_second_last_tns_active == 0 ) /*!st->rf_second_last_tns_active*/ - && ( ( st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns_fx[0] ) == 0 ) /*!(st->hTcxCfg->fIsTNSAllowed & st->fUseTns[0])*/ + && ( ( st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns[0] ) == 0 ) /*!(st->hTcxCfg->fIsTNSAllowed & st->fUseTns[0])*/ ) { rf_PLC_Mode = 1; @@ -698,7 +698,7 @@ void core_encode_openloop_fx( move16(); hRF->rf_second_last_tns_active = hRF->rf_last_tns_active; move16(); - hRF->rf_last_tns_active = ( st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns_fx[0] ); + hRF->rf_last_tns_active = ( st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns[0] ); move16(); hRF->rf_second_last_core = st->last_core; move16(); diff --git a/lib_enc/core_enc_reconf.c b/lib_enc/core_enc_reconf.c index 7eab3e742..67238f036 100644 --- a/lib_enc/core_enc_reconf.c +++ b/lib_enc/core_enc_reconf.c @@ -223,13 +223,13 @@ void core_coder_reconfig( if ( st->total_brate < ACELP_24k40 && ( ( st->total_brate > last_total_brate ) || ( st->last_codec_mode == MODE1 ) ) ) { /* low-freq memQuantZeros must be reset partially if bitrate increased */ - set_s( hTcxEnc->memQuantZeros, 0, hTcxEnc->nmStartLine ); + set_c( hTcxEnc->memQuantZeros, 0, hTcxEnc->nmStartLine ); } else { if ( st->total_brate >= ACELP_24k40 && st->total_brate <= ACELP_32k && last_total_brate >= ACELP_13k20 && last_total_brate < ACELP_24k40 ) { - set_s( hTcxEnc->memQuantZeros, 0, st->L_frame ); + set_c( hTcxEnc->memQuantZeros, 0, st->L_frame ); } } } diff --git a/lib_enc/core_enc_reconf_fx.c b/lib_enc/core_enc_reconf_fx.c index b66703f88..c4e4b16cd 100644 --- a/lib_enc/core_enc_reconf_fx.c +++ b/lib_enc/core_enc_reconf_fx.c @@ -310,7 +310,7 @@ void core_coder_reconfig_fx( /* low-freq memQuantZeros_fx must be reset partially if bitrate increased */ FOR( i = 0; i < hTcxEnc->nmStartLine; i++ ) { - hTcxEnc->memQuantZeros_fx[i] = 0; + hTcxEnc->memQuantZeros[i] = 0; move16(); } } @@ -318,7 +318,7 @@ void core_coder_reconfig_fx( { FOR( i = 0; i < st->L_frame; i++ ) /* memQuantZeros_fx won't be updated */ { - hTcxEnc->memQuantZeros_fx[i] = 0; + hTcxEnc->memQuantZeros[i] = 0; move16(); } } diff --git a/lib_enc/ext_sig_ana_fx.c b/lib_enc/ext_sig_ana_fx.c index f4c60b16f..e8db91a74 100644 --- a/lib_enc/ext_sig_ana_fx.c +++ b/lib_enc/ext_sig_ana_fx.c @@ -560,7 +560,7 @@ void core_signal_analysis_high_bitrate_fx( TNSAnalysis_fx( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], ( frameno == 0 ) && ( st->last_core == ACELP_CORE ), - spectrum[frameno], &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns_fx[frameno], NULL ); + spectrum[frameno], &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); #ifdef IVAS_CODE IF( st->hTcxCfg->fIsTNSAllowed ) #endif @@ -607,7 +607,7 @@ void core_signal_analysis_high_bitrate_fx( } IF( st->igf ) { - ProcessIGF_fx( st->hIGFEnc, st, spectrum[frameno], &( spectrum_e[frameno] ), powerSpec, &powerSpec_e, transform_type[frameno] == TCX_20, hTcxEnc->fUseTns_fx[frameno], ( st->last_core == ACELP_CORE ), frameno ); + ProcessIGF_fx( st->hIGFEnc, st, spectrum[frameno], &( spectrum_e[frameno] ), powerSpec, &powerSpec_e, transform_type[frameno] == TCX_20, hTcxEnc->fUseTns[frameno], ( st->last_core == ACELP_CORE ), frameno ); } /* Copy memory */ diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index 38803594f..b71282946 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -46,7 +46,7 @@ #include "ivas_prot_fx.h" #include "stat_enc.h" #include "wmc_auto.h" - +#include "ivas_prot_fx.h" /*-------------------------------------------------------------------* * createFdCngEnc() * @@ -522,6 +522,16 @@ void FdCng_encodeSID( N = hFdCngEnc->npartDec; invTrfMatrix = (float *) tmpRAM; /* dynamically filled */ + +#ifdef IVAS_FLOAT_FIXED + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + Word32 v_fx[32]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN]; +#endif + set_zero( v, FDCNG_VQ_MAX_LEN ); /* Convert to LOG */ @@ -559,10 +569,24 @@ void FdCng_encodeSID( { create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /* truncated DCT21 analysis */ + +#ifdef IVAS_FLOAT_FIXED + Word16 Q = 24; + move16(); + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM_fx ) / ( sizeof( Word32 ) ) ); // Q31 +#endif + dctT2_N_apply_matrix( (const float *) v, dct_target, FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); /* truncated IDCT21 extension to 24 bands */ - extend_dctN_input( v, dct_target, N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); +#ifdef IVAS_FLOAT_FIXED + floatToFixed_arr32( v, v_fx, Q, N ); + floatToFixed_arr32( dct_target, dct_target_fx, Q, FDCNG_VQ_DCT_MAXTRUNC ); + extend_dctN_input_fx( v_fx, dct_target_fx, N, tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); + fixedToFloat_arrL( tot_sig_ext_fx, tot_sig_ext, Q, N ); +#else + extend_dctN_input( v, dct_target, N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); +#endif mvr2r( tot_sig_ext, v, FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ } create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); @@ -1321,6 +1345,7 @@ void FdCngEncodeDiracMDCTStereoSID( /* truncated DCT 21 analysis */ dctT2_N_apply_matrix( (const float *) ms_ptr[0], dct_target, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); /* truncated IDCT21 extension to 24 synthesis */ + extend_dctN_input( ms_ptr[0], dct_target, N[0], tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ mvr2r( tot_sig_ext, ms_ptr[0], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 230df0248..b1429313f 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -43,14 +43,37 @@ #include "cnst.h" #include "stat_enc.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#endif // IVAS_FLOAT_FIXED +#define INV_Log2_10_Q15 9864 /*1/log2(10) in Q15*/ +#define INV_Log2_e_Q15 22713 /*1/log2(e) in Q15*/ /*-------------------------------------------------------------------* * IGF_write_bit() * * write single bit to stream *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void IGF_write_bit( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *bitCount, /* i/o: bit counter */ + const Word16 value /* i : value */ +) +{ + IF( hBstr ) + { + push_next_indice( hBstr, value, 1 ); + } + ( *bitCount ) = add( ( *bitCount ), 1 ); + move16(); + + return; +} +#else static void IGF_write_bit( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ int16_t *bitCount, /* i/o: bit counter */ @@ -67,13 +90,36 @@ static void IGF_write_bit( return; } +#endif /*-------------------------------------------------------------------* * IGF_write_bits() * * write bits to stream *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void IGF_write_bits( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *bitCount, /* i/o: bit counter */ + const Word16 value, /* i/o: value */ + Word16 bits /* i : number of bits */ +) +{ + WHILE( bits-- ) + { + IF( s_and( value, shl( 1, bits ) ) == 0 ) + { + IGF_write_bit( hBstr, bitCount, 0 ); + } + ELSE + { + IGF_write_bit( hBstr, bitCount, 1 ); + } + } + return; +} +#else static void IGF_write_bits( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ int16_t *bitCount, /* i/o: bit counter */ @@ -88,6 +134,7 @@ static void IGF_write_bits( return; } +#endif // IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* @@ -97,6 +144,70 @@ static void IGF_write_bits( *-------------------------------------------------------------------*/ /*! r: crest factor */ +#if 0 +#ifdef IVAS_FLOAT_FIXED +static Word16 IGF_getCrest_new_fx( + const Word16 *logSpec, /* i : power spectrum */ + const Word16 start, /* i : start subband index */ + const Word16 stop, /* i : stop subband index */ + Word16 *crest_exp /*Stores the exponent of the result(return value)*/ +) +{ + Word16 i; + Word16 x; + Word32 x_eff; + Word16 x_max; + Word16 exp; + Word16 temp; + Word16 temp_e; + Word16 crest; /*1.0f in Q15*/ + x_eff = 0; + x_max = 0; + exp = 0; + temp = 0; + temp_e; + crest = 32767; /*1.0f in Q15*/ + move32(); + move16(); + move16(); + move16(); + move16(); + + FOR( i = start; i < stop; i++ ) + { + x = logSpec[i]; + move16(); + x_eff = L_add( x_eff, L_mult0( x, x ) ); + + IF( GT_16( x, x_max ) ) + { + x_max = x; + move16(); + } + } + + x_eff = BASOP_Util_Divide3216_Scale( x_eff, sub( stop, start ), &temp_e ); + temp_e = add( temp_e, 16 ); /*exp += 31 - 15 + 16(because x_eff is word32)*/ + temp = Sqrt16( extract_l( x_eff ), &temp_e ); + + IF( x_eff > 0 && x_max > 0 ) + { + temp = BASOP_Util_Divide1616_Scale( x_max, temp, &exp ); + exp = add( exp, sub( 15, temp_e ) ); + IF( exp < 0 ) + { + temp = shl( temp, exp ); + exp = 0; + move16(); + } + crest = s_max( shl_sat( 1, sub( 15, exp ) ), temp ); + } + *crest_exp = exp; + move16(); + return crest; +} +#endif +#endif static float IGF_getCrest_new( const int16_t *logSpec, /* i : power spectrum */ const int16_t start, /* i : start subband index */ @@ -138,6 +249,64 @@ static float IGF_getCrest_new( *-------------------------------------------------------------------*/ /*! r: SFM value */ +/* Q for the returned sfm value is 15 */ +#if 0 +#ifdef IVAS_FLOAT_FIXED +static Word16 IGF_getSFM_new_fx( + const Word32 *powerSpectrum, /* i : power spectrum */ + const Word16 *logSpec, /* i : log of power spectrum */ + const Word16 start, /* i : start subband index */ + const Word16 stop, /* i : stop subband index */ + Word16 e_ps /*Stores exp related to power spectrum*/ +) +{ + Word16 n; + Word16 i; + Word16 num; + Word32 denom; + Word16 numf; + Word32 tmp; + Word16 sfm; + Word16 sfm_e; + Word16 denom_e; + Word16 numf_e; /*stores exponent for numf*/ + Word16 tmp_e; + + num = 0; + denom = 1; + denom_e = 31; + sfm = 1; + move16(); + move32(); + move16(); + move16(); + + FOR( i = start; i < stop; i++ ) + { + tmp = powerSpectrum[i]; + n = logSpec[i /*-start*/]; + move32(); + move16(); + num = add( num, n ); + denom = BASOP_Util_Add_Mant32Exp( tmp, e_ps, denom, denom_e, &denom_e ); + } + + numf = BASOP_Util_Divide1616_Scale( num, sub( stop, start ), &numf_e ); + denom = BASOP_Util_Divide3216_Scale( denom, sub( stop, start ), &tmp_e ); + denom_e = add( add( denom_e, tmp_e ), 1 ); /*denom_e+tmp_e-15 +16(because type of denom is word32)*/ + + IF( denom != 0 ) + { + tmp = BASOP_util_Pow2( L_add( numf, shl( 1, sub( 14, numf_e ) ) ), add(16 , numf_e), &tmp_e ); + sfm = BASOP_Util_Divide3232_Scale( tmp, denom, &sfm_e); + sfm_e = add(sfm_e, sub( tmp_e, denom_e ) ); + sfm = shl_sat( extract_l( L_min( sfm, L_shl( 1, 15 - sfm_e ) ) ), sfm_e ); + } + + return sfm; +} +#endif +#endif static float IGF_getSFM_new( const float *powerSpectrum, /* i : power spectrum */ const int16_t *logSpec, /* i : log of power spectrum */ @@ -184,6 +353,64 @@ static float IGF_getSFM_new( *-------------------------------------------------------------------*/ /*! r: spectral tilt value */ +#if 0 +#ifdef IVAS_FLOAT_FIXED +static Word16 IGF_getTilt_fx( + const Word32 *powerSpectrum, /* i : energies */ + const Word16 start, /* i : start subband index */ + const Word16 stop, /* i : stop subband index */ + Word16 q_powerSpectrum, /*Stores q reated to powerSpectrum*/ + Word16 *slope_e /*stores the exponent of returned slope value*/ +) +{ + Word16 i; + Word16 x; + Word16 width; + Word32 y; + Word32 mean_x, mean_y, mean_xy, mean_x2; + Word32 max_mean_x_e; + Word16 mean_x_e, mean_y_e, mean_xy_e, mean_x2_e; + Word16 slope; + Word16 slope_e; + + x = 1; + mean_x = mean_y = mean_xy = mean_x2 = 0; + move16(); + move32(); + move32(); + move32(); + move32(); + + width = sub( stop, start ); + for ( i = start; i < stop; i++ ) + { + mean_x = L_add( mean_x, x ); /*Q0*/ + mean_x2 = L_add( mean_x2, L_mult0( x, x ) ); /*Q0*/ + y = imult3216( Mult_32_16( L_add( BASOP_Util_Log2( L_max( L_shl( 1, q_powerSpectrum ), powerSpectrum[i] ) ), L_shl( sub( 31, q_powerSpectrum ), Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*Q25*/, 20 ); /*Q25*/ + mean_y = L_add( mean_y, y ); /*Q25*/ + mean_xy = L_add( mean_xy, Mult_32_16( y, x ) ); /*Q25+0-Q15=>Q10*/ + + x = add( x, 1 ); /*Q0*/ + } + mean_y = BASOP_Util_Divide3216_Scale( mean_y, width, &mean_y_e ); + mean_y_e = add( mean_y_e, -9 ) /*6 -15*/; + mean_x = BASOP_Util_Divide3216_Scale( mean_x, width, &mean_x_e ); + mean_x_e = add( mean_x_e, 16 ) /*31 -15*/; + mean_xy = BASOP_Util_Divide3216_Scale( mean_xy, width, mean_xy_e ); + mean_xy_e = add( mean_xy_e, 6 ) /*21 -15*/; + mean_x2 = BASOP_Util_Divide3216_Scale( mean_x2, width, mean_x2_e ); + mean_x2_e = add( mean_x2_e, 16 ) /*31 -15*/; + max_mean_x_e = s_max( mean_x_e, s_max( mean_xy_e, mean_x2_e ) ); + mean_x = shr( mean_x, sub( mean_x_e, max_mean_x_e ) ); /*mean_x_e=max_mean_x_e*/ + mean_xy = shr( mean_xy, sub( mean_xy_e, max_mean_x_e ) ); /*mean_xy_e=max_mean_x_e*/ + mean_x2 = shr( mean_x2, sub( mean_x2_e, max_mean_x_e ) ); /*mean_x2_e=mean_x2_e*/ + slope = BASOP_Util_Divide3232_Scale( L_mult0( extract_l( L_sub( mean_xy, mean_x ) ), extract_l( mean_y ) ) /*max_mean_x_e+mean_y_e*/, L_mult0( extract_l( L_sub( mean_x2, mean_x ) ), extract_l( mean_x ) ) /*2*max_mean_x_e*/, slope_e ); /*q_powerSpectrum-15*/ + *slope_e = add( *slope_e, sub( mean_y_e, max_mean_x_e ) ); + move16(); + return slope; +} +#endif +#endif static float IGF_getTilt( const float *powerSpectrum, /* i : energies */ const int16_t start, /* i : start subband index */ @@ -228,6 +455,90 @@ static float IGF_getTilt( *-------------------------------------------------------------------*/ /*! r: spectral tilt value */ +#ifdef IVAS_FLOAT_FIXED +/* Returns value with exponent as 9 and Q as 22*/ +static Word32 IGF_getTNR_fx( + const Word32 *powerSpectrum, /* i : energies */ + const Word16 start, /* i : start subband index */ + const Word16 stop, /* i : stop subband index */ + const Word16 adap, /* i : SFB width adaptation */ + Word16 e_ps, /*Stores exponent for powerSpectrum*/ + Word16 e_adap /*Stores exponent for adap*/ +) +{ + Word16 i; + Word16 width; + Word32 avg; + Word32 tonal; + Word16 tonal_e; /* holds exp for tonal*/ + Word32 noise; + Word16 noise_e; /* holds exp for noise*/ + Word32 tonalToNoise; + Word32 rootSpec[300]; + Word16 rootSpec_e[300]; /*rootSpec_e[i] holds exp for rootSpec[i]*/ + Word16 avg_e; /* holds exp for avg*/ + Word16 tmp_e; + avg = 0; + tonal = 0; + noise = EPSILON_FX; + tonal_e = 0; + noise_e = 0; + avg_e = 0; + tmp_e = 0; + move32(); + move32(); + move32(); + move16(); + move16(); + move16(); + move16(); + + set32_fx( rootSpec, 0, 300 ); + set16_fx( rootSpec_e, 0, 300 ); + + width = sub( stop, start ); + FOR( i = start; i < stop; i++ ) + { + rootSpec_e[sub( i, start )] = e_ps; + move16(); + rootSpec[sub( i, start )] = Sqrt32( powerSpectrum[i], &rootSpec_e[sub( i, start )] ); /*rootSpec[i - start] = sqrtf( powerSpectrum[i] );*/ + move32(); + avg = BASOP_Util_Add_Mant32Exp( avg, avg_e, rootSpec[sub( i, start )], rootSpec_e[sub( i, start )], &avg_e ); /*avg += rootSpec[i - start];resultant exponent is avg_e*/ + } + avg = BASOP_Util_Divide3216_Scale( avg, width, &tmp_e ); /*avg /= width;*/ + avg_e = add( 16, sub( add( avg_e, tmp_e ), 15 ) ); + + FOR( i = start; i < stop; i++ ) + { + Word16 normSpec_e; /*stores resultant exponent for normSpec*/ + Word16 normSpec = BASOP_Util_Divide3232_Scale( rootSpec[sub( i, start )], avg, &normSpec_e ); /*rootSpec[i - start] / avg;*/ + normSpec_e = add( normSpec_e, sub( rootSpec_e[sub( i, start )], avg_e ) ); + IF( GT_32( normSpec, L_add( L_shl( 1, sub( 15, normSpec_e ) ), L_shl( adap, sub( e_adap, normSpec_e ) ) ) ) ) + { + tonal = BASOP_Util_Add_Mant32Exp( tonal, tonal_e, rootSpec[sub( i, start )], rootSpec_e[sub( i, start )], &tonal_e ); /*tonal += rootSpec[i - start];*/ + } + ELSE IF( LT_32( normSpec, L_shl( 1, sub( 15, normSpec_e ) ) ) ) + { + noise = BASOP_Util_Add_Mant32Exp( noise, noise_e, rootSpec[sub( i, start )], rootSpec_e[sub( i, start )], &noise_e ); /*noise += rootSpec[i - start];*/ + } + } + + /*tonalToNoise=20.f * log10f( max( 1e-018f, tonal / noise ) )*/ + Word16 temp = BASOP_Util_Divide3232_Scale( tonal, noise, &tmp_e ); /*tonal / noise*/ + tmp_e = add( tmp_e, sub( tonal_e, noise_e ) ); + IF( GE_16( temp, 1 ) ) + { + tonalToNoise = L_shr( imult3216( Mult_32_16( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/, 20 ) /*25*/, 3 ); /*Q22*/ + } + ELSE + { + tonalToNoise = -1509949440; /*-360.f Q22*/ + move32(); + } + + return tonalToNoise; +} +#endif // IVAS_FLOAT_FIXED static float IGF_getTNR( const float *powerSpectrum, /* i : energies */ const int16_t start, /* i : start subband index */ @@ -279,7 +590,7 @@ static float IGF_getTNR( *-------------------------------------------------------------------*/ /*! r: crest factor */ -static float IGF_getCrest( +static float IGF_getCrest_ivas( const float *powerSpectrum, /* i : power spectrum */ const int16_t start, /* i : start subband index */ const int16_t stop /* i : stop subband index */ @@ -320,7 +631,7 @@ static float IGF_getCrest( *-------------------------------------------------------------------*/ /*! r: SFM value */ -static float IGF_getSFM( +static float IGF_getSFM_ivas( const float *powerSpectrum, /* i : energies */ const int16_t start, /* i : start subband index */ const int16_t stop /* i : stop subband index */ @@ -595,11 +906,485 @@ static void IGF_CalculateEnvelope( /*-------------------------------------------------------------------* - * IGF_CalculateStereoEnvelope() + * IGF_CalculateStereoEnvelope_fx() * * envelope estimation + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void IGF_CalculateStereoEnvelope_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + const Word32 *pMDCTSpectrum_fx, /* i : MDCT spectrum */ + Word16 pMDCTSpectrum_e, /* i : exponent for pMDCTSpectrum_fx */ + const Word32 *pMDCTSpectrumMsInv_fx, /* i : MDCT spectrum */ + Word16 pMDCTSpectrumMsInv_e, /* i : expontent for pMDCTSpectrumMsInv_fx */ + const Word32 *pPowerSpectrum_fx, /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 pPowerSpectrum_e, /* i : exponent for pPowerSpectrum_fx */ + const Word32 *pPowerSpectrumMsInv_fx, /* i : inverse power spectrum */ + Word16 pPowerSpectrumMsInv_e, /* i : exponent for pPowerSpectrumMsInv_fx */ + const Word16 igfGridIdx, /* i : IGF grid index */ + const Word16 coreMsMask[N_MAX], /* i : line wise ms Mask */ + const Word16 isTransient, /* i : flag indicating if transient is detected */ + const Word16 last_core_acelp /* i : indicator if last frame was ACELP core */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + Word16 sfb; /* this is the actual scalefactor band */ + Word16 width; /* this is width in subbands of the actual scalefactor band */ + Word16 tile_idx; + Word16 strt_cpy; + Word32 gain_fx; /* the gain which has to be applied to the source tile to get the destination energy */ + Word16 sb; + Word16 sfbEnergyR_fx; + Word32 sfbEnergyC_fx; /* the energy of the destination region of the tile */ + Word32 sfbEnergyTileR_fx; + Word32 sfbEnergyTileC_fx; /* the energy of the destination region of the tile */ + Word16 tmp, x, y; + Word16 mean_x_fx, mean_y_fx; + Word32 mean_xy_fx, mean_x2_fx; + Word16 slope_fx; + Word16 tmp_tb_fx; + Word16 tmp_sb_fx; + Word16 sfbCnt; + Word32 tileSrcSpec_fx[MAX_IGF_SFB_LEN]; + Word16 sfm; + Word16 crest; + Word16 temp; + Word16 mean_x_e, mean_y_e; /*Stores exponent for mean_x and mean_y respectively*/ + Word16 mean_xy_e, mean_x2_e; /*stores exponent for mean_xy and mean_x2 respectively*/ + Word16 tileSrcSpec_e; /*Exponent for tileSrcSpec_fx*/ + Word16 sfbEnergyTileR_e; /*Exponent for sfbEnergyTileR_fx*/ + Word16 sfbEnergyTileC_e; /*Exponent for sfbEnergyTileC_fx*/ + Word16 sfbEnergyC_e; /*Exponent for sfbEnergyC_fx*/ + Word16 gain_e; /*exponent for gain_fx*/ + Word16 crest_exp; /*stores exponent for output from crest*/ + Word16 sfm_exp; /*stores exponent for ouput from sfm*/ + Word16 tmp_tb_e; /*Stores exponent for tmp_tb_fx*/ + Word16 tmp_sb_e; /*stores exponent for tmp_sb_fx*/ + Word16 slope_e; /*stores exponent for slope_fx*/ + Word16 sfbEnergyR_e; /*stores exponent for sfbEnergyR*/ + Word16 tmp_e; + + hPrivateData = &hIGFEnc->igfData; + hGrid = &hPrivateData->igfInfo.grid[(Word16) igfGridIdx]; + swb_offset = hGrid->swb_offset; + move16(); + + IF( NE_16( igfGridIdx, IGF_GRID_LB_NORM ) ) + { + FOR( sfbCnt = 0; sfbCnt < sub( hGrid->sfbWrap[hGrid->nTiles], hGrid->sfbWrap[0] ); sfbCnt++ ) + { + /* reset filter */ + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_tb_e*/ + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_tb_e*/ + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_sb_e*/ + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_sb_e*/ + hPrivateData->sfb_sb_e[sfbCnt] = 0; + hPrivateData->sfb_tb_e[sfbCnt] = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + + IF( pPowerSpectrum_fx ) + { + FOR( sb = hGrid->sbWrap[0]; sb < swb_offset[hGrid->sfbWrap[hGrid->nTiles]]; sb++ ) + { + /*hPrivateData->logSpec[sb] = max( 0, (int16_t) ( logf( max( FLT_MIN, pPowerSpectrum[sb] ) ) * INV_LOG_2 ) );*/ + IF( LE_32( 1, pPowerSpectrum_fx[sb] ) ) + { + hPrivateData->logSpec[sb] = s_max( 0, (Word16) L_shr( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( pPowerSpectrum_e, Q25 ) ), 25 ) ); + } + ELSE + { + hPrivateData->logSpec[sb] = 0; /*max(0,-126) is always 0*/ + } + move16(); + } + } + FOR( tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++ ) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + FOR( sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++ ) + { + width = sub( swb_offset[sfb + 1], swb_offset[sfb] ); + sfbEnergyTileR_fx = EPSILON_FX; + sfbEnergyTileC_fx = EPSILON_FX; + sfbEnergyC_fx = EPSILON_FX; + sfbEnergyTileR_e = 0; + sfbEnergyTileC_e = 0; + sfbEnergyC_e = 0; + move16(); + move16(); + move16(); + move32(); + move32(); + move32(); + IF( pPowerSpectrum_fx ) + { + tmp = strt_cpy; + move16(); + + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + IF( NE_16( coreMsMask[sb], coreMsMask[strt_cpy] ) ) + { + sfbEnergyC_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyC_fx, sfbEnergyC_e, pPowerSpectrum_fx[sb], pPowerSpectrum_e, &sfbEnergyC_e ); /*resultant exponent is stored in sfbEnergyC_e*/ + sfbEnergyTileR_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyTileR_fx, sfbEnergyTileR_e, Mult_32_32( pMDCTSpectrumMsInv_fx[strt_cpy], pMDCTSpectrumMsInv_fx[strt_cpy] ), shl( pMDCTSpectrumMsInv_e, 1 ), &sfbEnergyTileR_e ); /*resultant exponent is stored in sfbEnergyTileR_e*/ + sfbEnergyTileC_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyTileC_fx, sfbEnergyTileC_e, pPowerSpectrumMsInv_fx[strt_cpy], pPowerSpectrumMsInv_e, &sfbEnergyTileC_e ); /*resultant exponent is stored in sfbEnergyTileC_e*/ + tileSrcSpec_fx[sub( strt_cpy, tmp )] = pPowerSpectrumMsInv_fx[strt_cpy]; /*resultant exponent is stored in tileSrcSpec_e*/ + tileSrcSpec_e = pPowerSpectrumMsInv_e; + } + ELSE + { + sfbEnergyC_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyC_fx, sfbEnergyC_e, pPowerSpectrum_fx[sb], pPowerSpectrum_e, &sfbEnergyC_e ); /*resultant exponent is stored in sfbEnergyC_e*/ + sfbEnergyTileR_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyTileR_fx, sfbEnergyTileR_e, Mult_32_32( pMDCTSpectrum_fx[strt_cpy], pMDCTSpectrum_fx[strt_cpy] ), shl( pMDCTSpectrum_e, 1 ), &sfbEnergyTileR_e ); /*resultant exponent is stored in sfbEnergyTileR_e*/ + sfbEnergyTileC_fx = BASOP_Util_Add_Mant32Exp( sfbEnergyTileC_fx, sfbEnergyTileC_e, pPowerSpectrum_fx[strt_cpy], pPowerSpectrum_e, &sfbEnergyTileC_e ); /*resultant exponent is stored in sfbEnergyTileC_e*/ + tileSrcSpec_fx[sub( strt_cpy, tmp )] = pPowerSpectrum_fx[strt_cpy]; /*resultant exponent is stored in tileSrcSpec_e*/ + tileSrcSpec_e = pPowerSpectrum_e; + } + move32(); + strt_cpy = add( strt_cpy, 1 ); + } + + sfbEnergyTileR_fx = BASOP_Util_Divide3216_Scale( sfbEnergyTileR_fx, width, &tmp_e ); + sfbEnergyTileR_e = sub( add( sfbEnergyTileR_e, tmp_e ), 15 ); /*stores the resultant exponent for sfbEnergyTileR_fx*/ + + /*gain = (float) ( sfbEnergyTileR * ( sfbEnergyC / sfbEnergyTileC ) );*/ + temp = BASOP_Util_Divide3232_Scale( sfbEnergyC_fx, L_add( sfbEnergyTileC_fx, EPSILON_FX ), &tmp_e ); + gain_e = add( tmp_e, sub( sfbEnergyC_e, sfbEnergyTileC_e ) ); + gain_fx = Mult_32_16( sfbEnergyTileR_fx, temp ); + gain_e = add( 16, add( gain_e, sfbEnergyTileR_e ) ); /*stores the resultant exponent for gain_fx*/ + + IF( !isTransient ) + { + Word16 diffSFM_fx; + Word16 diffSFM_e; + Word16 shiftedSFM_fx; + Word16 shiftedSFM_e; /*stores the resultant exponent for shiftedSFM_fx*/ + shiftedSFM_fx = 0; + shiftedSFM_e = 0; + move16(); + move16(); + + // tmp_tb = IGF_getSFM_ivas(pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1]) / IGF_getCrest_ivas(pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1]); + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, swb_offset[sfb], swb_offset[sfb + 1] ); + crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, swb_offset[sfb], swb_offset[sfb + 1] ); + tmp_tb_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); + tmp_tb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); /*stores the resultant exponent for tmp_tb_fx*/ + + // tmp_sb = IGF_getSFM_ivas(tileSrcSpec, 0, strt_cpy - tmp) / IGF_getCrest_ivas(tileSrcSpec, 0, strt_cpy - tmp); + sfm = IGF_getSFM( &sfm_exp, tileSrcSpec_fx, &tileSrcSpec_e, 0, sub( strt_cpy, tmp ) ); + crest = IGF_getCrest( &crest_exp, tileSrcSpec_fx, tileSrcSpec_e, 0, sub( strt_cpy, tmp ) ); + tmp_sb_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); + tmp_sb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); /*stores the resultant exponent for tmp_sb_fx*/ + + IF( last_core_acelp || hPrivateData->wasTransient ) + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = tmp_tb_fx; /*Exponent for hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] values stored in hPrivateData->sfb_tb_e[sfb] */ + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = tmp_sb_fx; /*Exponent for hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] values stored in hPrivateData->sfb_sb_e[sfb]*/ + hPrivateData->sfb_tb_e[sfb] = tmp_tb_e; + hPrivateData->sfb_sb_e[sfb] = tmp_sb_e; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + /* Purpose of this block: + -to make the exponent of hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] equal to that of tmp_tb_fx + -to make the exponent of hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] equal to that of tmp_sb_fx + */ + Word16 diff_sb_e; /*stores the difference of exponents for sb*/ + Word16 diff_tb_e; /*stores the difference of exponents for tb*/ + diff_sb_e = sub( tmp_sb_e, hPrivateData->sfb_sb_e[sfb] ); + diff_tb_e = sub( tmp_tb_e, hPrivateData->sfb_tb_e[sfb] ); + IF( LE_16( tmp_tb_e, hPrivateData->sfb_tb_e[sfb] ) ) + { + tmp_tb_fx = shl( tmp_tb_fx, diff_tb_e ); + tmp_tb_e = hPrivateData->sfb_tb_e[sfb]; + move16(); + } + ELSE + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = shr( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], diff_tb_e ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = shr( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], diff_tb_e ); + hPrivateData->sfb_tb_e[sfb] = tmp_tb_e; + move16(); + move16(); + move16(); + } + IF( LE_16( tmp_sb_e, hPrivateData->sfb_sb_e[sfb] ) ) + { + tmp_sb_fx = shl( tmp_sb_fx, diff_sb_e ); + tmp_sb_e = hPrivateData->sfb_sb_e[sfb]; + move16(); + } + ELSE + { + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = shr( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], diff_sb_e ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = shr( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], diff_sb_e ); + hPrivateData->sfb_sb_e[sfb] = tmp_sb_e; + move16(); + move16(); + move16(); + } + } + tmp_tb_fx = shr( tmp_tb_fx, 2 ); /*taking 2 guard bits so it's exponent tmp_sb_e=+2*/ + tmp_sb_fx = shr( tmp_sb_fx, 2 ); /*taking 2 guard bits so it's exponent tmp_tb_e=+2 */ + tmp_sb_e = add( tmp_sb_e, 2 ); + tmp_tb_e = add( tmp_tb_e, 2 ); + hPrivateData->SFM_tb_fx[sfb] = add( tmp_tb_fx, add( shr( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], 2 ), shr( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], 3 ) ) ); + hPrivateData->SFM_tb_fx[sfb] = extract_l( L_min( L_shl( 22118 /*2.7f Q13*/, sub( 2, tmp_tb_e ) ), hPrivateData->SFM_tb_fx[sfb] ) ); /* resultant exponent stored in hPrivateData->sfb_sb_e[sfb]*/ + hPrivateData->SFM_sb_fx[sfb] = add( tmp_sb_fx, add( shr( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], 2 ), shr( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], 3 ) ) ); + hPrivateData->SFM_sb_fx[sfb] = extract_l( L_min( L_shl( 22118 /*2.7f Q13*/, sub( 2, tmp_sb_e ) ), hPrivateData->SFM_sb_fx[sfb] ) ); /*resultant exponent stores in hPrivateData->sfb_tb_e[sfb]*/ + hPrivateData->sfb_sb_e[sfb] = tmp_sb_e; + hPrivateData->sfb_tb_e[sfb] = tmp_tb_e; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + diffSFM_e = BASOP_Util_Add_MantExp( hPrivateData->SFM_sb_fx[sfb], tmp_sb_e, negate( hPrivateData->SFM_tb_fx[sfb] ), tmp_tb_e, &diffSFM_fx ); /*stores the resultant exponent for diffSFM_fx*/ + + UNUSED_PARAM( diffSFM_e ); + + IF( diffSFM_fx > 0 && LT_32( hPrivateData->SFM_tb_fx[sfb], L_shr( 3277 /*0.1 Q15*/, tmp_tb_e ) ) ) /* check whether target SFB is more tonal than source SFB */ + { + Word16 currDampingFactor_fx, dampingFactor_fx, alpha_fx; + Word16 threshold_e, threshold_fx, alpha_e, currDampingFactor_e, dampingFactor_e; + /* calculate spectral tilt to detect sudden drops (or increases) in energy in the current SFB */ + x = 1; + mean_x_fx = mean_y_fx = 0; + mean_xy_fx = mean_x2_fx = 0; + mean_x_e = mean_y_e = 15; + mean_xy_e = mean_x2_e = 31; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + mean_x_fx = add( mean_x_fx, x ); /*Q0*/ + mean_x2_fx = L_add( mean_x2_fx, L_mult0( x, x ) ); /*Q0*/ + + /*y = 20 * (int16_t) log10f( max( 1e-018f, pPowerSpectrum[sb] ) );*/ + IF( LT_32( pPowerSpectrum_fx[sb], 1 ) ) + { + y = 20 * ( -18 ); + } + ELSE + { + y = imult1616( 20, extract_l( L_shr( Mult_32_16( ( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( pPowerSpectrum_e, Q25 ) ) ), INV_Log2_10_Q15 ), 25 ) ) ); /*Q0*/ + } + mean_y_fx = add( mean_y_fx, y ); /*Q0*/ + mean_xy_fx = L_add( mean_xy_fx, L_mult0( y, x ) ); /*Q0*/ + + x = add( x, 1 ); + } + mean_y_fx = BASOP_Util_Divide1616_Scale( mean_y_fx, width, &tmp_e ); /* resultant exp stores in mean_y_e*/ + mean_y_e = add( mean_y_e, sub( tmp_e, 15 ) ); + mean_x_fx = BASOP_Util_Divide1616_Scale( mean_x_fx, width, &tmp_e ); /* resultant exp stores in mean_x_e*/ + mean_x_e = add( mean_x_e, sub( tmp_e, 15 ) ); + mean_xy_fx = BASOP_Util_Divide3216_Scale( mean_xy_fx, width, &tmp_e ); /* resultant exp stores in mean_xy_e*/ + mean_xy_e = add( mean_xy_e, sub( tmp_e, 15 ) ); + mean_x2_fx = BASOP_Util_Divide3216_Scale( mean_x2_fx, width, &tmp_e ); /* resultant exp stores in mean_x2_e*/ + mean_x2_e = add( mean_x2_e, sub( tmp_e, 15 ) ); + + /*slope = ( mean_xy - mean_x * mean_y ) / ( mean_x2 - mean_x * mean_x );*/ + slope_fx = BASOP_Util_Divide3232_Scale( ( L_sub( mean_xy_fx, L_shl( mult( mean_x_fx, mean_y_fx ), sub( add( mean_x_e, mean_y_e ), mean_xy_e ) ) ) ), ( L_sub( mean_x2_fx, L_shl( mult( mean_x_fx, mean_x_fx ), sub( add( mean_x_e, mean_x_e ), mean_x2_e ) ) ) ), &slope_e ); + slope_e = add( slope_e, sub( mean_xy_e, mean_x2_e ) ); /*stores resultant exponent for slope_fx*/ + + /* determine whether strong tilt is due to a step in the spectrum (e.g. band limitation, no damping) + or a tonal component close the band border (apply damping) by calculating SFM for a shift of 1/2 SFB width*/ + threshold_fx = BASOP_Util_Divide1616_Scale( 60, width, &threshold_e ); /*stores resultant exponent for threshold_fx*/ + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope_fx, add( slope_e, 16 ), negate( threshold_fx ), add( threshold_e, 16 ) ), -1 ) ) + { + Word16 shift = shr( width, 1 ); + // shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ); + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, sub( swb_offset[sfb], shift ), sub( swb_offset[sfb + 1], shift ) ); + crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, sub( swb_offset[sfb], shift ), sub( swb_offset[sfb + 1], shift ) ); + shiftedSFM_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + ELSE IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope_fx, add( slope_e, 16 ), threshold_fx, add( threshold_e, 16 ) ), 1 ) && ( NE_16( sfb, sub( hGrid->sfbWrap[hGrid->nTiles], 1 ) ) ) ) + { + Word16 shift; + shift = shr( width, 1 ); + // shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ); + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, add( swb_offset[sfb], shift ), add( swb_offset[sfb + 1], shift ) ); + crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, add( swb_offset[sfb], shift ), add( swb_offset[sfb + 1], shift ) ); + shiftedSFM_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + shiftedSFM_e = add( shiftedSFM_e, sub( sfm_exp, crest_exp ) ); /* stores resultant exponent for shiftedSFM_fx*/ + + // alpha = min( 320.f / (float) swb_offset[sfb + 1], 1.25f ); + temp = BASOP_Util_Divide1616_Scale( 320, swb_offset[sfb + 1], &alpha_e ); + alpha_fx = extract_l( L_min( temp, L_shl( 20480 /*1.25 Q14*/, sub( 1, alpha_e ) ) ) ); /* exponent is alpha_e*/ + temp = BASOP_Util_Divide1616_Scale( hPrivateData->SFM_tb_fx[sfb], hPrivateData->SFM_sb_fx[sfb], &tmp_e ); + tmp_e = add( tmp_e, sub( hPrivateData->sfb_tb_e[sfb], hPrivateData->sfb_sb_e[sfb] ) ); /* stores resultant exponent for temp */ + + // currDampingFactor = expf( alpha * logf( hPrivateData->SFM_tb[sfb] / hPrivateData->SFM_sb[sfb] ) ); + currDampingFactor_fx = round_fx( BASOP_util_Pow2( Mpy_32_16_1( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), 25 ) ), alpha_fx ), add( alpha_e, 6 ), &currDampingFactor_e ) ); /*exp is currDampingFactor_e*/ + + IF( GT_32( shiftedSFM_fx, L_shl( 1311 /*0.04f Q15*/, negate( shiftedSFM_e ) ) ) ) + { + currDampingFactor_fx = 32767; /*1.f Q15*/ + currDampingFactor_e = 0; + move16(); + move16(); + } + + IF( last_core_acelp || hPrivateData->wasTransient || EQ_32( hPrivateData->prevDampingFactor_IIR_fx[sfb], L_shl( -1, sub( 15, hPrivateData->prevDampingFactor_IIR_e[sfb] ) ) ) ) + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = s_max( currDampingFactor_fx, shr( 3277 /*0.1f * 32767*/, currDampingFactor_e ) ); /*resultant exponent stored in hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = currDampingFactor_e; + move16(); + move16(); + } + + { + Word32 tonalToNoise; + Word16 adap; + Word16 adap_e; /*stores exp for adap*/ + Word16 tonalToNoise_e; /*stores exponent for tonalToNoise*/ + tonalToNoise_e = 9; /*stores exponent for tonalToNoise*/ + move16(); + adap = BASOP_Util_Divide1616_Scale( width, 30, &adap_e ); + tonalToNoise = IGF_getTNR_fx( pPowerSpectrum_fx, swb_offset[sfb], swb_offset[sfb + 1], adap, pPowerSpectrum_e, adap_e ); /*Q22*/ + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tonalToNoise, tonalToNoise_e, L_add( L_shl( 10, sub( 15, adap_e ) ), adap ), add( 16, adap_e ) ), -1 ) ) + { + // currDampingFactor += 0.1f * ( ( 10 + adap ) - tonalToNoise ); + Word32 temp2 = BASOP_Util_Add_Mant32Exp( L_add( L_shl( 10, sub( 15, adap_e ) ) /*exp:adap_e*/, adap ), add( adap_e, 16 ), L_negate( tonalToNoise ), tonalToNoise_e, &tmp_e ); /* resultant exp is tmp_e*/ + currDampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor_fx, currDampingFactor_e, extract_l( Mult_32_32( 3277 /*0.1f Q15*/, temp2 ) ), tmp_e, &currDampingFactor_fx ); /*stores resultant exp for currDampingFactor_fx*/ + } + } + + dampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor_fx, currDampingFactor_e, hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb], &dampingFactor_fx ); + dampingFactor_fx = shr( dampingFactor_fx, 1 ); /* resultant exponent is dampingFactor_e*/ + IF( NE_16( BASOP_Util_Cmp_Mant32Exp( dampingFactor_fx, add( dampingFactor_e, 16 ), shr( hPrivateData->prevDampingFactor_IIR_fx[sfb], 1 ), add( hPrivateData->prevDampingFactor_IIR_e[sfb], 16 ) ), -1 ) ) + { + // do nothing + } + ELSE + { + dampingFactor_fx = shr( hPrivateData->prevDampingFactor_IIR_fx[sfb], 1 ); /* resultant exponent is hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + dampingFactor_e = hPrivateData->prevDampingFactor_IIR_e[sfb]; + move16(); + } + IF( dampingFactor_e < 0 ) + { + dampingFactor_fx = shl( dampingFactor_fx, dampingFactor_e ); + dampingFactor_e = 0; + move16(); + } + gain_fx = Mult_32_16( gain_fx, shl_sat( extract_l( L_min( L_add( dampingFactor_fx, Mult_32_16( L_shl( hPrivateData->dampingFactorSmoothing[sfb], sub( 15, dampingFactor_e ) ) /*Q:15-dampingFactor_e*/, 3277 /*0.1f Q15*/ ) /*Q:15-dampingFactor_e*/ ), shl_sat( 1, sub( 15, dampingFactor_e ) ) ) ), dampingFactor_e ) /*Q15*/ ); + + hPrivateData->prevDampingFactor_IIR_fx[sfb] = dampingFactor_fx; + hPrivateData->prevDampingFactor_IIR_e[sfb] = dampingFactor_e; + move16(); + move16(); + if ( hPrivateData->dampingFactorSmoothing[sfb] > 0 ) + { + hPrivateData->dampingFactorSmoothing[sfb] = sub( hPrivateData->dampingFactorSmoothing[sfb], 1 ); + move16(); + } + } + ELSE + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = -( 1 << 15 ); /* resultant exp which is 0 stores in hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 1; + move16(); + move16(); + move16(); + } + + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = tmp_tb_fx; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = hPrivateData->SFM_tb_fx[sfb]; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = tmp_sb_fx; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = hPrivateData->SFM_sb_fx[sfb]; + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; + + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + ELSE + { + sfbEnergyR_fx = add_sat( EPSILON_FX, BASOP_Util_Divide3216_Scale( sum2_f_32_fx( pMDCTSpectrum_fx + swb_offset[sfb], width, 3 ) /*exp: 2 * pMDCTSpectrum_e + 3*/, width, &sfbEnergyR_e ) ); + sfbEnergyR_e = add( sfbEnergyR_e, add( shl( pMDCTSpectrum_e, 1 ), /*+3 - 15=>-12*/ -12 ) ); /* stores resultant exponent for sfbEnergyR_fx*/ + gain_fx = sfbEnergyR_fx; /*resultant exponent stored in gain_e=sfbEnergyR_e*/ + gain_e = add( sfbEnergyR_e, 16 ); /* because gain_fx is word32;only after adding 16 q of gain_fx is 15-sfbEnergyR_e*/ + + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; + move16(); + move16(); + move16(); + move16(); + } + /*gain=0.5f+log2f(gain)*2+16 becuase 2.885390081777927f=2*1/loge(2) so 2*1/loge(2)*loge(x) can be written as 2*log2(x)*/ + gain_fx = L_add( ONE_IN_Q23, L_add( L_add( BASOP_Util_Log2( gain_fx ), L_shl( gain_e, Q25 ) ), L_shl( 16, Q24 ) ) ); /*Q24*/ + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_48000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_48000_CPE ) ) ) + { + gain_fx = L_add( gain_fx, ONE_IN_Q22 ); /* better preservation of original HF band energy */ + } + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_64000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_64000_CPE ) ) ) + { + gain_fx = L_add( gain_fx, ONE_IN_Q21 ); + } + gain_fx = L_min( gain_fx, 91 << Q24 ); /* 13+15+63, see arithcode encode residual */ + gain_fx = L_max( gain_fx, 0 ); + gain_e = 7; /* stores exponent for gain_fx*/ + move16(); + hPrivateData->igfScfQuantized[sfb] = (Word16) ( L_shr( gain_fx, 24 ) ); /*Q0*/ + } + } + + return; +} +#endif +/*-------------------------------------------------------------------* + * IGF_CalculateStereoEnvelope() + * + * envelope estimation + *-------------------------------------------------------------------*/ static void IGF_CalculateStereoEnvelope( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ const float *pMDCTSpectrum, /* i : MDCT spectrum */ @@ -699,8 +1484,8 @@ static void IGF_CalculateStereoEnvelope( float diffSFM; float shiftedSFM = 0.f; - tmp_tb = IGF_getSFM( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1] ) / IGF_getCrest( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1] ); - tmp_sb = IGF_getSFM( tileSrcSpec, 0, strt_cpy - tmp ) / IGF_getCrest( tileSrcSpec, 0, strt_cpy - tmp ); + tmp_tb = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1] ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1] ); + tmp_sb = IGF_getSFM_ivas( tileSrcSpec, 0, strt_cpy - tmp ) / IGF_getCrest_ivas( tileSrcSpec, 0, strt_cpy - tmp ); if ( last_core_acelp || hPrivateData->wasTransient ) { @@ -744,12 +1529,12 @@ static void IGF_CalculateStereoEnvelope( if ( slope < -threshold ) { int16_t shift = width >> 1; - shiftedSFM = IGF_getSFM( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ) / IGF_getCrest( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ); + shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ); } else if ( ( slope > 1.f * threshold ) && ( sfb != hGrid->sfbWrap[hGrid->nTiles] - 1 ) ) { int16_t shift = width >> 1; - shiftedSFM = IGF_getSFM( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ) / IGF_getCrest( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ); + shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ); } alpha = min( 320.f / (float) swb_offset[sfb + 1], 1.25f ); @@ -1056,7 +1841,7 @@ static void IGF_Whitening( const int16_t igfGridIdx, /* i : Q0 | IGF grid index */ const int16_t isTransient, /* i : Q0 | flag indicating if transient is detected */ const int16_t last_core_acelp, /* i : Q0 | indicator if last frame was ACELP core */ - const int16_t isTNSActive, /* i : Q0 | indicator if TNS is active */ + const int8_t isTNSActive, /* i : Q0 | indicator if TNS is active */ const int16_t sp_aud_decision0, /* i : Q0 | first stage classifier decision */ const int32_t brate, /* i : Q0 | bitrate */ const int16_t element_mode /* i : Q0 | element mode */ @@ -1567,7 +2352,7 @@ static int16_t IGF_WriteFlatteningTrigger( * updates the start/stop frequency of IGF according to igfGridIdx *-------------------------------------------------------------------*/ -static void IGF_UpdateInfo( +static void IGF_UpdateInfo_ivas( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ const int16_t igfGridIdx /* i : IGF grid index */ ) @@ -1864,7 +2649,7 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - const int16_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ const int16_t sp_aud_decision0, /* i : first stage switching decision */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ) @@ -1877,7 +2662,7 @@ void IGFEncApplyMono( pPowerSpectrumParameter = !isTNSActive && isTCX20 ? pPowerSpectrum : NULL; - IGF_UpdateInfo( st->hIGFEnc, igfGridIdx ); + IGF_UpdateInfo_ivas( st->hIGFEnc, igfGridIdx ); if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { @@ -1902,6 +2687,165 @@ void IGFEncApplyMono( * * apply the IGF encoder, main encoder interface *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyStereo_fx( + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo encoder structure */ + Word16 ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ + const IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS], /* i : instance handle of IGF Encoder */ + const Word16 igfGridIdx, /* i : IGF grid index */ + Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ + Word32 *pPowerSpectrum_fx[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word32 *pPowerSpectrumMsInv_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse power spectrum */ + Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#if 1 + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrumMsInv[CPE_CHANNELS][NB_DIV], /* i/o: inverse power spectrum */ + float *inv_spectrum[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif + const Word16 frameno, /* i : flag indicating index of current subfr. */ + const Word16 sp_aud_decision0, /* i : sp_aud_decision0 */ + const Word32 element_brate, /* i : element bitrate */ + const Word16 mct_on /* i : flag mct block (1) or stereo (0) */ +) +{ + UNUSED_PARAM( pPowerSpectrum_fx ); + UNUSED_PARAM( pPowerSpectrumMsInv_fx ); +#if 1 + float *pPowerSpectrumParameter[NB_DIV]; /* If it is NULL it informs a function that specific handling is needed */ + float *pPowerSpectrumParameterMsInv[NB_DIV]; +#endif + Word16 inv_spectrum_e = 0; + Word16 pPowerSpectrumParameterMsInv_e = 0; + Word16 pPowerSpectrumParameter_e = 0; + Word32 *pPowerSpectrumParameter_fx[NB_DIV]; /* If it is NULL it informs a function that specific handling is needed */ + Word32 *pPowerSpectrumParameterMsInv_fx[NB_DIV]; + Word16 coreMsMask[N_MAX]; + Word16 sfb, ch, last_core_acelp; + STEREO_MDCT_BAND_PARAMETERS *sfbConf; + + /* assumptions: stereo filling was already done on the flattened spectra + * IGF region is always coded M/S, never L/R (to be done in the encoder) + * for residual bands with stereo filling infoTcxNoise is set to zero + * both channels have the same IGF configuration + */ + + /* sanity checks: check if both channels have the same configuration...*/ + assert( ( sts[0]->core == sts[1]->core ) ); + + /* initialization */ + IF( EQ_16( sts[0]->core, TCX_20_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20; + } + ELSE + { + sfbConf = &hStereoMdct->stbParamsTCX10; + } + IF( EQ_16( sts[0]->last_core, ACELP_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; + } + + /* create line wise ms mask for the core bands */ + set16_fx( coreMsMask, 0, N_MAX ); + FOR( sfb = 0; sfb < sfbConf->sfbCnt; sfb++ ) + { + set16_fx( &coreMsMask[sfbConf->sfbOffset[sfb]], ms_mask[frameno][sfb], sub( sfbConf->sfbOffset[sfb + 1], sfbConf->sfbOffset[sfb] ) ); + } + + test(); + test(); + IF( EQ_16( sts[0]->core, TCX_20_CORE ) && !sts[0]->hTcxEnc->fUseTns[frameno] && !sts[1]->hTcxEnc->fUseTns[frameno] ) + { +#if 1 + pPowerSpectrumParameter[0] = &pPowerSpectrum[0][0]; + pPowerSpectrumParameter[1] = &pPowerSpectrum[1][0]; + pPowerSpectrumParameterMsInv[0] = pPowerSpectrumMsInv[0][0]; + pPowerSpectrumParameterMsInv[1] = pPowerSpectrumMsInv[1][0]; +#endif + pPowerSpectrumParameter_fx[0] = &pPowerSpectrum_fx[0][0]; + pPowerSpectrumParameter_fx[1] = &pPowerSpectrum_fx[1][0]; + pPowerSpectrumParameterMsInv_fx[0] = pPowerSpectrumMsInv_fx[0][0]; + pPowerSpectrumParameterMsInv_fx[1] = pPowerSpectrumMsInv_fx[1][0]; + } + ELSE + { +#if 1 + pPowerSpectrumParameter[0] = NULL; + pPowerSpectrumParameter[1] = NULL; + pPowerSpectrumParameterMsInv[0] = NULL; + pPowerSpectrumParameterMsInv[1] = NULL; +#endif + pPowerSpectrumParameter_fx[0] = NULL; + pPowerSpectrumParameter_fx[1] = NULL; + pPowerSpectrumParameterMsInv_fx[0] = NULL; + pPowerSpectrumParameterMsInv_fx[1] = NULL; + } + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + last_core_acelp = (Word16) EQ_16( sts[ch]->last_core, ACELP_CORE ); + + IGF_UpdateInfo( hIGFEnc[ch], igfGridIdx ); +#if 1 /*************************************flt to fix conversion****************************************************/ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + hPrivateData = &hIGFEnc[ch]->igfData; + hGrid = &hPrivateData->igfInfo.grid[(Word16) igfGridIdx]; + swb_offset = hGrid->swb_offset; + f2me_buf( sts[ch]->hTcxEnc->spectrum[frameno], sts[ch]->hTcxEnc->spectrum_fx[frameno], &sts[ch]->hTcxEnc->spectrum_e[frameno], swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); + IF( pPowerSpectrumParameter[ch] ) + f2me_buf( pPowerSpectrumParameter[ch], pPowerSpectrumParameter_fx[ch], &pPowerSpectrumParameter_e, swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); + f2me_buf( inv_spectrum[ch][frameno], inv_spectrum_fx[ch][frameno], &inv_spectrum_e, swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); + IF( pPowerSpectrumParameterMsInv[ch] ) + f2me_buf( pPowerSpectrumParameterMsInv[ch], pPowerSpectrumParameterMsInv_fx[ch], &pPowerSpectrumParameterMsInv_e, swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + for ( sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + max_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_tb ); + max_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_tb ); + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + max_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_sb ); + max_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_sb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + if ( sub( 15, hPrivateData->sfb_tb_e[sfb] ) < 0 || sub( 15, hPrivateData->sfb_sb_e[sfb] ) < 0 ) + continue; + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } +#endif /**********************************flt to fix ends here*******************************************************/ + IGF_CalculateStereoEnvelope_fx( hIGFEnc[ch], sts[ch]->hTcxEnc->spectrum_fx[frameno], sts[ch]->hTcxEnc->spectrum_e[frameno], inv_spectrum_fx[ch][frameno], inv_spectrum_e, pPowerSpectrumParameter_fx[ch], pPowerSpectrumParameter_e, pPowerSpectrumParameterMsInv_fx[ch], pPowerSpectrumParameterMsInv_e, igfGridIdx, coreMsMask, sts[ch]->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp ); +#if 1 /*************************************fix to flt conversion****************************************************/ + for ( sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } +#endif /**********************************fix to flt ends here*******************************************************/ + + pPowerSpectrumParameter[ch] = sts[ch]->core == TCX_20_CORE ? pPowerSpectrum[ch] : NULL; + + IGF_Whitening( hIGFEnc[ch], pPowerSpectrumParameter[ch], igfGridIdx, sts[ch]->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, ( sts[0]->hTcxEnc->fUseTns[frameno] || sts[1]->hTcxEnc->fUseTns[frameno] ), sp_aud_decision0, element_brate, sts[ch]->element_mode ); + + IGF_ErodeSpectrum( hIGFEnc[ch], sts[ch]->hTcxEnc->spectrum[frameno], pPowerSpectrumParameter[ch], igfGridIdx, mct_on ); + } + + return; +} +#endif // IVAS_FLOAT_FIXED void IGFEncApplyStereo( STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo encoder structure */ @@ -1966,7 +2910,7 @@ void IGFEncApplyStereo( { last_core_acelp = ( sts[ch]->last_core == ACELP_CORE ); - IGF_UpdateInfo( hIGFEnc[ch], igfGridIdx ); + IGF_UpdateInfo_ivas( hIGFEnc[ch], igfGridIdx ); IGF_CalculateStereoEnvelope( hIGFEnc[ch], sts[ch]->hTcxEnc->spectrum[frameno], inv_spectrum[ch][frameno], pPowerSpectrumParameter[ch], pPowerSpectrumParameterMsInv[ch], igfGridIdx, coreMsMask, sts[ch]->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp ); @@ -1993,7 +2937,7 @@ void IGFSaveSpectrumForITF( const float *pITFSpectrum /* i : MDCT spectrum */ ) { - IGF_UpdateInfo( hIGFEnc, igfGridIdx ); + IGF_UpdateInfo_ivas( hIGFEnc, igfGridIdx ); mvr2r( pITFSpectrum + IGF_START_MN, hIGFEnc->spec_be_igf_flt, hIGFEnc->infoStopLine - IGF_START_MN ); diff --git a/lib_enc/igf_enc_fx.c b/lib_enc/igf_enc_fx.c index 1bcb7698f..184f9e9ee 100644 --- a/lib_enc/igf_enc_fx.c +++ b/lib_enc/igf_enc_fx.c @@ -565,12 +565,12 @@ static void IGF_ErodeSpectrum( Word16 *highPassEner_exp, /**< ou /**********************************************************************/ /* crest factor calculation **************************************************************************/ -static Word16 IGF_getCrest( /**< out: Q15| crest factor */ - Word16 *crest_exp, /**< out: | exponent of crest factor */ - const Word32 *powerSpectrum, /**< in: Q31 | power spectrum */ - const Word16 powerSpectrum_exp, /**< in: | exponent of power spectrum */ - const Word16 start, /**< in: Q0 | start subband index */ - const Word16 stop /**< in: Q0 | stop subband index */ +Word16 IGF_getCrest( /**< out: Q15| crest factor */ + Word16 *crest_exp, /**< out: | exponent of crest factor */ + const Word32 *powerSpectrum, /**< in: Q31 | power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ ) { Word16 i; @@ -654,12 +654,12 @@ static Word16 IGF_getCrest( /**< ou /************************************************************************* calculates spectral flatness measurment **************************************************************************/ -static Word16 IGF_getSFM( /**< out: Q15| SFM value */ - Word16 *SFM_exp, /**< out: | exponent of SFM Factor */ - const Word32 *energy, /**< in: Q31| energies */ - const Word16 *energy_exp, /**< in: | exponent of energies */ - const Word16 start, /**< in: Q0 | start subband index */ - const Word16 stop /**< in: Q0 | stop subband index */ +Word16 IGF_getSFM( /**< out: Q15| SFM value */ + Word16 *SFM_exp, /**< out: | exponent of SFM Factor */ + const Word32 *energy, /**< in: Q31| energies */ + const Word16 *energy_exp, /**< in: | exponent of energies */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ ) { Word16 n, i, s; @@ -1083,8 +1083,8 @@ static void IGF_WriteFlatteningTrigger( /**********************************************************************/ /* updates the start/stop frequency of IGF according to igfGridIdx **************************************************************************/ -static void IGF_UpdateInfo( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ - const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ +void IGF_UpdateInfo( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ ) { IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index 56144429e..e24df2607 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -803,6 +803,11 @@ ivas_error init_encoder( } /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum_fx[0] = st->hTcxEnc->spectrum_long_fx; + st->hTcxEnc->spectrum_fx[1] = st->hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#endif // IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum[0] = st->hTcxEnc->spectrum_long; st->hTcxEnc->spectrum[1] = st->hTcxEnc->spectrum_long + N_TCX10_MAX; #ifdef IVAS_FLOAT_FIXED diff --git a/lib_enc/ivas_mct_core_enc.c b/lib_enc/ivas_mct_core_enc.c index 6482d11de..5c7b481e5 100644 --- a/lib_enc/ivas_mct_core_enc.c +++ b/lib_enc/ivas_mct_core_enc.c @@ -39,7 +39,9 @@ #include "rom_com.h" #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" #include "ivas_prot_fx.h" +#include "prot_fx.h" #endif @@ -178,7 +180,7 @@ static void AdjustChannelRatios( * * joint mct encoding *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void ivas_mct_core_enc( const IVAS_FORMAT ivas_format, /* i : IVAS format */ MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ @@ -190,6 +192,15 @@ void ivas_mct_core_enc( const int16_t sba_order /* i : Ambisonic (SBA) order */ ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ + Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k]; + Word32 powerSpecMsInv_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* MS inv power spectrum, also inverse MDST spectrum */ + Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][2]; + Word32 *inv_mdst_spectrum_fx[MCT_MAX_CHANNELS][2]; + Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][2]; + Word32 inv_spectrum_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ +#endif // IVAS_FLOAT_FIXED int16_t ch, ch_core, nSubframes, L_subframeTCX; int16_t i, cpe_id, n, nAvailBits; int16_t nCPE; @@ -228,6 +239,13 @@ void ivas_mct_core_enc( for ( ch = 0; ch < nChannels; ch++ ) { +#ifdef IVAS_FLOAT_FIXED + inv_mdst_spectrum_fx[ch][0] = powerSpecMsInv_fx[ch][0] = powerSpecMsInv_long_fx[ch]; + inv_mdst_spectrum_fx[ch][1] = powerSpecMsInv_fx[ch][1] = powerSpecMsInv_long_fx[ch] + N_TCX10_MAX; + inv_spectrum_fx[ch][0] = inv_spectrum_long_fx[ch]; + inv_spectrum_fx[ch][1] = inv_spectrum_long_fx[ch] + N_TCX10_MAX; + UNUSED_PARAM( inv_mdst_spectrum_fx ); +#endif inv_mdst_spectrum[ch][0] = powerSpecMsInv[ch][0] = powerSpecMsInv_long[ch]; inv_mdst_spectrum[ch][1] = powerSpecMsInv[ch][1] = powerSpecMsInv_long[ch] + N_TCX10_MAX; inv_spectrum[ch][0] = inv_spectrum_long[ch]; @@ -245,8 +263,14 @@ void ivas_mct_core_enc( continue; } +#ifdef IVAS_FLOAT_FIXED + orig_spectrum_fx[i][0] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch]; + orig_spectrum_fx[i][1] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch] + N_TCX10_MAX; +#endif // IVAS_FLOAT_FIXED + mdst_spectrum[i][0] = hMCT->p_mdst_spectrum_long[cpe_id][ch]; mdst_spectrum[i][1] = hMCT->p_mdst_spectrum_long[cpe_id][ch] + N_TCX10_MAX; + orig_spectrum[i][0] = hMCT->p_orig_spectrum_long[cpe_id][ch]; orig_spectrum[i][1] = hMCT->p_orig_spectrum_long[cpe_id][ch] + N_TCX10_MAX; @@ -267,28 +291,16 @@ void ivas_mct_core_enc( if ( switch_bw ) { -#ifndef IVAS_FLOAT_FIXED initMdctStereoEncData( hMCT->hBlockData[ch]->hStereoMdct, ivas_format, sts[ch_core]->element_mode, sts[ch_core]->element_brate, sts[ch_core]->bwidth, sts[ch_core]->igf, sts[ch_core]->hIGFEnc->igfData.igfInfo.grid, 0 ); -#else - initMdctStereoEncData_fx( hMCT->hBlockData[ch]->hStereoMdct, ivas_format, sts[ch_core]->element_mode, sts[ch_core]->element_brate, sts[ch_core]->bwidth, - sts[ch_core]->igf, sts[ch_core]->hIGFEnc->igfData.igfInfo.grid, 0 ); -#endif } if ( sts[ch_core]->igf ) { -#ifndef IVAS_FLOAT_FIXED /* calculate the igf start band from the igf start line */ stereo_mdct_init_igf_start_band( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20, 1.0f, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); stereo_mdct_init_igf_start_band( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10, 0.5f, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); -#else - /* calculate the igf start band from the igf start line */ - stereo_mdct_init_igf_start_band_fx( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20, 16384 /* 1.0f in Q14 */, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); - - stereo_mdct_init_igf_start_band_fx( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10, 8192 /* 0.5f in Q14 */, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); -#endif } else { @@ -416,7 +428,11 @@ void ivas_mct_core_enc( { if ( hMCT->currBlockDataCnt > 0 ) { +#ifdef IVAS_FLOAT_FIXED + mctStereoIGF_enc_fx( hMCT, sts, orig_spectrum_fx, powerSpec_fx, powerSpecMsInv_fx, inv_spectrum_fx, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); +#else mctStereoIGF_enc( hMCT, sts, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); +#endif // IVAS_FLOAT_FIXED } else { @@ -559,3 +575,499 @@ void ivas_mct_core_enc( return; } +#else +void ivas_mct_core_enc( + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ + const Word16 nChannels, /* i : number of channels to be coded */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + const Word16 switch_bw, /* i : flag bandwidth switch occurance */ + const Word16 lfe_bits, /* i : bits spent for LFE */ + const Word16 sba_order /* i : Ambisonic (SBA) order */ +) +{ + Word16 ch, ch_core, nSubframes, L_subframeTCX; + Word16 i, cpe_id, n, nAvailBits; + Word16 nCPE; + float *orig_spectrum[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ + float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k]; + float powerSpecMsInv_long[MCT_MAX_CHANNELS][L_FRAME48k]; /* MS inv power spectrum, also inverse MDST spectrum */ + float *powerSpecMsInv[MCT_MAX_CHANNELS][2]; + float *inv_mdst_spectrum[MCT_MAX_CHANNELS][2]; + float *inv_spectrum[MCT_MAX_CHANNELS][2]; + float *mdst_spectrum[MCT_MAX_CHANNELS][2] = { NULL }; + float inv_spectrum_long[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ +#if 0 + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ + Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k]; + Word32 mdst_fx; +#endif + Word32 powerSpecMsInv_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* MS inv power spectrum, also inverse MDST spectrum */ + Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][2]; + Word32 *inv_mdst_spectrum_fx[MCT_MAX_CHANNELS][2]; + Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][2]; + Word32 *mdst_spectrum_fx[MCT_MAX_CHANNELS][2] = { NULL }; + Word32 inv_spectrum_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ + Word16 total_side_bits; + Word16 chBitRatios[MCT_MAX_CHANNELS]; + Encoder_State *sts[MCT_MAX_CHANNELS]; + Encoder_State *st; + Word16 sp_aud_decision0[MCT_MAX_CHANNELS]; + BSTR_ENC_HANDLE hBstr; + float mdst; + + + push_wmops( "mct_encoding" ); + + /*--------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + total_side_bits = 0; + move16(); + + nCPE = shr( nChannels, 1 ); // nChannels / CPE_CHANNELS + + /*in case of odd number of channels*/ + if ( NE_16( ( nCPE * CPE_CHANNELS ), nChannels ) ) + { + nCPE = add( nCPE, 1 ); + } + + FOR( ch = 0; ch < nChannels; ch++ ) + { +#if 1 // Float initialization to be removed + inv_mdst_spectrum[ch][0] = powerSpecMsInv[ch][0] = powerSpecMsInv_long[ch]; + inv_mdst_spectrum[ch][1] = powerSpecMsInv[ch][1] = powerSpecMsInv_long[ch] + N_TCX10_MAX; + inv_spectrum[ch][0] = inv_spectrum_long[ch]; + inv_spectrum[ch][1] = inv_spectrum_long[ch] + N_TCX10_MAX; +#endif + + inv_mdst_spectrum_fx[ch][0] = powerSpecMsInv_fx[ch][0] = powerSpecMsInv_long_fx[ch]; + inv_mdst_spectrum_fx[ch][1] = powerSpecMsInv_fx[ch][1] = powerSpecMsInv_long_fx[ch] + N_TCX10_MAX; + inv_spectrum_fx[ch][0] = inv_spectrum_long_fx[ch]; + inv_spectrum_fx[ch][1] = inv_spectrum_long_fx[ch] + N_TCX10_MAX; + } + + FOR( ( cpe_id = 0, i = 0 ); cpe_id < nCPE; cpe_id++ ) + { + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[i] = hCPE[cpe_id]->hCoreCoder[ch]; + IF( EQ_32( hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + i = add( i, 1 ); + CONTINUE; + } +#if 1 // Float initialization to be removed + mdst_spectrum[i][0] = hMCT->p_mdst_spectrum_long[cpe_id][ch]; + mdst_spectrum[i][1] = hMCT->p_mdst_spectrum_long[cpe_id][ch] + N_TCX10_MAX; + orig_spectrum[i][0] = hMCT->p_orig_spectrum_long[cpe_id][ch]; + orig_spectrum[i][1] = hMCT->p_orig_spectrum_long[cpe_id][ch] + N_TCX10_MAX; +#endif + mdst_spectrum_fx[i][0] = hMCT->p_mdst_spectrum_long_fx[cpe_id][ch]; + mdst_spectrum_fx[i][1] = hMCT->p_mdst_spectrum_long_fx[cpe_id][ch] + N_TCX10_MAX; +#if 0 + orig_spectrum_fx[i][0] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch]; + orig_spectrum_fx[i][1] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch] + N_TCX10_MAX; +#endif + + sp_aud_decision0[i] = hCPE[cpe_id]->hCoreCoder[0]->sp_aud_decision0; + move16(); + + sts[i]->hTcxEnc->tns_ms_flag[0] = 0; + sts[i]->hTcxEnc->tns_ms_flag[1] = 0; + move16(); + move16(); + + i = add( i, 1 ); + } + } + + hBstr = sts[0]->hBstr; + + FOR( ch = 0; ch < shr( hMCT->nchan_out_woLFE, 1 ); ch++ ) + { + ch_core = imult1616( ch, CPE_CHANNELS ); + + IF( switch_bw ) + { + initMdctStereoEncData_fx( hMCT->hBlockData[ch]->hStereoMdct, ivas_format, sts[ch_core]->element_mode, sts[ch_core]->element_brate, sts[ch_core]->bwidth, + sts[ch_core]->igf, sts[ch_core]->hIGFEnc->igfData.igfInfo.grid, 0 ); + } + + IF( sts[ch_core]->igf ) + { + /* calculate the igf start band from the igf start line */ + stereo_mdct_init_igf_start_band_fx( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20, 16384 /* 1.0f in Q14 */, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); + + stereo_mdct_init_igf_start_band_fx( &hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10, 8192 /* 0.5f in Q14 */, sts[ch_core]->bwidth, sts[ch_core]->total_brate ); + } + ELSE + { + hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20.sfbIgfStart = -1; + hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10.sfbIgfStart = -1; + hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10.nBandsStereoCore = hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX10.sfbCnt; + hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20.nBandsStereoCore = hMCT->hBlockData[ch]->hStereoMdct->stbParamsTCX20.sfbCnt; + move16(); + move16(); + move16(); + move16(); + } + } + + FOR( ch = 0; ch < nChannels; ch++ ) + { + st = sts[ch]; + + IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + CONTINUE; + } + + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + } + + FOR( n = 0; n < nSubframes; n++ ) + { + st->side_bits_frame_channel = add( st->side_bits_frame_channel, NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); + move16(); + } + + /* Add estimated stereo bits */ + st->side_bits_frame_channel = add( st->side_bits_frame_channel, NBBITS_MCT_RATIO ); + move16(); + } + + /*--------------------------------------------------------------* + * MCT algorithm + *---------------------------------------------------------------*/ + +#if 1 // Float to Fixed, to be removed + Word16 q_spec = Q31; + Word16 length; + + FOR( ch = 0; ch < nChannels; ch++ ) + { + length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + IF( sts[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + FOR( Word16 k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + if ( sts[ch]->hTcxEnc->spectrum[0] ) + { + q_spec = s_min( q_spec, Q_factor_arrL( sts[ch]->hTcxEnc->spectrum[k], length ) - 1 ); + } + IF( mdst_spectrum[ch][0] ) + { + q_spec = s_min( q_spec, Q_factor_arrL( mdst_spectrum[ch][k], length ) - 1 ); + } + } + } + + FOR( ch = 0; ch < nChannels; ch++ ) + { + length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + IF( sts[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + FOR( Word16 k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + if ( sts[ch]->hTcxEnc->spectrum[0] ) + { + floatToFixed_arrL32( sts[ch]->hTcxEnc->spectrum[k], sts[ch]->hTcxEnc->spectrum_fx[k], q_spec, length ); + sts[ch]->hTcxEnc->spectrum_e[k] = sub( Q31, q_spec ); + } + if ( mdst_spectrum[ch][0] ) + { + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_spec, length ); + } + } + } +#endif // 1 + + apply_MCT_enc_fx( hMCT, sts, mdst_spectrum_fx, inv_spectrum_fx, inv_mdst_spectrum_fx, nChannels ); + +#if 1 // Fixed to Float, to be removed + FOR( ch = 0; ch < nChannels; ch++ ) + { + if ( sts[ch]->hTcxEnc->spectrum[0] ) + { + q_spec = 31 - sts[ch]->hTcxEnc->spectrum_e[0]; + } + length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + IF( sts[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + FOR( Word16 k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + if ( sts[ch]->hTcxEnc->spectrum[0] ) + { + fixedToFloat_arrL32( sts[ch]->hTcxEnc->spectrum_fx[k], sts[ch]->hTcxEnc->spectrum[k], q_spec, length ); + fixedToFloat_arrL32( inv_spectrum_fx[ch][k], inv_spectrum[ch][k], q_spec, length ); + } + if ( mdst_spectrum[ch][0] ) + { + fixedToFloat_arrL32( inv_mdst_spectrum_fx[ch][k], inv_mdst_spectrum[ch][k], q_spec, length ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_spec, length ); + } + } + } +#endif // 1 + + /*--------------------------------------------------------------* + * Power spectrum calculation for Noise Estimation + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < nChannels; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + nSubframes = ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX / nSubframes; + /* in MCT only relevant for bitrate switching from non-MCT bitrates */ + if ( sts[ch]->last_core == ACELP_CORE ) + { + L_subframeTCX += L_subframeTCX / 4; + } + + for ( n = 0; n < nSubframes; n++ ) + { + if ( sts[ch]->hTcxEnc->tns_ms_flag[n] ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpec[ch][i + n * L_subframeTCX] = mdst_spectrum[ch][n][i] * mdst_spectrum[ch][n][i] + sts[ch]->hTcxEnc->spectrum[n][i] * sts[ch]->hTcxEnc->spectrum[n][i]; + powerSpecMsInv[ch][n][i] = inv_mdst_spectrum[ch][n][i] * inv_mdst_spectrum[ch][n][i] + inv_spectrum[ch][n][i] * inv_spectrum[ch][n][i]; + } + } + else + { + if ( hMCT->currBlockDataCnt > 0 ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + powerSpecMsInv[ch][n][0] = inv_spectrum[ch][n][0] * inv_spectrum[ch][n][0]; + + for ( i = 1; i < L_subframeTCX - 1; i++ ) + { + mdst = ( inv_spectrum[ch][n][i + 1] - inv_spectrum[ch][n][i - 1] ); /* An MDST estimate */ + powerSpecMsInv[ch][n][i] = mdst * mdst + inv_spectrum[ch][n][i] * inv_spectrum[ch][n][i]; + } + + powerSpecMsInv[ch][n][L_subframeTCX - 1] = inv_spectrum[ch][n][L_subframeTCX - 1] * inv_spectrum[ch][n][L_subframeTCX - 1]; + } + + /* power spectrum: MDCT^2 + MDST^2 */ + powerSpec[ch][n * L_subframeTCX] = sts[ch]->hTcxEnc->spectrum[n][0] * sts[ch]->hTcxEnc->spectrum[n][0]; + + for ( i = 1; i < L_subframeTCX - 1; i++ ) + { + mdst = ( sts[ch]->hTcxEnc->spectrum[n][i + 1] - sts[ch]->hTcxEnc->spectrum[n][i - 1] ); /* An MDST estimate */ + powerSpec[ch][i + n * L_subframeTCX] = mdst * mdst + sts[ch]->hTcxEnc->spectrum[n][i] * sts[ch]->hTcxEnc->spectrum[n][i]; + } + powerSpec[ch][L_subframeTCX - 1 + n * L_subframeTCX] = sts[ch]->hTcxEnc->spectrum[n][L_subframeTCX - 1] * sts[ch]->hTcxEnc->spectrum[n][L_subframeTCX - 1]; + } + } + } + + for ( ch = 0; ch < nChannels; ch++ ) + { + st = sts[ch]; + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + /* in MCT only relevant for bitrate switching from non-MCT bitrates */ + if ( st->last_core == ACELP_CORE ) + { + L_subframeTCX += L_subframeTCX / 4; + } + + if ( ( st->hTcxEnc->tcxMode == TCX_20 ) && ( st->total_brate < HQ_96k || st->igf ) ) + { + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + + ComputeSpectrumNoiseMeasure( powerSpec[ch], st->hTcxEnc->L_frameTCX, st->hTcxEnc->nmStartLine, ( st->L_frame * st->last_sr_core != st->L_frame_past * st->sr_core ) || ( st->last_core != TCX_20_CORE ), st->hTcxEnc->memQuantZeros, st->hTcxEnc->L_frameTCX ); + } + + st->hTcxEnc->measuredBwRatio_flt = 1.f; /* No bandwidth limit for the noise filling */ + } + + if ( sts[0]->igf ) + { + if ( hMCT->currBlockDataCnt > 0 ) + { + mctStereoIGF_enc( hMCT, sts, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); + } + else + { + for ( ch = 0; ch < nChannels; ch++ ) + { + st = sts[ch]; + + /* update the pointer to the buffer of indices of the second channel */ + if ( ch > 0 ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + if ( + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + + if ( st->igf ) + { + for ( n = 0; n < nSubframes; n++ ) + { + ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + } + } + } + } + + /*write IGF data to bitstream*/ + for ( ch = 0; ch < nChannels; ch++ ) + { + st = sts[ch]; + if ( + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + enc_prm_igf_mdct( st, hBstr ); + } + } + + /* correct side bits per channel*/ + for ( ch = 0; ch < nChannels; ch++ ) + { + st = sts[ch]; + + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + st->side_bits_frame_channel -= NBBITS_MCT_RATIO; /* Subtract estimated stereo bits */ + total_side_bits += st->side_bits_frame_channel; + } + + /*--------------------------------------------------------------* + * Bitrate distribution among channels and MCT bitstream writing + *---------------------------------------------------------------*/ +#if 1 // Float to fixed conversion, to be removed + FOR( Word16 pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- ) + { + IF( hMCT->hBlockData[pair]->hStereoMdct->hItd ) + { + hMCT->hBlockData[pair]->hStereoMdct->hItd->itd_fx[1] = float_to_fix( hMCT->hBlockData[pair]->hStereoMdct->hItd->itd[1], Q23 ); + } + } +#endif + write_mct_bitstream_fx( sts, hMCT, nChannels ); + + FindChannelRatio( sts, chBitRatios, nChannels ); + + nAvailBits = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - NBITS_BWIDTH - hMCT->nBitsMCT - lfe_bits ); + + + /* subtract IVAS format signaling bits */ + if ( ivas_format == MC_FORMAT ) + { + nAvailBits -= IVAS_FORMAT_SIGNALING_NBITS; + nAvailBits -= MC_LS_SETUP_BITS; + } + else if ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) + { + nAvailBits -= IVAS_FORMAT_SIGNALING_NBITS_EXTENDED; + nAvailBits -= SBA_ORDER_BITS + SBA_PLANAR_BITS; + if ( ivas_format == SBA_ISM_FORMAT && nChannels > 4 ) + { + nAvailBits -= IVAS_COMBINED_FORMAT_SIGNALLING_BITS; + } + } + + for ( cpe_id = 0, i = 0; cpe_id < nCPE; cpe_id++ ) + { + if ( hCPE[cpe_id]->hMetaData != NULL ) + { + nAvailBits -= hCPE[cpe_id]->hMetaData->nb_bits_tot; + } + } + + /*substract bits needed for the bitrate ratios */ + for ( ch = 0; ch < nChannels; ch++ ) + { + if ( + sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + nAvailBits -= NBBITS_MCT_RATIO; + } + nAvailBits -= total_side_bits + hMCT->nchan_out_woLFE; /* if MC 1 extra bit that was initially send to signal LFE_off */ + + + if ( hMCT->hbr_mct ) + { + assert( ivas_total_brate >= IVAS_256k ); + AdjustChannelRatios( chBitRatios, nChannels, ivas_total_brate, nAvailBits, sba_order ); + } + + for ( ch = 0; ch < nChannels; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + push_next_indice( hBstr, chBitRatios[ch], NBBITS_MCT_RATIO ); + } + + /*distribute bits amongst channels*/ + splitAvailableBitsMCT( (void **) sts, nAvailBits, chBitRatios, ENC, nChannels ); + + for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = hCPE[cpe_id]->hCoreCoder[ch]; + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st->total_brate = ( st->bits_frame_channel + st->side_bits_frame_channel ) * FRAMES_PER_SEC; + } + } + + + pop_wmops(); + + return; +} +#endif diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index e0e9d5cbc..89515091f 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -40,6 +40,7 @@ #include "ivas_prot.h" #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" #include "ivas_prot_fx.h" #endif @@ -79,6 +80,14 @@ static void set_mct_enc_params( { set_f( hMCT->lastxCorrMatrix[n], 0, MCT_MAX_CHANNELS ); } +#ifdef IVAS_FLOAT_FIXED + FOR( n = 0; n < MCT_MAX_CHANNELS; n++ ) + { + set32_fx( hMCT->lastxCorrMatrix_fx[n], 0, MCT_MAX_CHANNELS ); + } + hMCT->lastxCorrMatrix_e = 0; + move16(); +#endif } hMCT->hbr_mct = 0; @@ -157,7 +166,7 @@ static void map_input_to_cpe_channels( * * Multi-Channel Coding Tool (MCT) encoding routine *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_mct_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ float *data[MCT_MAX_CHANNELS], /* i : input signal buffers */ @@ -169,6 +178,9 @@ ivas_error ivas_mct_enc( MCT_ENC_HANDLE hMCT; CPE_ENC_HANDLE hCPE; float mdst_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; +#ifdef IVAS_FLOAT_FIXED + Word32 orig_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; +#endif // IVAS_FLOAT_FIXED float orig_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; int16_t switch_bw; IVAS_FORMAT ivas_format; @@ -196,6 +208,9 @@ ivas_error ivas_mct_enc( { hCPE = st_ivas->hCPE[cpe_id]; hMCT->p_mdst_spectrum_long[cpe_id][n] = mdst_spectrum_long[cpe_id][n]; +#ifdef IVAS_FLOAT_FIXED + hMCT->p_orig_spectrum_long_fx[cpe_id][n] = orig_spectrum_long_fx[cpe_id][n]; +#endif // IVAS_FLOAT_FIXED hMCT->p_orig_spectrum_long[cpe_id][n] = orig_spectrum_long[cpe_id][n]; hCPE->hCoreCoder[n]->input_bwidth = hCPE->hCoreCoder[n]->last_input_bwidth; /* updated in BWD */ hCPE->hCoreCoder[n]->bwidth = hCPE->hCoreCoder[n]->last_bwidth; /* updated in BWD */ @@ -224,11 +239,7 @@ ivas_error ivas_mct_enc( for ( n = 0; n < (int16_t) ( hMCT->nchan_out_woLFE * 0.5 ); n++ ) { -#ifndef IVAS_FLOAT_FIXED initMdctStereoEncData( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, st_ivas->hCPE[0]->hCoreCoder[0]->igf ? st_ivas->hCPE[0]->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid : NULL, 0 ); -#else - initMdctStereoEncData_fx( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, st_ivas->hCPE[0]->hCoreCoder[0]->igf ? st_ivas->hCPE[0]->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid : NULL, 0 ); -#endif } } @@ -275,7 +286,148 @@ ivas_error ivas_mct_enc( pop_wmops(); return error; } +#else +ivas_error ivas_mct_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + float *data[MCT_MAX_CHANNELS], /* i : input signal buffers */ + const Word16 input_frame, /* i : input frame length per channel */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +) +{ + Word16 n, cpe_id; + MCT_ENC_HANDLE hMCT; + CPE_ENC_HANDLE hCPE; + float mdst_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; + float orig_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; + Word32 mdst_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; + Word32 orig_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS][L_FRAME48k]; + Word16 switch_bw; + IVAS_FORMAT ivas_format; + Word16 max_bwidth; + Word32 ivas_total_brate; + ivas_error error; + float *pdata[MAX_INPUT_CHANNELS]; + + error = IVAS_ERR_OK; + move32(); + + push_wmops( "ivas_mct_enc" ); + + /* Initialization */ + hMCT = st_ivas->hMCT; + hMCT->hBstr = st_ivas->hCPE[0]->hCoreCoder[0]->hBstr; /* pointer to write MCT side bits */ + + ivas_format = st_ivas->hEncoderConfig->ivas_format; + max_bwidth = st_ivas->hEncoderConfig->max_bwidth; + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + move32(); + move16(); + move32(); + + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + hCPE = st_ivas->hCPE[cpe_id]; +#if 1 // float initialization to be removed + hMCT->p_mdst_spectrum_long[cpe_id][n] = mdst_spectrum_long[cpe_id][n]; + hMCT->p_orig_spectrum_long[cpe_id][n] = orig_spectrum_long[cpe_id][n]; +#endif + + hMCT->p_mdst_spectrum_long_fx[cpe_id][n] = mdst_spectrum_long_fx[cpe_id][n]; + hMCT->p_orig_spectrum_long_fx[cpe_id][n] = orig_spectrum_long_fx[cpe_id][n]; + + hCPE->hCoreCoder[n]->input_bwidth = hCPE->hCoreCoder[n]->last_input_bwidth; /* updated in BWD */ + hCPE->hCoreCoder[n]->bwidth = hCPE->hCoreCoder[n]->last_bwidth; /* updated in BWD */ + move16(); + move16(); + /* reset channel mode from previous state*/ + IF( ( hCPE->cpe_id * CPE_CHANNELS + n ) >= hMCT->nchan_out_woLFE ) + { + hCPE->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + move32(); + } + ELSE + { + hCPE->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + move32(); + } + } + } + /* reconfiguration in case of bitrate switching */ + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + Word32 cp_bitrate; + // cp_bitrate = ivas_total_brate / hMCT->nchan_out_woLFE * CPE_CHANNELS; + cp_bitrate = L_shl( L_deposit_l( div_l( ivas_total_brate, hMCT->nchan_out_woLFE ) ), 2 ); // a/b => div_l(a, b/2) or (2 * div_l(a, b)) + + IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + // cp_bitrate = ivas_total_brate / st_ivas->nchan_transport * CPE_CHANNELS; + cp_bitrate = L_shl( L_deposit_l( div_l( ivas_total_brate, st_ivas->nchan_transport ) ), 2 ); // a/b => div_l(a, b/2) or (2 * div_l(a, b)) + } + + IF( st_ivas->hCPE[0]->hCoreCoder[0]->igf ) + { + FOR( n = 0; n < shr( hMCT->nchan_out_woLFE, 1 ); n++ ) + { + initMdctStereoEncData_fx( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, st_ivas->hCPE[0]->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid, 0 ); + } + } + ELSE + { + FOR( n = 0; n < shr( hMCT->nchan_out_woLFE, 1 ); n++ ) + { + initMdctStereoEncData_fx( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, NULL, 0 ); + } + } + } + + /* set coded audio band-width */ + switch_bw = set_bw_mct_fx( st_ivas->hCPE, st_ivas->nCPE ); + + /*for MC and MCT remove pointer to LFE input that has been processed separately */ + map_input_to_cpe_channels( st_ivas, pdata, data ); + + /* pre-processing */ + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + IF( ( error = ivas_cpe_enc( st_ivas, cpe_id, pdata[cpe_id * CPE_CHANNELS], pdata[cpe_id * CPE_CHANNELS + 1], input_frame, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* joint MCT encoding */ + ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE, hMCT->nchan_out_woLFE, ivas_total_brate, switch_bw, ( ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0, st_ivas->hEncoderConfig->sba_order ); + + /* Spectrum quantization and coding */ + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + hCPE = st_ivas->hCPE[cpe_id]; + + if ( cpe_id > 0 ) + { + hCPE->hCoreCoder[0]->hBstr->ind_list = st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->ind_list + st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->nb_ind_tot; + } + + ivas_mdct_quant_coder( hCPE, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); + + /* update input samples buffer (as done in ivas_cpe_enc() for other than MCT coding) */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + mvr2r( hCPE->hCoreCoder[n]->input, hCPE->hCoreCoder[n]->old_input_signal, input_frame ); + + /* common encoder updates */ + updt_enc_common( hCPE->hCoreCoder[n] ); + } + } + + pop_wmops(); + return error; +} +#endif /*------------------------------------------------------------------------- * create_mct_enc() diff --git a/lib_enc/ivas_mct_enc_mct.c b/lib_enc/ivas_mct_enc_mct.c index d3628b7e1..0a4659182 100644 --- a/lib_enc/ivas_mct_enc_mct.c +++ b/lib_enc/ivas_mct_enc_mct.c @@ -46,8 +46,10 @@ * Local constants *---------------------------------------------------------------*/ -#define SPAR_CORR_THRES 0.9f -#define DEFAULT_CORR_THRES 0.3f +#define SPAR_CORR_THRES 0.9f +#define DEFAULT_CORR_THRES 0.3f +#define SPAR_CORR_THRES_Q31 1932735283 +#define DEFAULT_CORR_THRES_Q31 644245094 /*------------------------------------------------------------------------- * getChannelEnergies() @@ -85,6 +87,64 @@ void getChannelEnergies( return; } +#ifdef IVAS_FLOAT_FIXED +void getChannelEnergies_fx( + Encoder_State **sts, /* i/o: Encoder state structure */ + Word32 nrg[MCT_MAX_CHANNELS], /* o : buffer with energies for each channel */ + Word16 nrg_e[MCT_MAX_CHANNELS], /* o : exponents of energies for each channel */ + const Word16 nchan /* i : number of channels */ +) +{ + Word16 ch, n, gb, sum2_e; + Word32 sum2; + Word16 nSubframes, L_subframe; + Encoder_State *st; + + /* Calculate energies per channel */ + FOR( ch = 0; ch < nchan; ch++ ) + { + st = sts[ch]; + IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + L_subframe = st->hTcxEnc->L_frameTCX; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + L_subframe = shr( st->hTcxEnc->L_frameTCX, 1 ); + } + + gb = find_guarded_bits_fx( (Word32) L_subframe ); + + sum2_e = st->hTcxEnc->spectrum_e[0]; + move16(); + nrg[ch] = 0; + move32(); + FOR( n = 0; n < nSubframes; n++ ) + { + sum2 = sum2_32_exp_fx( st->hTcxEnc->spectrum_fx[n], L_subframe, &sum2_e, gb ); + + nrg[ch] = BASOP_Util_Add_Mant32Exp( nrg[ch], nrg_e[ch], sum2, sum2_e, &nrg_e[ch] ); + move32(); + + sum2_e = st->hTcxEnc->spectrum_e[0]; + move16(); + } + + nrg[ch] = Sqrt32( nrg[ch], &nrg_e[ch] ); + move32(); + } + } + + return; +} +#endif /*------------------------------------------------------------------------- @@ -92,7 +152,7 @@ void getChannelEnergies( * * find channel pair with highest cross-correlation *-------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void getNextBestCorrelation( float xCorrMatrix[][MCT_MAX_CHANNELS], /* i : cross-correlation matrix */ int16_t *_ch1, /* o : first channel of selected channel-pair */ @@ -145,6 +205,69 @@ static void getNextBestCorrelation( return; } +#else +static void getNextBestCorrelation_fx( + Word32 xCorrMatrix[][MCT_MAX_CHANNELS], /* i : cross-correlation matrix, Qx */ + Word16 *_ch1, /* o : first channel of selected channel-pair */ + Word16 *_ch2, /* o : second channel of selected channel-pair, Qx */ + Word32 *max_corr, /* o : normalized cross correlation value of selected channel pair */ + const Word16 sortInd, + const Word16 nChannels ) +{ + Word32 tmp_corrVals[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2]; + Word16 tmp_org[( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2]; + Word16 i, tmp_idx; + Word16 ch1, ch2; + + set32_fx( tmp_corrVals, 0, ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 ); + + /* first sort correlation matrix */ + i = 0; + move16(); + FOR( ch1 = 0; ch1 < nChannels; ch1++ ) + { + FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ ) + { + IF( L_abs( xCorrMatrix[ch1][ch2] ) > 0 ) + { + assert( i < ( MCT_MAX_CHANNELS * ( MCT_MAX_CHANNELS - 1 ) ) / 2 ); + tmp_corrVals[i] = L_abs( xCorrMatrix[ch1][ch2] ); + move32(); + i = add( i, 1 ); + } + } + } + + tmp_idx = sub( shr( imult1616( nChannels, sub( nChannels, 1 ) ), 1 ), 1 ); + + /* sort values */ + v_sort_ind_fixed( tmp_corrVals, tmp_org, add( tmp_idx, 1 ) ); + + /* get max, or 2nd max and so on depending on sortInd value */ + *max_corr = tmp_corrVals[sub( tmp_idx, sortInd )]; + move32(); + + /*find channel pair for this max_corr*/ + FOR( ch1 = 0; ch1 < nChannels; ch1++ ) + { + FOR( ch2 = ch1 + 1; ch2 < nChannels; ch2++ ) + { + IF( EQ_32( L_abs( xCorrMatrix[ch1][ch2] ), *max_corr ) ) + { + *_ch1 = ch1; + *_ch2 = ch2; + *max_corr = xCorrMatrix[ch1][ch2]; /* assign to max_corr its actual value */ + move16(); + move16(); + move32(); + BREAK; + } + } + } + + return; +} +#endif /*-----------------------------------------------------------------------* @@ -153,7 +276,7 @@ static void getNextBestCorrelation( * calculates the cross correlation matrix for all active * channels *-----------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void getCorrelationMatrix( Encoder_State **sts, /* i : core coder handle */ MCT_ENC_HANDLE hMCT, /* i : MCT handle */ @@ -206,6 +329,125 @@ static void getCorrelationMatrix( return; } +#else +static void getCorrelationMatrix_fx( + Encoder_State **sts, /* i : core coder handle */ + MCT_ENC_HANDLE hMCT, /* i : MCT handle */ + Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS], /* o : cross-correlation matrix, exponent: xCorrMatrix_e */ + Word16 *xCorrMatrix_e /* o : exponent of cross-correlation matrix */ +) +{ + Word16 ch1, ch2, n, nchan, res_q, s, max_e; + Word16 xCorrMatrix_exp[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; + Word32 L_tmp; + Word64 W_tmp; + + nchan = hMCT->nchan_out_woLFE; + move16(); + + /* correlation */ + FOR( ch1 = 0; ch1 < nchan; ch1++ ) + { + FOR( ch2 = ch1; ch2 < nchan; ch2++ ) + { + xCorrMatrix[ch1][ch2] = 0; + move32(); + xCorrMatrix_exp[ch1][ch2] = 0; + move16(); + + test(); + test(); + IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) && + NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + Word16 nSubframes; + Word16 L_subframe; + IF( EQ_16( sts[ch1]->core, TCX_20 ) ) + { + nSubframes = 1; + move16(); + L_subframe = sts[ch1]->hTcxEnc->L_frameTCX; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + L_subframe = shr( sts[ch1]->hTcxEnc->L_frameTCX, 1 ); + } + + FOR( n = 0; n < nSubframes; n++ ) + { + res_q = sub( 31, sts[0]->hTcxEnc->spectrum_e[0] ); + L_tmp = dotp_fixed_32( sts[ch1]->hTcxEnc->spectrum_fx[n], sts[ch2]->hTcxEnc->spectrum_fx[n], L_subframe, 1 /*find_guarded_bits_fx( L_subframe )*/, &res_q ); + + xCorrMatrix[ch1][ch2] = BASOP_Util_Add_Mant32Exp( xCorrMatrix[ch1][ch2], xCorrMatrix_exp[ch1][ch2], L_tmp, sub( 31, res_q ), &xCorrMatrix_exp[ch1][ch2] ); + move32(); + } + } + } + } + + /* normalize */ + FOR( ch1 = 0; ch1 < nchan; ch1++ ) + { + FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ ) + { + // tmp = sqrtf( xCorrMatrix[ch1][ch1] * xCorrMatrix[ch2][ch2] ); + W_tmp = W_mult0_32_32( xCorrMatrix[ch1][ch1], xCorrMatrix[ch2][ch2] ); + s = W_norm( W_tmp ); + L_tmp = W_extract_h( W_shl( W_tmp, s ) ); + + s = sub( add( s, 30 ), add( xCorrMatrix_exp[ch1][ch1], xCorrMatrix_exp[ch2][ch2] ) ); // s = s + ( 31 - xCorrMatrix_exp[ch1][ch1] ) + ( 31 - xCorrMatrix_exp[ch2][ch2] ) - 32; + s = sub( 31, s ); + L_tmp = Sqrt32( L_tmp, &s ); + + IF( L_tmp > 0 ) + { + // xCorrMatrix[ch1][ch2] /= tmp; + xCorrMatrix[ch1][ch2] = L_deposit_h( BASOP_Util_Divide3232_Scale( xCorrMatrix[ch1][ch2], L_tmp, &res_q ) ); + xCorrMatrix_exp[ch1][ch2] = add( res_q, sub( xCorrMatrix_exp[ch1][ch2], s ) ); + move32(); + move16(); + } + ELSE + { + xCorrMatrix[ch1][ch2] = 0; + xCorrMatrix_exp[ch1][ch2] = 0; + move32(); + move16(); + } + } + } + + /* Aligning the variable exponents for each element to a common exponent */ + s = 31; + *xCorrMatrix_e = 0; + move16(); + move16(); + + FOR( ch1 = 0; ch1 < nchan - 1; ch1++ ) + { + s = s_min( s, getScaleFactor32( &xCorrMatrix[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ) ) ); + maximum_s( &xCorrMatrix_exp[ch1][ch1 + 1], sub( nchan, add( ch1, 1 ) ), &max_e ); + *xCorrMatrix_e = s_max( *xCorrMatrix_e, max_e ); + move16(); + } + + FOR( ch1 = 0; ch1 < nchan; ch1++ ) + { + FOR( ch2 = ch1 + 1; ch2 < nchan; ch2++ ) + { + xCorrMatrix[ch1][ch2] = L_shl_sat( xCorrMatrix[ch1][ch2], add( s, sub( xCorrMatrix_exp[ch1][ch2], *xCorrMatrix_e ) ) ); + move32(); + } + } + *xCorrMatrix_e = sub( *xCorrMatrix_e, s ); + move16(); + + return; +} +#endif /*-----------------------------------------------------------------* @@ -213,7 +455,7 @@ static void getCorrelationMatrix( * * searches for the best correlated channel pair *------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void getBestCorrelation( MCT_ENC_HANDLE hMCT, /* i : MCT handle */ int16_t *_ch1, /* o : first channel of selected channel-pair */ @@ -243,13 +485,50 @@ static void getBestCorrelation( return; } +#else +static void getBestCorrelation_fx( + MCT_ENC_HANDLE hMCT, /* i : MCT handle */ + Word16 *_ch1, /* o : first channel of selected channel-pair, Q0 */ + Word16 *_ch2, /* o : second channel of selected channel-pair, Q0 */ + Word32 *max_corr, /* o : normalized cross correlation value of selected channel pair, Qx */ + Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] ) /* i : cross-correlation matrix, Qx */ +{ + Word16 ch1, ch2; + + *_ch1 = -1; + *_ch2 = -1; + *max_corr = 0; + move16(); + move16(); + move32(); + + FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ ) + { + FOR( ch2 = ch1 + 1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ ) + { + IF( LT_32( L_abs( *max_corr ), L_abs( xCorrMatrix[ch1][ch2] ) ) ) + { + *max_corr = xCorrMatrix[ch1][ch2]; + move32(); + + *_ch1 = ch1; + *_ch2 = ch2; + move16(); + move16(); + } + } + } + + return; +} +#endif /*----------------------------------------------------------------------* * getBlockValues() * stereo processing for the channels of current block *----------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void getBlockValues( Encoder_State **sts, /* i/o: core coder handle */ const int16_t ch1, /* i : first channel of channel-pair */ @@ -282,79 +561,65 @@ static void getBlockValues( p_st[0] = sts[ch1]; p_st[1] = sts[ch2]; -#ifndef IVAS_FLOAT_FIXED stereo_coder_tcx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1 ); -#else -#if 1 - Word16 k; - Word32 *p_inv_spectrum_fx[2][2]; - Word16 q_spec = Q31; - Word16 length; - Word32 *p_inv_mdst_spectrum_fx[2][2]; - Word32 *p_mdst_spectrum_fx[2][2]; - FOR( Word16 ch = 0; ch < CPE_CHANNELS; ch++ ) - { - length = p_st[ch]->hTcxEnc->L_frameTCX / ( ( p_st[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); - IF( p_st[ch]->last_core == ACELP_CORE ) - { - length += length / 4; - } - FOR( k = 0; k <= ( ( p_st[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) - { - p_inv_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); - p_inv_mdst_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); - p_mdst_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); - q_spec = s_min( q_spec, Q_factor_arrL( p_st[ch]->hTcxEnc->spectrum[k], length ) - 1 ); - q_spec = s_min( q_spec, Q_factor_arrL( p_mdst_spectrum[ch][k], length ) - 1 ); - } - } - FOR( Word16 ch = 0; ch < CPE_CHANNELS; ch++ ) + if ( ( sts[ch1]->core == TCX_20_CORE && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) || ( sts[ch1]->core == TCX_10_CORE && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO && hBlock->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) ) { - length = p_st[ch]->hTcxEnc->L_frameTCX / ( ( p_st[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); - IF( p_st[ch]->last_core == ACELP_CORE ) - { - length += length / 4; - } - FOR( k = 0; k <= ( ( p_st[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) - { - floatToFixed_arrL32( p_st[ch]->hTcxEnc->spectrum[k], p_st[ch]->hTcxEnc->spectrum_fx[k], q_spec, length ); - p_st[ch]->hTcxEnc->spectrum_e[k] = sub( Q31, q_spec ); - floatToFixed_arrL32( p_mdst_spectrum[ch][k], p_mdst_spectrum_fx[ch][k], q_spec, length ); - } + hBlock->isActive = 0; } -#endif - stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum_fx, p_inv_spectrum_fx, p_inv_mdst_spectrum_fx, 1, q_spec ); -#if 1 - FOR( Word16 ch = 0; ch < CPE_CHANNELS; ch++ ) + return; +} +#else +static void getBlockValues_fx( + Encoder_State **sts, /* i/o: core coder handle */ + const Word16 ch1, /* i : first channel of channel-pair */ + const Word16 ch2, /* i : second channel of channel-pair */ + MCT_BLOCK_DATA *hBlock, /* i : stereo block handle */ + Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: MDST spectrum, Q = q_spec */ + Word32 *inv_spectrum[MCT_MAX_CHANNELS][2], /* i/o: inverse spectrum, Q = q_spec */ + Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: invers MDST spectrum, Q = q_spec */ + Word16 q_spec /* i : common Q factor of the above spectrum buffers */ +) +{ + Word16 n; + Word32 *p_mdst_spectrum[2][2]; + Word32 *p_inv_spectrum[2][2]; + Word32 *p_inv_mdst_spectrum[2][2]; + Encoder_State *p_st[2]; + + /* init return values: */ + hBlock->isActive = 1; + move16(); + + /* map vectors to current block channels */ + FOR( n = 0; n < 2; n++ ) { - length = p_st[ch]->hTcxEnc->L_frameTCX / ( ( p_st[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); - IF( p_st[ch]->last_core == ACELP_CORE ) - { - length += length / 4; - } - FOR( k = 0; k <= ( ( p_st[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) - { - fixedToFloat_arrL32( p_st[ch]->hTcxEnc->spectrum_fx[k], p_st[ch]->hTcxEnc->spectrum[k], q_spec, length ); - fixedToFloat_arrL32( p_inv_spectrum_fx[ch][k], p_inv_spectrum[ch][k], q_spec, length ); - fixedToFloat_arrL32( p_inv_mdst_spectrum_fx[ch][k], p_inv_mdst_spectrum[ch][k], q_spec, length ); - fixedToFloat_arrL32( p_mdst_spectrum_fx[ch][k], p_mdst_spectrum[ch][k], q_spec, length ); - free( p_inv_spectrum_fx[ch][k] ); - free( p_inv_mdst_spectrum_fx[ch][k] ); - free( p_mdst_spectrum_fx[ch][k] ); - } + p_mdst_spectrum[0][n] = mdst_spectrum[ch1][n]; + p_mdst_spectrum[1][n] = mdst_spectrum[ch2][n]; + p_inv_spectrum[0][n] = inv_spectrum[ch1][n]; + p_inv_spectrum[1][n] = inv_spectrum[ch2][n]; + p_inv_mdst_spectrum[0][n] = inv_mdst_spectrum[ch1][n]; + p_inv_mdst_spectrum[1][n] = inv_mdst_spectrum[ch2][n]; } -#endif -#endif + p_st[0] = sts[ch1]; + p_st[1] = sts[ch2]; - if ( ( sts[ch1]->core == TCX_20_CORE && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) || ( sts[ch1]->core == TCX_10_CORE && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO && hBlock->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) ) + stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1, q_spec ); + + test(); + test(); + test(); + test(); + if ( ( EQ_16( sts[ch1]->core, TCX_20_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) || ( EQ_16( sts[ch1]->core, TCX_10_CORE ) && hBlock->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO && hBlock->hStereoMdct->mdct_stereo_mode[1] == SMDCT_DUAL_MONO ) ) { hBlock->isActive = 0; + move16(); } return; } +#endif /*-------------------------------------------------------------------* @@ -363,7 +628,7 @@ static void getBlockValues( * updates the cross correlation matrix with modified spectra after * stereo block processing *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void updateCorrelationMatrix( Encoder_State **sts, MCT_ENC_HANDLE hMCT, @@ -396,13 +661,64 @@ static void updateCorrelationMatrix( return; } +#else +static void updateCorrelationMatrix_fx( + Encoder_State **sts, + MCT_ENC_HANDLE hMCT, + const Word16 _ch1, + const Word16 _ch2, + Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS] // Qx +) +{ + Word16 ch1, ch2, n; + + /* correlation: */ + FOR( ch1 = 0; ch1 < ( hMCT->nchan_out_woLFE ); ch1++ ) + { + FOR( ch2 = ch1; ch2 < ( hMCT->nchan_out_woLFE ); ch2++ ) + { + test(); + test(); + IF( EQ_16( sts[ch1]->core, sts[ch2]->core ) && NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) && + NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + Word16 nSubframes; + IF( EQ_16( sts[ch1]->core, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + } + + test(); + test(); + test(); + IF( EQ_16( ch1, _ch1 ) || EQ_16( ch2, _ch2 ) || EQ_16( ch1, _ch2 ) || EQ_16( ch2, _ch1 ) ) + { + FOR( n = 0; n < nSubframes; n++ ) + { + xCorrMatrix[ch1][ch2] = 0; /*disable combinations with channels already processed */ + move32(); + } + } + } + } + } + + return; +} +#endif /*----------------------------------------------------------* * channelPairToIndex() * get the index of each channel pair *----------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static int16_t channelPairToIndex( const int16_t chIdx1, const int16_t chIdx2, @@ -430,13 +746,43 @@ static int16_t channelPairToIndex( return -1; } +#else +static Word16 channelPairToIndex_fx( + const Word16 chIdx1, + const Word16 chIdx2, + const Word16 nChannels ) +{ + Word16 ch1, ch2; + Word16 pairIdx; + + pairIdx = 0; + move16(); + + FOR( ch2 = 1; ch2 < nChannels; ch2++ ) + { + FOR( ch1 = 0; ch1 < ch2; ch1++ ) + { + test(); + IF( EQ_16( ch1, chIdx1 ) && EQ_16( ch2, chIdx2 ) ) + { + return pairIdx; + } + ELSE + { + pairIdx = add( pairIdx, 1 ); + } + } + } + return -1; +} +#endif /*--------------------------------------------------------------------* * getGlobalILD() * get broadband ILD to mean energy and normalize channels with ratio *--------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void getGlobalILD( Encoder_State **sts, MCT_ENC_HANDLE hMCT, @@ -498,30 +844,147 @@ static void getGlobalILD( return; } +#else +static void getGlobalILD_fx( + Encoder_State **sts, + MCT_ENC_HANDLE hMCT, + Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], // Exponent is same as spectrum_fx i.e. spectrum_e + const Word16 nchan ) +{ + Word16 k, ch, nSubframes, L_subframe; + Word32 nrg[MCT_MAX_CHANNELS]; + Word16 nrg_e[MCT_MAX_CHANNELS]; + Word16 ratio_fx, qratio; + Word32 meanE = 0; + Word32 L_tmp; + Word16 cnt = 0, meanE_e = 0, L_tmp_e; + move32(); + move16(); + move16(); + /*Initializations*/ + set16_fx( hMCT->lowE_ch, 0, nchan ); -/*--------------------------------------------------------------------* - * apply_MCT_enc() - * - * apply MCT algorithm to input channels - *--------------------------------------------------------------------*/ + getChannelEnergies_fx( sts, nrg, nrg_e, nchan ); -void apply_MCT_enc( - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - Encoder_State **sts, /* i/o: encoder state structure */ - float *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ - float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ - float *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ - const int16_t nchan /* i : number of channels */ -) -{ - int16_t ch, k, ch1, ch2, nSubframes, L_subframeTCX; - float max_corr, qratio; - int16_t forceKeepTree, pair; - float sumCorrDiff, thr; - float xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; - int16_t currBlockDataCnt; - int16_t cpEle[MCT_MAX_CHANNELS]; + /*calculate total energy without LFE*/ + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + meanE = BASOP_Util_Add_Mant32Exp( meanE, meanE_e, nrg[ch], nrg_e[ch], &meanE_e ); + cnt = add( cnt, 1 ); + } + } + + /*calculate mean energy*/ + assert( cnt >= 2 ); + L_tmp = BASOP_Util_Divide3216_Scale( meanE, cnt, &L_tmp_e ); + L_tmp_e = add( L_tmp_e, sub( meanE_e, 15 ) ); + + // meanE = max( meanE / cnt, EPSILON ); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, EPSILON_FX_M, EPSILON_FX_E ), 1 ) ) + { + meanE = L_deposit_h( (Word16) L_tmp ); + meanE_e = L_tmp_e; + move32(); + move16(); + } + ELSE + { + meanE = EPSILON_FX_M; + meanE_e = EPSILON_FX_E; + move32(); + move16(); + } + + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + L_subframe = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + L_subframe = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + } + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( nrg[ch], nrg_e[ch], meanE, meanE_e ), 1 ) ) /*change it to meanE if final solution*/ + { + // ratio_fx = meanE / nrg[ch]; + ratio_fx = BASOP_Util_Divide3232_Scale( meanE, nrg[ch], &L_tmp_e ); + L_tmp_e = add( L_tmp_e, sub( meanE_e, nrg_e[ch] ) ); + ratio_fx = shl_sat( ratio_fx, L_tmp_e ); + + hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) ); + move16(); + + qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE / 2 ); // Q11 + } + ELSE + { + // ratio_fx = nrg[ch] / meanE; + ratio_fx = BASOP_Util_Divide3232_Scale( nrg[ch], meanE, &L_tmp_e ); + L_tmp_e = add( L_tmp_e, sub( nrg_e[ch], meanE_e ) ); + ratio_fx = shl_sat( ratio_fx, L_tmp_e ); + + hMCT->lowE_ch[ch] = 1; + move16(); + + hMCT->mc_global_ild[ch] = s_max( 1, s_min( SMDCT_ILD_RANGE - 1, mult_r( SMDCT_ILD_RANGE, ratio_fx ) ) ); + move16(); + + qratio = shl_sat( div_l( ( (Word32) SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ), 1 ); // Q11 + } + + FOR( k = 0; k < nSubframes; k++ ) + { + sts[ch]->hTcxEnc->spectrum_e[k] = add( sts[ch]->hTcxEnc->spectrum_e[k], 4 ); // Updating exponent of spectrum as q_ratio is in Q11 + } + + FOR( k = 0; k < nSubframes; k++ ) + { + v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframe ); + v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframe ); + } + } + } + + + return; +} +#endif + + +/*--------------------------------------------------------------------* + * apply_MCT_enc() + * + * apply MCT algorithm to input channels + *--------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED +void apply_MCT_enc( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + float *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ + float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ + float *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ + const int16_t nchan /* i : number of channels */ +) +{ + int16_t ch, k, ch1, ch2, nSubframes, L_subframeTCX; + float max_corr, qratio; + int16_t forceKeepTree, pair; + float sumCorrDiff, thr; + float xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; + int16_t currBlockDataCnt; + int16_t cpEle[MCT_MAX_CHANNELS]; int16_t inactiveBlockDetected; int16_t tmp_ch1, tmp_ch2; float tmp_max_corr; @@ -722,14 +1185,291 @@ void apply_MCT_enc( return; } +#else +void apply_MCT_enc_fx( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ + Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ + Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ + const Word16 nchan /* i : number of channels */ +) +{ + Word16 ch, k, ch1, ch2, nSubframes, L_subframeTCX; + Word32 max_corr; + Word16 forceKeepTree, pair, qratio; + Word32 sumCorrDiff, thr; + Word32 xCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; + Word16 currBlockDataCnt; + Word16 cpEle[MCT_MAX_CHANNELS]; + Word16 inactiveBlockDetected; + Word16 tmp_ch1, tmp_ch2, tmp; + Word32 tmp_max_corr, L_tmp; + Word16 count_active_ch = 0; + Word16 xCorrMatrix_e = 0, sumCorrDiff_e = 0, L_tmp_e; + move16(); + move16(); + move16(); + + push_wmops( "mct_core_enc_mct" ); + + forceKeepTree = 1; + inactiveBlockDetected = 0; + move16(); + move16(); + set16_fx( cpEle, 0, MCT_MAX_CHANNELS ); + /*Determine active channels*/ + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + count_active_ch = add( count_active_ch, 1 ); + } + ELSE + { + hMCT->mc_global_ild[ch] = 0; + move16(); + } + } + + /*there should be at least one cp*/ + IF( GE_16( count_active_ch, CPE_CHANNELS ) ) + { + /*Normalize energies with global ILD*/ + getGlobalILD_fx( sts, hMCT, mdst_spectrum, nchan ); + getCorrelationMatrix_fx( sts, hMCT, xCorrMatrix, &xCorrMatrix_e ); + + /*check if previous tree should be kept*/ + sumCorrDiff = 0; + move32(); + // thr = 0.15f * (float) ( count_active_ch ) * ( count_active_ch - 1 ) / 2.0f; + thr = Mpy_32_16_1( 161061274, imult1616( count_active_ch, sub( count_active_ch, 1 ) ) ); /* Q16 */ /* 161061274 = 0.15 / 2 in Q31 */ + + FOR( ch2 = 1; ch2 < nchan; ch2++ ) + { + FOR( ch1 = 0; ch1 < ch2; ch1++ ) + { + test(); + IF( NE_32( sts[ch1]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) && + NE_32( sts[ch2]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + L_tmp = L_abs( BASOP_Util_Add_Mant32Exp( hMCT->lastxCorrMatrix_fx[ch1][ch2], hMCT->lastxCorrMatrix_e, L_negate( xCorrMatrix[ch1][ch2] ), xCorrMatrix_e, &L_tmp_e ) ); + sumCorrDiff = BASOP_Util_Add_Mant32Exp( sumCorrDiff, sumCorrDiff_e, L_tmp, L_tmp_e, &sumCorrDiff_e ); + } + } + } + + if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( sumCorrDiff, sumCorrDiff_e, thr, 15 ), 1 ) ) + { + forceKeepTree = 0; + move16(); + } + + /* check if keepTree is applied on unallowed blocks (e.g. channel pairs with different cores) */ + IF( forceKeepTree ) + { + IF( !hMCT->currBlockDataCnt ) + { + forceKeepTree = 0; + move16(); + } + ELSE + { + FOR( pair = 0; pair < hMCT->currBlockDataCnt; pair++ ) + { + if ( xCorrMatrix[hMCT->hBlockData[pair]->ch1][hMCT->hBlockData[pair]->ch2] == 0 ) + { + forceKeepTree = 0; + move16(); + } + } + } + } + + /*save initial correlation matrix for next frame*/ + FOR( ch1 = 0; ch1 < nchan; ch1++ ) + { + FOR( ch2 = ch1; ch2 < nchan; ch2++ ) + { + hMCT->lastxCorrMatrix_fx[ch1][ch2] = xCorrMatrix[ch1][ch2]; + move32(); + } + } + hMCT->lastxCorrMatrix_e = xCorrMatrix_e; + move16(); + move16(); + currBlockDataCnt = 0; + WHILE( LT_16( currBlockDataCnt, hMCT->nchan_out_woLFE ) ) + { + /* find best fitting channel pair: */ + ch1 = -1; + ch2 = -1; + max_corr = 0; + move16(); + move16(); + move32(); + + IF( !forceKeepTree ) + { + getNextBestCorrelation_fx( xCorrMatrix, &ch1, &ch2, &max_corr, inactiveBlockDetected, nchan ); + } + ELSE + { + getBestCorrelation_fx( hMCT, &tmp_ch1, &tmp_ch2, &tmp_max_corr, xCorrMatrix ); + + IF( EQ_16( currBlockDataCnt, hMCT->currBlockDataCnt ) ) + { + BREAK; + } + ELSE + { + ch1 = hMCT->hBlockData[currBlockDataCnt]->ch1; + ch2 = hMCT->hBlockData[currBlockDataCnt]->ch2; + move16(); + move16(); + + /*don't allow forcing of channel-pair if their correlation is under the threshold*/ + max_corr = xCorrMatrix[ch1][ch2]; + move32(); + + tmp = BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31 /* 0.3 in Q31 */, 0 ); + test(); + IF( EQ_16( tmp, -1 ) || tmp == 0 ) + { + ch1 = tmp_ch1; + ch2 = tmp_ch2; + max_corr = tmp_max_corr; + forceKeepTree = 0; + move16(); + move16(); + move32(); + move16(); + } + } + } + + test(); + test(); + test(); + IF( ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, DEFAULT_CORR_THRES_Q31, 0 ), 1 ) && !hMCT->hbr_mct ) || ( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_abs( max_corr ), xCorrMatrix_e, SPAR_CORR_THRES_Q31, 0 ), 1 ) && hMCT->hbr_mct ) ) + { + IF( !forceKeepTree ) + { + /*save channel pair*/ + hMCT->hBlockData[currBlockDataCnt]->ch1 = ch1; + hMCT->hBlockData[currBlockDataCnt]->ch2 = ch2; + move16(); + move16(); + } + + /* calculate all related values: */ + assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ); + + getBlockValues_fx( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum, sub( 31, sts[0]->hTcxEnc->spectrum_e[0] ) ); + + IF( hMCT->hBlockData[currBlockDataCnt]->isActive == 0 ) + { + inactiveBlockDetected = add( inactiveBlockDetected, 1 ); + IF( GT_16( inactiveBlockDetected, shr( hMCT->nchan_out_woLFE, 1 ) ) ) + { + BREAK; + } + forceKeepTree = 0; + move16(); + + CONTINUE; /* skip inactive blocks where stereo mode is dual-mono */ + } + + updateCorrelationMatrix_fx( sts, hMCT, ch1, ch2, xCorrMatrix ); + cpEle[ch1] = 1; + cpEle[ch2] = 1; + move16(); + move16(); + + currBlockDataCnt = add( currBlockDataCnt, 1 ); + } + ELSE + { + BREAK; + } + } + + /*save number of blocks for next frame*/ + hMCT->currBlockDataCnt = currBlockDataCnt; + move16(); + + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + test(); + IF( ( !cpEle[ch] ) || hMCT->currBlockDataCnt == 0 ) + { + IF( EQ_16( sts[ch]->core, TCX_20_CORE ) ) + { + nSubframes = 1; + move16(); + L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + L_subframeTCX = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + } + + IF( hMCT->lowE_ch[ch] ) + { + // qratio = (float) hMCT->mc_global_ild[ch] / SMDCT_ILD_RANGE; + qratio = div_l( L_shl( hMCT->mc_global_ild[ch], 11 ), SMDCT_ILD_RANGE / 2 ); // Q11 + } + ELSE + { + // qratio = (float) SMDCT_ILD_RANGE / hMCT->mc_global_ild[ch]; + qratio = shl_sat( div_l( ( (Word32) SMDCT_ILD_RANGE << 11 ), hMCT->mc_global_ild[ch] ), 1 ); // Q11 + } + + FOR( k = 0; k < nSubframes; k++ ) + { + v_multc_fixed( sts[ch]->hTcxEnc->spectrum_fx[k], L_deposit_h( qratio ), sts[ch]->hTcxEnc->spectrum_fx[k], L_subframeTCX ); + v_multc_fixed( mdst_spectrum[ch][k], L_deposit_h( qratio ), mdst_spectrum[ch][k], L_subframeTCX ); + set32_fx( inv_spectrum[ch][k], 0, L_subframeTCX ); + } + sts[ch]->hTcxEnc->spectrum_e[1] = add( sts[ch]->hTcxEnc->spectrum_e[0], 4 ); + sts[ch]->hTcxEnc->spectrum_e[0] = add( sts[ch]->hTcxEnc->spectrum_e[0], 4 ); + hMCT->mc_global_ild[ch] = 0; + move16(); + move16(); + move16(); + } + } + } + } + ELSE + { + hMCT->currBlockDataCnt = 0; + move16(); + FOR( ch = 0; ch < nchan; ch++ ) + { + hMCT->mc_global_ild[ch] = 0; + move16(); + } + } + + pop_wmops(); + + return; +} +#endif /*--------------------------------------------------------------------* * write_mct_bitstream() * * write mct metadata to bitstream *--------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void write_mct_bitstream( Encoder_State **sts, /* i/o: encoder state structure */ MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ @@ -781,10 +1521,6 @@ void write_mct_bitstream( p_st[1] = sts[hBlock->ch2]; /*then business as usual for each block pair */ -#ifdef IVAS_FLOAT_FIXED - IF( hMCT->hBlockData[pair]->hStereoMdct->hItd ) - hMCT->hBlockData[pair]->hStereoMdct->hItd->itd_fx[1] = float_to_fix( hMCT->hBlockData[pair]->hStereoMdct->hItd->itd[1], Q23 ); -#endif write_stereo_to_bitstream( hMCT->hBlockData[pair]->hStereoMdct, p_st, hBlock->mask, 1, hBstr ); } @@ -792,14 +1528,214 @@ void write_mct_bitstream( return; } +#else +void write_mct_bitstream_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + const Word16 nchan /* i : number of channels */ +) +{ + Word16 pair, ch; + Word16 channelPairIndex; + Word16 nbits_start; + MCT_BLOCK_DATA_HANDLE hBlock; + Encoder_State *p_st[2]; + BSTR_ENC_HANDLE hBstr = sts[0]->hBstr; + + nbits_start = hBstr->nb_bits_tot; + move16(); + + push_next_indice( hBstr, hMCT->currBlockDataCnt, MCT_NUM_BLOCK_DATA_BITS ); + + /* first write core info and overlap mode for all channels */ + FOR( ch = 0; ch < nchan; ch++ ) + { + test(); + IF( hMCT->currBlockDataCnt && NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + push_next_indice( hBstr, hMCT->mc_global_ild[ch], SMDCT_GLOBAL_ILD_BITS ); + } + } + + IF( hMCT->currBlockDataCnt ) + { + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + push_next_indice( hBstr, hMCT->lowE_ch[ch], 1 ); + } + } + } + + /* Do for each stereo block */ + FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- ) + { + hBlock = hMCT->hBlockData[pair]; + + /*calculate channel pair index and write it to BS*/ + channelPairIndex = channelPairToIndex_fx( hBlock->ch1, hBlock->ch2, nchan ); + push_next_indice( hBstr, channelPairIndex, hMCT->bitsChannelPairIndex ); + + /*point to encoder states of actual channels to write block pair bits*/ + p_st[0] = sts[hBlock->ch1]; + p_st[1] = sts[hBlock->ch2]; + + /*then business as usual for each block pair */ + write_stereo_to_bitstream( hMCT->hBlockData[pair]->hStereoMdct, p_st, hBlock->mask, 1, hBstr ); + } + + hMCT->nBitsMCT = sub( hBstr->nb_bits_tot, nbits_start ); + move16(); + return; +} +#endif /*--------------------------------------------------------------------* * mctStereoIGF_enc() * * IGF analysis of channels after MCT processing *--------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void mctStereoIGF_enc_fx( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ + Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif // IVAS_FLOAT_FIXED + float *orig_spectrum[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ + float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ +) +{ +#ifdef IVAS_FLOAT_FIXED + Word32 *p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; + Word32 *p_inv_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word32 *p_orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word32 *p_powerSpec_fx[NB_DIV]; +#endif // IVAS_FLOAT_FIXED + + UNUSED_PARAM( powerSpec_fx ); + int16_t b, nSubframes, L_subframeTCX; + int16_t p_ch[2], n, ch, ch1, ch2; + Encoder_State *p_st[NB_DIV]; + Encoder_State *st; + float *p_powerSpecMsInv[CPE_CHANNELS][NB_DIV]; + float *p_inv_spectrum[CPE_CHANNELS][NB_DIV]; + float *p_orig_spectrum[CPE_CHANNELS][NB_DIV]; + float *p_powerSpec[NB_DIV]; + int16_t singleChEle[MCT_MAX_CHANNELS]; + + L_subframeTCX = 0; /* to avoid compilation warning */ + set_s( singleChEle, 1, hMCT->nchan_out_woLFE ); + for ( b = 0; b < hMCT->currBlockDataCnt; b++ ) + { + ch1 = hMCT->hBlockData[b]->ch1; + ch2 = hMCT->hBlockData[b]->ch2; + + p_ch[0] = ch1; + p_ch[1] = ch2; + + singleChEle[hMCT->hBlockData[b]->ch1] = 0; + singleChEle[hMCT->hBlockData[b]->ch2] = 0; + + /* point to encoder states of actual channels to write block pair bits */ + p_st[0] = sts[ch1]; + p_st[1] = sts[ch2]; + + if ( ch1 > 0 ) + { + sts[ch1]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + + if ( ch2 > 0 ) + { + sts[ch2]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + +#if 1 + p_powerSpec_fx[0] = powerSpec_fx[ch1]; + p_powerSpec_fx[1] = powerSpec_fx[ch2]; +#endif + p_powerSpec[0] = powerSpec[ch1]; + p_powerSpec[1] = powerSpec[ch2]; + + /* Band-wise M/S for MDST */ + nSubframes = p_st[0]->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; + for ( n = 0; n < nSubframes; n++ ) + { +#if 1 + p_orig_spectrum[0][n] = orig_spectrum[ch1][n]; + p_orig_spectrum[1][n] = orig_spectrum[ch2][n]; + p_powerSpecMsInv[0][n] = powerSpecMsInv[ch1][n]; + p_powerSpecMsInv[1][n] = powerSpecMsInv[ch2][n]; + p_inv_spectrum[0][n] = inv_spectrum[ch1][n]; + p_inv_spectrum[1][n] = inv_spectrum[ch2][n]; +#endif + p_orig_spectrum_fx[0][n] = orig_spectrum_fx[ch1][n]; + p_orig_spectrum_fx[1][n] = orig_spectrum_fx[ch2][n]; + p_powerSpecMsInv_fx[0][n] = powerSpecMsInv_fx[ch1][n]; + p_powerSpecMsInv_fx[1][n] = powerSpecMsInv_fx[ch2][n]; + p_inv_spectrum_fx[0][n] = inv_spectrum_fx[ch1][n]; + p_inv_spectrum_fx[1][n] = inv_spectrum_fx[ch2][n]; + if ( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n] != hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] || + hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n] == SMDCT_BW_MS ) + { + ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, p_powerSpec_fx, p_powerSpecMsInv_fx, p_inv_spectrum_fx, p_orig_spectrum, p_powerSpec, p_powerSpecMsInv, p_inv_spectrum, n, sp_aud_decision0[ch1], p_st[0]->total_brate, 1 ); + } + else + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = p_st[ch]; + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + + ProcessIGF( st, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[p_ch[ch]][n], &powerSpec[p_ch[ch]][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch1], 0 ); + } + } + } + } + + /* channel elements that are coded separately detected */ + if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 ) + { + for ( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ ) + { + if ( singleChEle[ch] ) + { + st = sts[ch]; + + if ( + st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + if ( ch > 0 ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + + nSubframes = st->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; + for ( n = 0; n < nSubframes; n++ ) + { + ProcessIGF( st, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + } + } + } + } + + return; +} +#endif void mctStereoIGF_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index c778a3071..668dc5a26 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -1278,12 +1278,20 @@ typedef struct mct_enc_data_structure MCT_BLOCK_DATA_HANDLE hBlockData[MCT_MAX_BLOCKS]; float lastxCorrMatrix[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word32 lastxCorrMatrix_fx[MCT_MAX_CHANNELS][MCT_MAX_CHANNELS]; + Word16 lastxCorrMatrix_e; +#endif int16_t lowE_ch[MCT_MAX_CHANNELS]; uint16_t mc_global_ild[MCT_MAX_CHANNELS]; int16_t nBitsMCT; /* number of bits spent on mct side info */ /* pointers to local buffers */ float *p_mdst_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS]; float *p_orig_spectrum_long[MCT_MAX_BLOCKS][CPE_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word32 *p_mdst_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS]; + Word32 *p_orig_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS]; +#endif int16_t tnsBits[MCT_MAX_BLOCKS][CPE_CHANNELS][NB_DIV]; /* number of tns bits in the frame */ int16_t tnsSize[MCT_MAX_BLOCKS][CPE_CHANNELS][NB_DIV]; /* number of tns parameters put into prm */ int16_t p_param[MCT_MAX_BLOCKS][CPE_CHANNELS][NB_DIV]; diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 86715a6ce..93630057c 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -122,6 +122,18 @@ void stereo_mdct_core_enc( float pitch_buf[CPE_CHANNELS][NB_SUBFR16k] /* o : floating pitch for each subframe */ ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *p_orig_spectrum_long_fx[CPE_CHANNELS], orig_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ + Word32 *orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ + Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; + Word32 *p_powerSpec_fx[CPE_CHANNELS]; + Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ + Word32 *powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; + Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ + Word32 *quantized_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word32 *inv_mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV]; +#endif int16_t i, ch, nSubframes, L_subframeTCX; int16_t n, nAvailBits; int16_t tnsSize[CPE_CHANNELS][NB_DIV]; /* number of tns parameters put into prm */ @@ -156,6 +168,10 @@ void stereo_mdct_core_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { +#ifdef IVAS_FLOAT_FIXED + p_orig_spectrum_long_fx[ch] = orig_spectrum_long_fx[ch]; + UNUSED_PARAM( p_orig_spectrum_long_fx ); +#endif // IVAS_FLOAT_FIXED p_mdst_spectrum_long[ch] = mdst_spectrum_long[ch]; p_orig_spectrum_long[ch] = orig_spectrum_long[ch]; } @@ -214,6 +230,17 @@ void stereo_mdct_core_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { +#ifdef IVAS_FLOAT_FIXED + orig_spectrum_fx[ch][0] = orig_spectrum_long_fx[ch]; + orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; + inv_mdst_spectrum_fx[ch][0] = powerSpecMsInv_fx[ch][0] = powerSpecMsInv_long_fx[ch]; + inv_mdst_spectrum_fx[ch][1] = powerSpecMsInv_fx[ch][1] = powerSpecMsInv_long_fx[ch] + N_TCX10_MAX; + quantized_spectrum_fx[ch][0] = quantized_spectrum_long_fx[ch]; + quantized_spectrum_fx[ch][1] = quantized_spectrum_long_fx[ch] + N_TCX10_MAX; + inv_spectrum_fx[ch][0] = quantized_spectrum_fx[ch][0]; + inv_spectrum_fx[ch][1] = quantized_spectrum_fx[ch][1]; + UNUSED_PARAM( inv_mdst_spectrum_fx ); +#endif // IVAS_FLOAT_FIXED orig_spectrum[ch][0] = orig_spectrum_long[ch]; orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; @@ -264,10 +291,8 @@ void stereo_mdct_core_enc( #else #if 1 Word16 k; - Word32 *inv_spectrum_fx[2][2]; Word16 q_spec = Q31; Word16 length; - Word32 *inv_mdst_spectrum_fx[2][2]; Word32 *mdst_spectrum_fx[2][2]; FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -278,8 +303,6 @@ void stereo_mdct_core_enc( } FOR( k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) { - inv_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); - inv_mdst_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); mdst_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); q_spec = s_min( q_spec, Q_factor_arrL( sts[ch]->hTcxEnc->spectrum[k], length ) - 1 ); q_spec = s_min( q_spec, Q_factor_arrL( mdst_spectrum[ch][k], length ) - 1 ); @@ -317,8 +340,6 @@ void stereo_mdct_core_enc( fixedToFloat_arrL32( inv_spectrum_fx[ch][k], inv_spectrum[ch][k], q_spec, length ); fixedToFloat_arrL32( inv_mdst_spectrum_fx[ch][k], inv_mdst_spectrum[ch][k], q_spec, length ); fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_spec, length ); - free( inv_spectrum_fx[ch][k] ); - free( inv_mdst_spectrum_fx[ch][k] ); free( mdst_spectrum_fx[ch][k] ); } } @@ -417,7 +438,13 @@ void stereo_mdct_core_enc( { p_powerSpec[0] = powerSpec[0]; p_powerSpec[1] = powerSpec[1]; +#ifdef IVAS_FLOAT_FIXED + p_powerSpec_fx[0] = powerSpec_fx[0]; + p_powerSpec_fx[1] = powerSpec_fx[1]; + ProcessStereoIGF_fx( hStereoMdct, sts, ms_mask, orig_spectrum_fx, p_powerSpec_fx, powerSpecMsInv_fx, inv_spectrum_fx, orig_spectrum, p_powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); +#else ProcessStereoIGF( hStereoMdct, sts, ms_mask, orig_spectrum, p_powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); +#endif // IVAS_FLOAT_FIXED } else { diff --git a/lib_enc/ivas_stereo_switching_enc.c b/lib_enc/ivas_stereo_switching_enc.c index 1a333aaf7..165db27f9 100644 --- a/lib_enc/ivas_stereo_switching_enc.c +++ b/lib_enc/ivas_stereo_switching_enc.c @@ -511,6 +511,12 @@ ivas_error stereo_memory_enc( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxEnc\n" ) ); } + +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum_fx[0] = st->hTcxEnc->spectrum_long_fx; + st->hTcxEnc->spectrum_fx[1] = st->hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#endif // IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum[0] = st->hTcxEnc->spectrum_long; st->hTcxEnc->spectrum[1] = st->hTcxEnc->spectrum_long + N_TCX10_MAX; #ifdef IVAS_FLOAT_FIXED diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 1e9121daa..e414f2f04 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -2120,7 +2120,23 @@ void qlpc_avq_fx( void stereo_tcx_init_enc_fx( Encoder_State *st /* i/o: encoder state structure */ ); - +void IGF_UpdateInfo( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ +); +Word16 IGF_getCrest( /**< out: Q15| crest factor */ + Word16 *crest_exp, /**< out: | exponent of crest factor */ + const Word32 *powerSpectrum, /**< in: Q31 | power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +); +Word16 IGF_getSFM( /**< out: Q15| SFM value */ + Word16 *SFM_exp, /**< out: | exponent of SFM Factor */ + const Word32 *energy, /**< in: Q31| energies */ + const Word16 *energy_exp, /**< in: | exponent of energies */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +); /* IGFEnc.c */ void IGFEncApplyMono_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 5c029a808..335b3061a 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -678,6 +678,18 @@ typedef struct igf_enc_private_data_struct IGF_INFO igfInfo; int16_t igfScfQuantized[IGF_MAX_SFB]; IGFSCFENC_INSTANCE hIGFSCFArithEnc; +#ifdef IVAS_FLOAT_FIXED + Word16 prevSFM_FIR_SFB_TB_fx[IGF_MAX_SFB]; + Word16 sfb_sb_e[IGF_MAX_SFB]; + Word16 sfb_tb_e[IGF_MAX_SFB]; + Word16 prevSFM_IIR_SFB_TB_fx[IGF_MAX_SFB]; + Word16 prevSFM_FIR_SFB_SB_fx[IGF_MAX_SFB]; + Word16 prevSFM_IIR_SFB_SB_fx[IGF_MAX_SFB]; + Word16 SFM_tb_fx[IGF_MAX_SFB]; + Word16 SFM_sb_fx[IGF_MAX_SFB]; + Word16 prevDampingFactor_IIR_fx[IGF_MAX_SFB]; + Word16 prevDampingFactor_IIR_e[IGF_MAX_SFB]; +#endif // IVAS_FLOAT_FIXED float prevSFM_FIR_SFB_TB[IGF_MAX_SFB]; float prevSFM_IIR_SFB_TB[IGF_MAX_SFB]; @@ -1595,12 +1607,12 @@ typedef struct tcx_enc_structure int16_t noiseLevelMemory_cnt; /* counter of consecutive low TCX noise levels */ float ltpGainMemory[N_LTP_GAIN_MEMS]; /* for smoothing noiseTransWidth */ STnsData tnsData[2]; - int16_t fUseTns[2]; - Word8 fUseTns_fx[2]; + // int16_t fUseTns[2]; + Word8 fUseTns[2]; int16_t bTnsOnWhithenedSpectra[2]; - int16_t memQuantZeros[L_FRAME_PLUS]; /* Quantization deadzone flags */ - Word8 memQuantZeros_fx[L_FRAME_PLUS]; + // int16_t memQuantZeros[L_FRAME_PLUS]; /* Quantization deadzone flags */ + Word8 memQuantZeros[L_FRAME_PLUS]; /* Quantization deadzone flags */ float *speech_TCX_flt; float *new_speech_TCX_flt; diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index 4f14866c8..5c314cd79 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -57,7 +57,7 @@ void ComputeSpectrumNoiseMeasure( const int16_t L_frame, const int16_t startLine, const int16_t resetMemory, - int16_t *noiseFlags, + int8_t *noiseFlags, const int16_t lowpassLine ) { int16_t i, lastTone; @@ -567,12 +567,12 @@ float SQ_gain_estimate( *---------------------------------------------------------------------*/ void tcx_scalar_quantization( - float *x, /* i : input coefficients */ - int16_t *xq, /* o : quantized coefficients */ - const int16_t L_frame, /* i : frame length */ - const float gain, /* i : quantization gain */ - const float offset, /* i : rounding offset (deadzone) */ - int16_t *memQuantZeros, /* o : coefficients set to 0 */ + float *x, /* i : input coefficients */ + int16_t *xq, /* o : quantized coefficients */ + const int16_t L_frame, /* i : frame length */ + const float gain, /* i : quantization gain */ + const float offset, /* i : rounding offset (deadzone) */ + int8_t *memQuantZeros, /* o : coefficients set to 0 */ const int16_t tcxonly ) { int16_t i; @@ -710,7 +710,7 @@ int16_t tcx_scalar_quantization_rateloop( const int16_t L_frame, /* i : frame length */ float *gain, /* i/o: quantization gain */ float offset, /* i : rounding offset (deadzone) */ - int16_t *memQuantZeros, /* o : coefficients set to 0 */ + int8_t *memQuantZeros, /* o : coefficients set to 0 */ int16_t *lastnz_out, /* i/o: last nonzero coeff index */ const int16_t target, /* i : target number of bits */ int16_t *nEncoded, /* o : number of encoded coeff */ @@ -1583,6 +1583,95 @@ void ProcessIGF( * * *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ProcessStereoIGF_fx( + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, + Encoder_State *sts[CPE_CHANNELS], /* i : Encoder state */ + int16_t ms_mask[2][MAX_SFB], /* i : bandwise MS mask */ +#if 1 + Word32 *pITFMDCTSpectrum_fx[CPE_CHANNELS][NB_DIV], /* i : MDCT spectrum fir ITF */ + Word32 *pPowerSpectrum_fx[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word32 *pPowerSpectrumMsInv_fx[CPE_CHANNELS][NB_DIV], /* i : inverse power spectrum */ + Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ +#endif + float *pITFMDCTSpectrum[CPE_CHANNELS][NB_DIV], /* i : MDCT spectrum fir ITF */ + float *pPowerSpectrum[CPE_CHANNELS], /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + float *pPowerSpectrumMsInv[CPE_CHANNELS][NB_DIV], /* i : inverse power spectrum */ + float *inv_spectrum[CPE_CHANNELS][NB_DIV], /* i : inverse spectrum */ + const int16_t frameno, /* i : flag indicating index of current subfr. */ + const int16_t sp_aud_decision0, /* i : sp_aud_decision0 */ + const int32_t element_brate, /* i : element bitrate */ + const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ +) +{ + UNUSED_PARAM( pITFMDCTSpectrum_fx ); + int16_t ch, igfGridIdx, isIndepFlag, bsBits, pBsStart, curr_order; + float predictionGain; + float A[ITF_MAX_FILTER_ORDER + 1]; + IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS]; + BSTR_ENC_HANDLE hBstr; + + hIGFEnc[0] = sts[0]->hIGFEnc; + hIGFEnc[1] = sts[1]->hIGFEnc; + + isIndepFlag = 1; + + if ( sts[0]->last_core == ACELP_CORE && sts[0]->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( sts[0]->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + if ( frameno == 1 ) + { + isIndepFlag = 0; + } + } + + IGFSaveSpectrumForITF( hIGFEnc[0], igfGridIdx, pITFMDCTSpectrum[0][frameno] ); + + IGFSaveSpectrumForITF( hIGFEnc[1], igfGridIdx, pITFMDCTSpectrum[1][frameno] ); + + IGFEncApplyStereo_fx( hStereoMdct, ms_mask, hIGFEnc, igfGridIdx, sts, pPowerSpectrum_fx, pPowerSpectrumMsInv_fx, inv_spectrum_fx, pPowerSpectrum, pPowerSpectrumMsInv, inv_spectrum, frameno, sp_aud_decision0, element_brate, mct_on ); + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + curr_order = 0; + + ITF_Detect( hIGFEnc[ch]->spec_be_igf_flt, hIGFEnc[ch]->infoStartLine, hIGFEnc[ch]->infoStopLine, 8 /*maxOrder*/, A, &predictionGain, &curr_order ); + + hIGFEnc[ch]->flatteningTrigger = hIGFEnc[ch]->tns_predictionGain_flt < 1.15 && predictionGain < 1.15; + + hIGFEnc[ch]->infoTotalBitsPerFrameWritten = 0; + + if ( sts[ch]->core == TCX_20_CORE ) + { + IGFEncWriteBitstream( hIGFEnc[ch], NULL, &hIGFEnc[ch]->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + } + else + { + hBstr = sts[ch]->hBstr; + pBsStart = hBstr->nb_ind_tot; + if ( ch > 0 ) + { + hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + IGFEncWriteBitstream( hIGFEnc[ch], hBstr, &hIGFEnc[ch]->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + + bsBits = hBstr->nb_ind_tot - pBsStart; + IGFEncConcatenateBitstream( hIGFEnc[ch], bsBits, hBstr ); + } + } + + return; +} +#endif void ProcessStereoIGF( STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index 1ef5f0463..dc6dc6b7e 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -294,7 +294,7 @@ void AnalyzePowerSpectrum_fx( L_frameTCX, divide3216( L_mult( hTcxEnc->nmStartLine, L_frame ), st->L_frame ), tmp8, - hTcxEnc->memQuantZeros_fx, + hTcxEnc->memQuantZeros, lowpassLine ); IF( LE_32( st->total_brate, ACELP_24k40 ) ) -- GitLab From f346788784326713a1a6f08ab9ef6a838fcd1bf7 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Thu, 25 Jul 2024 10:00:34 +0530 Subject: [PATCH 2/2] Revert LSF tools changes --- lib_com/lsf_tools.c | 52 -------------------------------------------- lib_com/prot_fx.h | 11 ---------- lib_enc/fd_cng_enc.c | 29 ++---------------------- 3 files changed, 2 insertions(+), 90 deletions(-) diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index f13362be5..ddce7c199 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -2828,58 +2828,6 @@ void extend_dctN_input( return; } -#ifdef IVAS_FLOAT_FIXED -void extend_dctN_input_fx( - const Word32 *input, /* i : input in fdcng domain -> Q */ - const Word32 *dct_input, /* i : input in dctN(fdcng) domain -> Q */ - const Word16 in_dim, /* i : in_dim == N */ - Word32 *ext_sig, /* o : extended output in fdcng domain Q */ - const Word16 out_dim, /* i : output total dim */ - Word32 *matrix, /* i : idct synthesis matrix N rows, n_cols columns -> Q31*/ - const Word16 n_cols, /* i : number of columns == DCT truncation length */ - const DCTTYPE dcttype /* i : matrix operation type */ -) -{ - Word16 i, j, i_rev; - const Word32( *ptr )[FDCNG_VQ_DCT_MAXTRUNC] = (void *) matrix; - - /* stored format is an IDCT_Nx(FDCNG_VQ_DCT_MAXTRUNC) matrix */ - assert( in_dim < FDCNG_VQ_MAX_LEN ); - assert( out_dim <= FDCNG_VQ_MAX_LEN ); - assert( out_dim > in_dim ); - assert( n_cols == FDCNG_VQ_DCT_MAXTRUNC ); /* for *ptr[MAX_TRUNC] adressing*/ - assert( ( dcttype & 1 ) != 0 ); /* idct tables always in use for this basis vector extension */ - - Copy32( input, ext_sig, in_dim ); /* copy initial part, i.e. only last/tail parts are extended */ - set32_fx( &( ext_sig[in_dim] ), 0, out_dim - in_dim ); - - i_rev = in_dim; /*ptr init*/ - move16(); - - FOR( i = in_dim; i < out_dim; i++ ) - { /* for each extension sample */ - /* i = 21 22 23; - i_rev = 20 19 18; for odd dctII reflect basis vector - */ - i_rev = sub( i_rev, 1 ); - - FOR( j = 0; j < n_cols; j++ ) /* for each available DCT coeff */ - { - /* DCTcoeff * reflected basis vector */ -#define WMC_TOOL_SKIP - /* pure ptr MAC operations */ - ext_sig[i] = L_add( ext_sig[i], Mpy_32_32( dct_input[j], ptr[i_rev][j] ) ); /* sum up scaled and extended basis vector */ - move32(); - // Q31 + Q - Q31 -> Q - MAC( 1 ); -#undef WMC_TOOL_SKIP - } - } - - return; -} - -#endif /*-------------------------------------------------------------------* * create_IDCT_N_Matrix() diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index b51d561b0..e2b548441 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -9886,17 +9886,6 @@ void dctT2_N_apply_matrix_fx( const DCTTYPE dcttype /* i : matrix operation type */ ); -void extend_dctN_input_fx( - const Word32 *input, /* i : input in fdcng domain */ - const Word32 *dct_input, /* i : input in dctN(fdcng) domain */ - const Word16 in_dim, /* i : in_dim == N */ - Word32 *ext_sig, /* o : extended output in fdcng domain */ - const Word16 out_dim, /* i : output total dim */ - Word32 *matrix, /* i : idct synthesis matrix N rows, n_cols columns */ - const Word16 n_cols, /* i : number of columns == DCT truncation length */ - const DCTTYPE dcttype /* i : matrix operation type */ -); - Word32 sum2_f_32_fx( const Word32 *vec, /* i : input vector */ const int16_t lvec, /* i : length of input vector */ diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index b71282946..38803594f 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -46,7 +46,7 @@ #include "ivas_prot_fx.h" #include "stat_enc.h" #include "wmc_auto.h" -#include "ivas_prot_fx.h" + /*-------------------------------------------------------------------* * createFdCngEnc() * @@ -522,16 +522,6 @@ void FdCng_encodeSID( N = hFdCngEnc->npartDec; invTrfMatrix = (float *) tmpRAM; /* dynamically filled */ - -#ifdef IVAS_FLOAT_FIXED - Word32 *invTrfMatrix_fx; - Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; - Word32 v_fx[32]; - invTrfMatrix_fx = (Word32 *) tmpRAM_fx; - Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; - Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN]; -#endif - set_zero( v, FDCNG_VQ_MAX_LEN ); /* Convert to LOG */ @@ -569,24 +559,10 @@ void FdCng_encodeSID( { create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /* truncated DCT21 analysis */ - -#ifdef IVAS_FLOAT_FIXED - Word16 Q = 24; - move16(); - create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM_fx ) / ( sizeof( Word32 ) ) ); // Q31 -#endif - dctT2_N_apply_matrix( (const float *) v, dct_target, FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); /* truncated IDCT21 extension to 24 bands */ - -#ifdef IVAS_FLOAT_FIXED - floatToFixed_arr32( v, v_fx, Q, N ); - floatToFixed_arr32( dct_target, dct_target_fx, Q, FDCNG_VQ_DCT_MAXTRUNC ); - extend_dctN_input_fx( v_fx, dct_target_fx, N, tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); - fixedToFloat_arrL( tot_sig_ext_fx, tot_sig_ext, Q, N ); -#else extend_dctN_input( v, dct_target, N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); -#endif + mvr2r( tot_sig_ext, v, FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ } create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); @@ -1345,7 +1321,6 @@ void FdCngEncodeDiracMDCTStereoSID( /* truncated DCT 21 analysis */ dctT2_N_apply_matrix( (const float *) ms_ptr[0], dct_target, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); /* truncated IDCT21 extension to 24 synthesis */ - extend_dctN_input( ms_ptr[0], dct_target, N[0], tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ mvr2r( tot_sig_ext, ms_ptr[0], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ -- GitLab