diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index ce32ca59c023b82176d608b85e270c57043229b7..0085d0c2e04459efd5732b0928c636eee872f853 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -174,6 +174,19 @@ Word32 BASOP_Util_InvLog2( Word32 x ) return retVal; } +Word32 BASOP_Util_Log10( Word32 x, Word16 e ) +{ + Word32 res = BASOP_Util_Log2( x ); + res = L_add( Mpy_32_32( res, 646456993 /* log10(2) in Q31 */ ), Mpy_32_32( L_shl( e, 25 ), 646456993 /* log10(2) in Q31 */ ) ); // Adjusting for the exponent mismatch: multiplying first so as to avoid saturation + return res; +} + +Word32 BASOP_Util_Loge( Word32 x, Word16 e ) +{ + Word32 res = BASOP_Util_Log2( x ); + res = L_add( Mpy_32_32( res, 1488522235 /* loge(2) in Q31 */ ), Mpy_32_32( L_shl( e, 25 ), 1488522235 /* loge(2) in Q31 */ ) ); // Adjusting for the exponent mismatch: multiplying first so as to avoid saturation + return res; +} Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */ ( Word16 a_m, /*!< Mantissa of 1st operand a */ diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h index d633a33f918410a7b5ee32b6aceb7a1a279af15c..3549f7d5ce4619283fe75210c1682d42ee7ee3c6 100644 --- a/lib_com/basop_util.h +++ b/lib_com/basop_util.h @@ -340,6 +340,8 @@ Word32 BASOP_Util_Divide3232_Scale_cadence( Word32 x, /*!< i : Numerator*/ */ /************************************************************************/ Word32 BASOP_Util_Log2( Word32 x ); +Word32 BASOP_Util_Log10( Word32 x, Word16 e ); +Word32 BASOP_Util_Loge( Word32 x, Word16 e ); /****************************************************************************/ diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 5d0864ce8ba017548e2d5f020fd2a0e7f86fd4bd..1ef5879dc8ffe249d4f8cd3672c22663fa5cb720 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -163,6 +163,16 @@ ivas_error ivas_sce_enc( const int16_t nb_bits_metadata /* i : number of metadata bits */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_cpe_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + float data_f_ch0[], /* i : input signal for channel 0 */ + float data_f_ch1[], /* i : input signal for channel 1 */ + const Word16 input_frame, /* i : input frame length per channel */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +); +#else ivas_error ivas_cpe_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t cpe_id, /* i : CPE # identifier */ @@ -171,6 +181,7 @@ ivas_error ivas_cpe_enc( const int16_t input_frame, /* i : input frame length per channel */ const int16_t nb_bits_metadata /* i : number of metadata bits */ ); +#endif ivas_error ivas_mct_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ @@ -1684,10 +1695,17 @@ void stereo_enc_itd_init_fx( ITD_DATA_HANDLE hItd /* i/o: encoder ITD handle */ ); +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_update_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word16 max_bwidth /* i : maximum encoded bandwidth */ +); +#else void stereo_dft_enc_update( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ const int16_t max_bwidth /* i : maximum encoded bandwidth */ ); +#endif void stereo_dft_enc_destroy( STEREO_DFT_ENC_DATA_HANDLE *hStereoDft /* i/o: encoder DFT stereo handle */ @@ -1703,6 +1721,19 @@ void stereo_dft_enc_analyze( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_analyze_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + const Word16 n_channels, /* i : number of input channels */ + const Word16 input_frame, /* i : input frame length */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem + ); +#endif + float stereo_dft_enc_synthesize( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ float *output, /* o : output synthesis */ @@ -2187,6 +2218,22 @@ void stereo_dft_hybrid_ITD_flag( const Word16 hybrid_itd_max /* i : flag for hybrid ITD for very large ITDs */ ); +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_compute_itd_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word32 *DFT_L, + Word16 DFT_L_e, + Word32 *DFT_R, + Word16 DFT_R_e, + const Word16 k_offset, + const Word16 input_frame, + const Word16 vad_flag_dtx[], + const Word16 vad_hover_flag[], + Word32 *bin_nrgL, + Word16 *bin_nrgL_e, + Word32 *bin_nrgR, + Word16 *bin_nrgR_e ); +#endif void stereo_dft_enc_compute_itd( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float *DFT_L, @@ -2223,6 +2270,20 @@ void stereo_td_itd( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); +#ifdef IVAS_FLOAT_FIXED +void stereo_td_itd_fx( + ITD_DATA *hITD, /* i/o: ITD data structure */ + Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ + Word16 *q_input_mem_itd, + const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ + const Word16 dft_ovl, /* i : size of DFT overlap */ + Encoder_State **sts, /* i/o: Encoder state structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem +); +#endif + void stereo_dft_dmx_out_reset( STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder */ ); @@ -2560,6 +2621,13 @@ void unclr_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); +#ifdef IVAS_FLOAT_FIXED +void xtalk_classifier_dft_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word16 itd, /* i : ITD from DFT stereo - used as a feature */ + const Word32 gcc_phat[] /* i : GPHAT cross-channel correlation function Q31*/ +); +#endif void xtalk_classifier_dft( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const int16_t itd, /* i : ITD from DFT stereo - used as a feature */ @@ -3817,6 +3885,14 @@ int16_t check_bounds_s( const int16_t high /* i : High limit */ ); +#ifdef IVAS_FLOAT_FIXED +Word16 check_bounds_s_fx( + const Word16 value, /* i : Input value */ + const Word16 low, /* i : Low limit */ + const Word16 high /* i : High limit */ +); +#endif + Word32 check_bounds_l( const Word32 value, /* i : Input value */ const Word32 low, /* i : Low limit */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index c0d8f21ed06a0d431c3032d9ce0a79f28d9ae529..400aa3eb070c51a12d4035787b79b0d7c5c367fb 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -1189,6 +1189,17 @@ void create_IDCT_N_Matrix_fx( const Word16 alloc_size /* i : RAM buffer size in elements */ ); +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 */ +); + void ivas_dirac_dec_get_frequency_axis_fx( Word16 *frequency_axis, /* Q0 */ const Word32 output_Fs, diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index ddce7c19914bfb70759d3366d1443d750a205aa8..4a6b5c2a6d3abf113da9da61741a8e8ee2cff971 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -2828,6 +2828,57 @@ 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 31 */ + 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, sub( 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 */ + // Q31 + Q - Q31 -> Q + move32(); + 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 12828f0ddefb815916f911f64691e616fcb22b2f..05ffc64e741b35f48fccc7611245a802d8951639 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -195,6 +195,11 @@ void set_zero_fx( const Word16 lvec /* i : length of the vector */ ); +void set16_zero_fx( + Word16 *vec, /* o : input vector */ + const Word16 lvec /* i : length of the vector */ +); + void set_zero( float *vec, /* o : input vector */ const int16_t lvec /* i : length of the vector */ @@ -257,6 +262,12 @@ int16_t maximumAbs( float *max_val /* o : maximum value in the input vector */ ); +Word16 maximumAbs_l( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word32 *max_val /* o : maximum value in the input vector */ +); + /*! r: index of the minimum value in the input vector */ int16_t minimum( const float *vec, /* i : input vector */ @@ -5404,7 +5415,7 @@ void bitallocsum( const int16_t length, /* i : length of spectrum */ const int16_t *sfmsize /* i : Length of bands */ ); - +#ifndef IVAS_FLOAT_FIXED void hq_generic_hf_encoding( const float *coefs, /* i : MDCT coefficients of weighted original */ float *hq_generic_fenv, /* i/o: energy of SWB envelope */ @@ -5413,7 +5424,7 @@ void hq_generic_hf_encoding( int16_t *hq_generic_exc_clas, /* o : HF excitation class */ const int16_t length /* i : Length of spectrum */ ); - +#endif /*! r: BWE class */ int16_t swb_bwe_gain_deq_flt( Decoder_State *st, /* i/o: decoder state structure */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index c65baf0807f0fd9955f35de2232002fb3c5cbd69..5cc639543b2cafdf7facbb1313e5e3f8d1498bc4 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -210,6 +210,13 @@ Word32 sum2_fx( /* o : sum of all squared vector elements const Word16 lvec /* i : length of i vector */ ); +Word16 sign_fx( + const Word32 x /* i : input value of x */ +); + +Word16 sign16_fx( + const Word16 x /* i : input value of x */ +); /*========================================================================================================/ mslvq_com_fx.c /========================================================================================================*/ @@ -9843,6 +9850,15 @@ void delay_signal32( const Word16 delay /* i : delay in samples */ ); +Word16 lin_interp_ivas_fx( + const Word16 x, /* i : the value to be mapped */ + const Word16 x1, /* i : source range interval: low end */ + const Word16 y1, /* i : source range interval: high end */ + const Word16 x2, /* i : target range interval: low */ + const Word16 y2, /* i : target range interval: high */ + const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ +); + Word16 lin_interp_fx( const Word16 x, /* i : the value to be mapped */ const Word16 x1, /* i : source range interval: low end */ @@ -10151,3 +10167,13 @@ void IGFEncApplyStereo_fx( #endif // IVAS_FLOAT_FIXED #endif + +#ifdef IVAS_FLOAT_FIXED +void hq_generic_hf_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas, /* o : bwe excitation class */ + Word16 length ); +#endif diff --git a/lib_com/swb_bwe_com_fx.c b/lib_com/swb_bwe_com_fx.c index 0ecd34e83db660fac977521d98ec20e75aeb18dc..879e76e07f80f45ee004290d08f73bfca2967101 100644 --- a/lib_com/swb_bwe_com_fx.c +++ b/lib_com/swb_bwe_com_fx.c @@ -2479,7 +2479,7 @@ void calc_normal_length_fx_32( n_band = 0; move16(); pit = sp; - move16(); + FOR( i = 0; i < N; i++ ) { peak = 0; @@ -2503,7 +2503,7 @@ void calc_normal_length_fx_32( pit++; } - L_tmp1 = Mult_32_16( peak, shl( 15 + THRES, 10 ) ); + L_tmp1 = Mult_32_16( peak, shl( add( 15, THRES ), 10 ) ); L_tmp2 = Mult_32_16( mean, shl( THRES, 10 ) ); test(); if ( GT_32( L_tmp1, L_tmp2 ) && GT_32( peak, 40960 ) ) @@ -2512,18 +2512,18 @@ void calc_normal_length_fx_32( } } - IF( EQ_16( core, ACELP_CORE ) ) + IF( core == ACELP_CORE ) { L_swb_norm_trans = add( 4, shr( n_band, 2 ) ); L_swb_norm_norm = add( 8, shr( n_band, 1 ) ); L_swb_norm_harm = s_max( add( 32, shl( n_band, 1 ) ), 24 ); - IF( mode == HARMONIC ) + IF( EQ_16( mode, HARMONIC ) ) { L_swb_norm_cur = L_swb_norm_harm; move16(); } - ELSE IF( mode == NORMAL ) + ELSE IF( EQ_16( mode, NORMAL ) ) { L_swb_norm_cur = L_swb_norm_norm; move16(); @@ -2542,7 +2542,7 @@ void calc_normal_length_fx_32( ELSE { test(); - IF( mode == HQ_HARMONIC || mode == HQ_HVQ ) + IF( EQ_16( mode, HQ_HARMONIC ) || EQ_16( mode, HQ_HVQ ) ) { L_swb_norm_cur = add( 32, add( shl( n_band, 1 ), shr( n_band, 1 ) ) ); } @@ -2575,9 +2575,9 @@ void calc_norm_envelop_fx_32( { Word16 i, lookback, env_index, n_freq, n_lag_now, n_lag, tmp; - lookback = L_swb_norm / 2; + lookback = shr( L_swb_norm, 1 ); move16(); - env_index = swb_bwe_subband[0] + st_offset; + env_index = add( swb_bwe_subband[0], st_offset ); move16(); n_lag_now = L_swb_norm; move16(); @@ -2605,13 +2605,13 @@ void calc_norm_envelop_fx_32( { Word32 L_tmp; - n_lag_now = L_swb_norm - i; + n_lag_now = sub( L_swb_norm, i ); move16(); /* Apply MA filter */ L_tmp = L_deposit_l( 0 ); FOR( n_lag = 0; n_lag < n_lag_now; n_lag++ ) { - L_tmp = L_add( L_tmp, L_abs( SWB_signal_fx[n_freq + n_lag] ) ); + L_tmp = L_add( L_tmp, L_abs( SWB_signal_fx[add( n_freq, n_lag )] ) ); } envelope_fx[env_index] = L_tmp; move32(); diff --git a/lib_com/tools.c b/lib_com/tools.c index 64de07a75841248a4c168b386f2c96aeff8fdbec..b184b15f151d9610d061647a8bedbe6290b7009c 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -769,18 +769,51 @@ int16_t maximumAbs( ind = 0; tmp = (float) fabs( vec[0] ); - FOR( j = 1; j < lvec; j++ ) + for ( j = 1; j < lvec; j++ ) { - IF( (float) fabs( vec[j] ) > tmp ) + if ( (float) fabs( vec[j] ) > tmp ) { ind = j; tmp = (float) fabs( vec[j] ); } } + if ( max_val != NULL ) + { + *max_val = tmp; + } + + return ind; +} + +/*! r: index of the maximum value in the input vector */ +Word16 maximumAbs_l( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word32 *max_val /* o : maximum value in the input vector */ +) +{ + Word16 j, ind; + Word32 tmp; + + ind = 0; + move16(); + tmp = L_abs( vec[0] ); + + FOR( j = 1; j < lvec; j++ ) + { + IF( GT_32( L_abs( vec[j] ), tmp ) ) + { + ind = j; + move16(); + tmp = L_abs( vec[j] ); + } + } + IF( max_val != NULL ) { *max_val = tmp; + move32(); } return ind; diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 19c5efcbb903118ed2141691d96cc7d8f80b2c38..4641195552d10c5d10436b6bb0e034b7293d412f 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -2023,6 +2023,39 @@ Word16 own_random2_fx( Word16 seed ) return extract_l( L_mac0( 13849, seed, 31821 ) ); } +/*--------------------------------------------------------------------- + * sign() + * + *---------------------------------------------------------------------*/ + +/*! r: sign of x (+1/-1) */ +Word16 sign_fx( + const Word32 x /* i : input value of x */ +) +{ + IF( LT_32( x, 0 ) ) + { + return -1; + } + ELSE + { + return 1; + } +} + +Word16 sign16_fx( + const Word16 x /* i : input value of x */ +) +{ + IF( LT_16( x, 0 ) ) + { + return -1; + } + ELSE + { + return 1; + } +} /*------------------------------------------------------------------* * function Div_32_optmz @@ -4060,6 +4093,36 @@ Word16 lin_interp_fx( } +Word16 lin_interp_ivas_fx( + const Word16 x, /* i : Q15 the value to be mapped */ + const Word16 x1, /* i : Q15 source range interval: low end */ + const Word16 y1, /* i : Q15 source range interval: high end */ + const Word16 x2, /* i : Q15 target range interval: low */ + const Word16 y2, /* i : Q15 target range interval: high */ + const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ +) +{ + IF( EQ_16( sub( x2, x1 ), 0 ) ) + { + return y1; + } + ELSE IF( flag_sat ) + { + IF( GE_16( x, s_max( x1, x2 ) ) ) + { + return GT_16( x1, x2 ) ? y1 : y2; + } + ELSE IF( LE_16( x, s_min( x1, x2 ) ) ) + { + return LT_16( x1, x2 ) ? y1 : y2; + } + } + Word16 div_res_e; + Word16 div_res = BASOP_Util_Divide1616_Scale( sub( y2, y1 ), sub( x2, x1 ), &div_res_e ); + // div_res = shl( div_res, div_res_e ); + return add_sat( y1, round_fx( L_shl( L_mult( sub( x, x1 ), div_res ), div_res_e ) ) ); +} + /*--------------------------------------------------------------------- * sign() * @@ -4120,6 +4183,22 @@ void set_zero_fx( return; } +void set16_zero_fx( + Word16 *vec, /* o : input vector */ + const Word16 lvec /* i : length of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < lvec; i++ ) + { + *vec++ = 0; + move16(); + } + + return; +} + UWord32 mvl2s_r( const Word32 x[], /* i : input vector */ const Word16 q_x, diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index 38803594fbbff31f413528e27f94f77be9fa3458..86e0bd27388ec1303c7ebe6616b0f2bab942f797 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -518,10 +518,21 @@ void FdCng_encodeSID( float tot_sig_ext[FDCNG_VQ_MAX_LEN]; const float gain_q_offset = ( st->element_mode == EVS_MONO ) ? GAIN_Q_OFFSET_EVS : GAIN_Q_OFFSET_IVAS; +#ifdef IVAS_FLOAT_FIXED + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + Word32 v_fx[32]; + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN]; +#endif + /* Init */ N = hFdCngEnc->npartDec; invTrfMatrix = (float *) tmpRAM; /* dynamically filled */ +#ifdef IVAS_FLOAT_FIXED + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; /* dynamically filled */ +#endif set_zero( v, FDCNG_VQ_MAX_LEN ); /* Convert to LOG */ @@ -559,9 +570,23 @@ 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, FDCNG_VQ_MAX_LEN ); + 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, FDCNG_VQ_MAX_LEN ); +#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 */ } diff --git a/lib_enc/hq_hr_enc.c b/lib_enc/hq_hr_enc.c index d7b462449b7156377b4f29992a108a69e0a91c49..63f6713797140b33522dfdabe2c04a66dca32b14 100644 --- a/lib_enc/hq_hr_enc.c +++ b/lib_enc/hq_hr_enc.c @@ -38,6 +38,9 @@ #include "options.h" #include "cnst.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif #include "rom_enc.h" #include "rom_com.h" #include "wmc_auto.h" @@ -47,7 +50,7 @@ * * HQ high rate encoding routine *--------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void hq_hr_enc( Encoder_State *st, /* i/o: encoder state structure */ float *t_audio, /* i/o: transform-domain coefficients */ @@ -158,6 +161,218 @@ void hq_hr_enc( if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) { hq_generic_hf_encoding( t_audio, hq_generic_fenv, hq_generic_offset, st, &hq_generic_exc_clas, length ); + + if ( hq_generic_exc_clas == HQ_GENERIC_SP_EXC ) + { + ( *num_bits )++; /* conditional 1 bit saving for representing FD3 BWE excitation class */ + } + map_hq_generic_fenv_norm( hqswb_clas, hq_generic_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); + } + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation( st->core_brate, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level, R, Rsubband, &sum, &core_sfm, num_env_bands ); + + /*------------------------------------------------------------------* + * Normalize coefficients with quantized norms + *------------------------------------------------------------------*/ + if ( hqswb_clas != HQ_HVQ ) + { + if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + { + b_delta_env = calc_nor_delta_hf( hBstr, t_audio, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); + sum -= b_delta_env; + } + normalizecoefs( t_audio, ynrm, nb_sfm, sfm_start, sfm_end ); + } + + /*------------------------------------------------------------------* + * Quantize/code spectral fine structure using PVQ or HVQ + *------------------------------------------------------------------*/ + + if ( hqswb_clas == HQ_HVQ ) + { + sum = hvq_enc( hBstr, st->bwidth, st->core_brate, *num_bits, Npeaks, ynrm, R, peaks, nf_gains, noise_level, pe_gains, t_audio, t_audio_q ); + *num_bits -= sum; + } + else + { + shape_bits = pvq_core_enc( hBstr, t_audio, t_audio_q, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, npulses, maxpulse, HQ_CORE ); + *num_bits += ( sum - shape_bits ); + } + + if ( hqswb_clas == HQ_HVQ || hqswb_clas == HQ_HARMONIC ) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + + har_est( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &hHQ_core->prev_frm_hfe2, subband_search_offset, wBands, &hHQ_core->prev_stab_hfe2 ); + + hHQ_core->prev_frm_hfe2 = har_freq_est2; + } + + /* reset LR-HQ memories */ + hHQ_core->prev_frm_hfe2 = 0; /*reset*/ + hHQ_core->prev_stab_hfe2 = 0; + + nf_idx = 0; + if ( !is_transient && hqswb_clas != HQ_HVQ && !( length == L_FRAME16k && st->core_brate <= HQ_32k ) ) + { + if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + { + nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, max( core_sfm, num_env_bands - 1 ) ); + push_indice( hBstr, IND_NF_IDX, nf_idx, 2 ); + } + else + { + nf_idx = noise_adjust( t_audio, R, sfm_start, sfm_end, core_sfm ); + push_indice( hBstr, IND_NF_IDX, nf_idx, 2 ); + } + } + + + /* updates */ + hHQ_core->prev_hqswb_clas = hqswb_clas; + + /* Prepare synthesis for LB generation in case of switch to ACELP */ + if ( hqswb_clas != HQ_HVQ ) + { + apply_envelope_enc( t_audio_q, ynrm, num_sfm, sfm_start, sfm_end ); + } + + if ( is_transient ) + { + de_interleave_spectrum( t_audio_q, length ); + } + + mvr2r( t_audio_q, t_audio, length ); + + + return; +} +#else +void hq_hr_enc( + Encoder_State *st, /* i/o: encoder state structure */ + float *t_audio, /* i/o: transform-domain coefficients */ + const int16_t length, /* i : length of spectrum */ + int16_t *num_bits, /* i/o: number of available bits */ + const int16_t is_transient, /* i : transient flag */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +) +{ + int16_t nb_sfm; + int16_t sum, hcode_l; + int16_t difidx[NB_SFM]; + int16_t normqlg2[NB_SFM], ynrm[NB_SFM]; + int16_t nf_idx; + int16_t LCmode; + int16_t shape_bits, num_sfm, numnrmibits; + int16_t hqswb_clas; + int16_t num_env_bands; + int16_t Npeaks, start_norm; + int16_t difidx_org[NB_SFM]; + int16_t R[NB_SFM]; + int16_t peaks[HVQ_MAX_PEAKS]; + int16_t sfmsize[NB_SFM], sfm_start[NB_SFM], sfm_end[NB_SFM]; + int16_t npulses[NB_SFM], maxpulse[NB_SFM]; + int16_t Rsubband[NB_SFM]; /* Q3 */ + float t_audio_q[L_SPEC48k_EXT]; + float nf_gains[HVQ_NF_GROUPS], pe_gains[HVQ_NF_GROUPS]; + float noise_level[HVQ_BWE_NOISE_BANDS]; + int16_t hq_generic_offset; + float hq_generic_fenv[HQ_FB_FENV]; + int16_t hq_generic_exc_clas = 0; + int16_t core_sfm; + int16_t har_freq_est1 = 0, har_freq_est2 = 0; + int16_t flag_dis = 1; + const int16_t *subband_search_offset; + int16_t wBands[2]; + int16_t b_delta_env; + float att; + HQ_ENC_HANDLE hHQ_core = st->hHQ_core; + BSTR_ENC_HANDLE hBstr = st->hBstr; +#ifdef IVAS_FLOAT_FIXED + Word32 t_audio_fx[L_FRAME48k_EXT]; + Word16 hq_generic_fenv_fx[HQ_FB_FENV]; +#endif + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + Npeaks = 0; + set_s( npulses, 0, NB_SFM ); + set_s( maxpulse, 0, NB_SFM ); + set_s( difidx_org, 0, NB_SFM ); + set_f( t_audio_q, 0.0f, L_FRAME48k ); + set_f( nf_gains, 0.0f, HVQ_NF_GROUPS ); + set_f( pe_gains, 0.0f, HVQ_NF_GROUPS ); + + /*------------------------------------------------------------------* + * Classification + *------------------------------------------------------------------*/ + + *num_bits -= hq_classifier_enc( st, length, t_audio, is_transient, &Npeaks, peaks, pe_gains, nf_gains, &hqswb_clas ); + + + /*------------------------------------------------------------------* + * Set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure( length, hqswb_clas, st->core_brate, &num_sfm, &nb_sfm, &start_norm, &num_env_bands, &numnrmibits, &hq_generic_offset, sfmsize, sfm_start, sfm_end ); + + /*------------------------------------------------------------------* + * Transient frame handling + *------------------------------------------------------------------*/ + + /* Interleave MLT coefficients of 4 sub-vectors in case of transient frame */ + if ( is_transient ) + { + interleave_spectrum( t_audio, length ); + } + + if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) + { + calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); + if ( att != 1.0f ) + { + v_multc( t_audio, att, t_audio, sfm_end[num_sfm - 1] ); + } + } + + /*------------------------------------------------------------------* + * Scalar quantization of norms + * Encode norm indices + *------------------------------------------------------------------*/ + + /* calculate and quantize norms */ + calc_norm( t_audio, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + + /* create differential code of quantized norm indices */ + diff_envelope_coding( is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx ); + + /* Find norm coding mode and calculate number of bits */ + hcode_l = encode_envelope_indices( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); + *num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; + + /* Encode norm indices */ + encode_envelope_indices( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); + + /*------------------------------------------------------------------* + * HQ GENERIC BWE encoding + *------------------------------------------------------------------*/ + + if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + { +#ifdef IVAS_FLOAT_FIXED + floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); + hq_generic_hf_encoding_fx( t_audio_fx, hq_generic_fenv_fx, hq_generic_offset, st, &hq_generic_exc_clas, length ); + fixedToFloat_arr( hq_generic_fenv_fx, hq_generic_fenv, Q1, HQ_FB_FENV ); +#else + hq_generic_hf_encoding( t_audio, hq_generic_fenv, hq_generic_offset, st, &hq_generic_exc_clas, length ); +#endif if ( hq_generic_exc_clas == HQ_GENERIC_SP_EXC ) { ( *num_bits )++; /* conditional 1 bit saving for representing FD3 BWE excitation class */ @@ -249,3 +464,4 @@ void hq_hr_enc( return; } +#endif diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index ac191c7ff89ed31926c142caf352b1aa5eb3a745..75e39103e787f9d1d25a67a5853a958477e5994f 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -342,9 +342,10 @@ ivas_error init_encoder( st->input_buff = st->hSignalBuf->input_buff_flt; set_zero( st->input_buff, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); st->old_input_signal = st->input_buff; +// This part needs to be removed once fx fn is invoked// #ifdef IVAS_FLOAT_FIXED st->input_buff_fx = st->hSignalBuf->input_buff; - set16_fx( st->input_buff_fx, 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + set16_fx( st->input_buff_fx, 0, add( L_FRAME48k, add( L_FRAME48k, NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ) ) ); st->old_input_signal_fx = st->input_buff_fx; #endif if ( st->element_mode == EVS_MONO ) @@ -362,9 +363,6 @@ ivas_error init_encoder( st->input32_fx = st->input_buff32_fx + st->input_Fs / FRAMES_PER_SEC; #endif // IVAS_FLOAT_FIXED st->input = st->input_buff + st->input_Fs / FRAMES_PER_SEC; -#ifdef IVAS_FLOAT_FIXED - st->input_fx = st->input_buff_fx + st->input_Fs / FRAMES_PER_SEC; -#endif } } else diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 9b8b4bfc50cccfd4d7297ac7f287e18521d09c0a..50eb83ee5d6679b2b607050fb7a021ad21122bd2 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -44,6 +44,7 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #include "prot_fx.h" +#include "ivas_rom_enc.h" #endif @@ -61,12 +62,12 @@ static void stereo_mode_combined_format_enc( const Encoder_Struct *st_ivas, CPE_ *-------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED ivas_error ivas_cpe_enc( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const int16_t cpe_id, /* i : CPE # identifier */ - float data_f_ch0[], /* i : input signal for channel 0 */ - float data_f_ch1[], /* i : input signal for channel 1 */ - const int16_t input_frame, /* i : input frame length per channel */ - const int16_t nb_bits_metadata /* i : number of metadata bits */ + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + float data_f_ch0[], /* i : input signal for channel 0 */ + float data_f_ch1[], /* i : input signal for channel 1 */ + const Word16 input_frame, /* i : input frame length per channel */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ ) { CPE_ENC_HANDLE hCPE; @@ -409,17 +410,81 @@ ivas_error ivas_cpe_enc( if ( hCPE->element_mode == IVAS_CPE_DFT ) { stereo_dft_hybrid_ITD_flag( hCPE->hStereoDft->hConfig, input_Fs, hCPE->hStereoDft->hItd->hybrid_itd_max ); +#ifdef IVAS_FLOAT_FIXED + /* flt2fix: to be removed */ + // Word16 input_fx[CPE_CHANNELS][1965]; + FOR( int i = 0; i < CPE_CHANNELS; i++ ) + { + // sts[i]->input_fx = &input_fx[i][0]; + // sts[i]->q_inp = Q_factor_arr(sts[i]->input, 1965); + // sts[i]->q_old_inp = sts[i]->q_inp = Q_factor_arr( sts[i]->old_input_signal, 1965 ); // check length + sts[i]->q_inp = Q_factor_arr( sts[i]->old_input_signal, 1965 ); // check length + hCPE->hStereoDft->q_input_mem_itd[i] = Q_factor_arr( &hCPE->hStereoDft->input_mem_itd[i][0], STEREO_DFT_OVL_MAX ); + // hCPE->hStereoDft->DFT_q_fx[i] = Q_factor_arrL(&hCPE->hStereoDft->DFT[i][0], STEREO_DFT_N_MAX_ENC); + // f2me_buf( hCPE->hStereoDft->DFT[i], hCPE->hStereoDft->DFT_fx[i], &hCPE->hStereoDft->DFT_fx_e[i], STEREO_DFT_N_MAX_ENC ); + hCPE->q_input_mem[i] = Q_factor_arr( &hCPE->input_mem[i][0], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + // floatToFixed_arr(sts[i]->old_input_signal, sts[i]->old_input_signal_fx, sts[i]->q_old_inp, 1965); + floatToFixed_arr( sts[i]->old_input_signal, sts[i]->old_input_signal_fx, sts[i]->q_inp, 1965 ); + // floatToFixed_arr(sts[i]->input, sts[i]->input_fx, sts[i]->q_inp, 1965); + // floatToFixed_arrL(&hCPE->hStereoDft->DFT[i][0], &hCPE->hStereoDft->DFT_fx[i][0], hCPE->hStereoDft->DFT_q_fx[i], STEREO_DFT_N_MAX_ENC); + floatToFixed_arr( &hCPE->input_mem[i][0], &hCPE->input_mem_fx[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + floatToFixed_arr( &hCPE->hStereoDft->input_mem_itd[i][0], &hCPE->hStereoDft->input_mem_itd_fx[i][0], hCPE->hStereoDft->q_input_mem_itd[i], STEREO_DFT_OVL_MAX ); + } + floatToFixed_arrL( hCPE->hStereoDft->side_gain, hCPE->hStereoDft->side_gain_fx, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); + floatToFixed_arrL( hCPE->hStereoDft->res_pred_gain, hCPE->hStereoDft->res_pred_gain_fx, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); + floatToFixed_arrL( hCPE->hStereoDft->gipd, hCPE->hStereoDft->gipd_fx, Q13, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoDft->hItd->itd, hCPE->hStereoDft->hItd->itd_fx, Q16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoDft->hItd->deltaItd, hCPE->hStereoDft->hItd->deltaItd_fx, Q16, STEREO_DFT_ENC_DFT_NB ); + /* flt2fix end */ + + /*FOR(int i = 0; i < 2; i++) + { + hCPE->hStereoDft->hItd->deltaItd_fx[i] = float_to_fix(hCPE->hStereoDft->hItd->deltaItd[i], hCPE->hStereoDft->hItd->q_itd); + hCPE->hStereoDft->hItd->itd_fx[i] = float_to_fix(hCPE->hStereoDft->hItd->itd[i], hCPE->hStereoDft->hItd->q_itd); + }*/ + /* Time Domain ITD compensation using extrapolation */ + stereo_td_itd_fx( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd_fx, hCPE->hStereoDft->q_input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); + stereo_dft_enc_analyze_fx( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT_fx, hCPE->input_mem_fx, hCPE->q_input_mem ); +#else /* Time Domain ITD compensation using extrapolation */ stereo_td_itd( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem ); /* DFT on right and left input channels */ stereo_dft_enc_analyze( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT, hCPE->input_mem ); +#endif sts[0]->total_brate = ( sts[0]->bits_frame_nominal + 10 ) * FRAMES_PER_SEC; /* add small overhead; st[0]->total_brate used in coder_type_modif() */ /* Update DFT Stereo memories */ - stereo_dft_enc_update( hCPE->hStereoDft, sts[0]->max_bwidth ); + stereo_dft_enc_update_fx( hCPE->hStereoDft, sts[0]->max_bwidth ); + /* fix2flt: to be removed */ + fixedToFloat_arrL( hCPE->hStereoDft->side_gain_fx, hCPE->hStereoDft->side_gain, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); + fixedToFloat_arrL( hCPE->hStereoDft->res_pred_gain_fx, hCPE->hStereoDft->res_pred_gain, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); + fixedToFloat_arrL( hCPE->hStereoDft->gipd_fx, hCPE->hStereoDft->gipd, Q13, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoDft->hItd->itd, Q16, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hCPE->hStereoDft->hItd->deltaItd_fx, hCPE->hStereoDft->hItd->deltaItd, Q16, STEREO_DFT_ENC_DFT_NB ); + + + FOR( int i = 0; i < CPE_CHANNELS; i++ ) + { + // fixedToFloat_arr( sts[i]->input_fx, sts[i]->input, sts[i]->q_inp, 1965 ); + // fixedToFloat_arr(sts[i]->old_input_signal_fx, sts[i]->old_input_signal, sts[i]->q_old_inp, 1965); + fixedToFloat_arr( &hCPE->input_mem_fx[i][0], &hCPE->input_mem[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + // fixedToFloat_arrL( &hCPE->hStereoDft->DFT_fx[i][0], &hCPE->hStereoDft->DFT[i][0], hCPE->hStereoDft->DFT_q_fx[i], STEREO_DFT_N_MAX_ENC ); + me2f_buf( hCPE->hStereoDft->DFT_fx[i], hCPE->hStereoDft->DFT_fx_e[i], hCPE->hStereoDft->DFT[i], STEREO_DFT_N_MAX_ENC ); + fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], STEREO_DFT_OVL_MAX ); + } + /* fix2flt end */ + +#if 0 + /* flt2fix: to be removed */ + for ( int i = 0; i < CPE_CHANNELS; i++ ) + { + f2me_buf( hCPE->hStereoDft->DFT[i], hCPE->hStereoDft->DFT_fx[i], &hCPE->hStereoDft->DFT_fx_e[i], STEREO_DFT_N_MAX_ENC ); + } + /* flt2fix end */ +#endif /* DFT stereo processing */ stereo_dft_enc_process( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); } @@ -1079,6 +1144,157 @@ ivas_error ivas_cpe_enc( } + if ( hCPE->element_mode != IVAS_CPE_MDCT && ( hCPE->element_brate != hCPE->last_element_brate || hCPE->last_element_mode != hCPE->element_mode || sts[0]->ini_frame == 0 || + ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) || sts[0]->last_core_brate <= SID_2k40 ) ) /* If the last frame was SID or NO_DATA, we need to run stereo_dft_config here since VAD decision is not known yet */ + { + if ( st_ivas->hQMetaData != NULL ) + { + if ( ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode != ISM_MODE_NONE ) + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, (int32_t) ( 0.70f * st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC ), &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + else + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + else + { + /* note; "bits_frame_nominal" needed in TD stereo as well */ + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, hCPE->element_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + + if ( hCPE->element_mode == IVAS_CPE_TD ) + { + if ( hCPE->hStereoTD->tdm_LRTD_flag ) + { + sts[0]->bits_frame_nominal = (int16_t) ( ( hCPE->element_brate >> 1 ) / FRAMES_PER_SEC ); + sts[1]->bits_frame_nominal = (int16_t) ( ( hCPE->element_brate >> 1 ) / FRAMES_PER_SEC ); + } + else + { + stereo_dft_config( NULL, hCPE->element_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + + mvr2r( data_f_ch0, sts[0]->input, input_frame ); + if ( data_f_ch1 != NULL ) /*this may happen for cases with odd number of channels*/ + { + mvr2r( data_f_ch1, sts[1]->input, input_frame ); + } + + /*----------------------------------------------------------------* + * Stereo technology selection + * Front-VAD on input L and R channels + *----------------------------------------------------------------*/ + + if ( sts[0]->ini_frame > 0 && st_ivas->hMCT == NULL ) + { + hCPE->element_mode = select_stereo_mode( hCPE, ivas_format ); + } + + stereo_mode_combined_format_enc( st_ivas, hCPE ); + + if ( ( error = front_vad( hCPE, NULL, hEncoderConfig, &hCPE->hFrontVad[0], st_ivas->hMCT != NULL, input_frame, vad_flag_dtx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, vad_hover_flag, band_energies_LR, NULL, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + + sts[0]->element_mode = hCPE->element_mode; + sts[1]->element_mode = hCPE->element_mode; + + n_CoreChannels = 2; + if ( hCPE->element_mode == IVAS_CPE_DFT ) + { + n_CoreChannels = 1; /* in DFT stereo, only M channel is coded */ + + sts[1]->vad_flag = 0; + } + + /*----------------------------------------------------------------* + * dynamically allocate data structures depending on the actual stereo mode + *----------------------------------------------------------------*/ + + if ( ( error = stereo_memory_enc( hCPE, input_Fs, max_bwidth, &tdm_last_ratio, ivas_format, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } + + + /*----------------------------------------------------------------* + * Set TD stereo parameters + *----------------------------------------------------------------*/ + + if ( ( error = stereo_set_tdm( hCPE, input_frame ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*----------------------------------------------------------------* + * Resets/updates in case of stereo switching + *----------------------------------------------------------------*/ + + stereo_switching_enc( hCPE, sts[0]->old_input_signal, input_frame ); + + /*----------------------------------------------------------------* + * Temporal inter-channel alignment, stereo adjustment + *----------------------------------------------------------------*/ + + stereo_tca_enc( hCPE, input_frame ); + + /*----------------------------------------------------------------* + * Input signal buffering - needed in IC-BWE and TD ITD in MDCT stereo + *----------------------------------------------------------------*/ + + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + mvr2r( sts[n]->input, orig_input[n], input_frame ); + + if ( hCPE->hStereoICBWE != NULL ) + { + hCPE->hStereoICBWE->dataChan[n] = &orig_input[n][0]; + } + } + + /*---------------------------------------------------------------* + * Time Domain Transient Detector + *---------------------------------------------------------------*/ + + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + if ( sts[n]->hTranDet == NULL ) + { + currFlatness[n] = 0; + continue; + } + + if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) ) + { + RunTransientDetection( sts[n]->input, input_frame, sts[n]->hTranDet ); + } + currFlatness[n] = GetTCXAvgTemporalFlatnessMeasure( sts[n]->hTranDet, NSUBBLOCKS, 0 ); + } + + /* Synchonize detection for downmix-based stereo */ + if ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_TD ) + { + set_transient_stereo( hCPE, currFlatness ); + } + + /*----------------------------------------------------------------* + * Configuration of stereo encoder + *----------------------------------------------------------------*/ + + for ( n = 0; n < n_CoreChannels; n++ ) + { + /* Force to MODE1 in IVAS */ + sts[n]->codec_mode = MODE1; + + sts[n]->element_mode = hCPE->element_mode; + } + + if ( hCPE->element_mode != IVAS_CPE_MDCT && ( hCPE->element_brate != hCPE->last_element_brate || hCPE->last_element_mode != hCPE->element_mode || sts[0]->ini_frame == 0 || ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) || sts[0]->last_core_brate <= SID_2k40 ) ) /* If the last frame was SID or NO_DATA, we need to run stereo_dft_config here since VAD decision is not known yet */ { @@ -1607,6 +1823,26 @@ ivas_error create_cpe_enc( } } + // This should be removed when actual create_cpe_enc_fx +#ifdef IVAS_FLOAT_FIXED + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + IF( EQ_16( ivas_format, STEREO_FORMAT ) || EQ_16( ivas_format, MASA_FORMAT ) || ( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) + { + IF( ( hCPE->input_mem_fx[n] = (Word16 *) malloc( sizeof( Word16 ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + + set16_zero_fx( hCPE->input_mem_fx[n], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + } + ELSE + { + hCPE->input_mem_fx[n] = NULL; + } + } +#endif + /*-----------------------------------------------------------------* * stereo classifier: allocate and initialize *-----------------------------------------------------------------*/ @@ -1847,12 +2083,12 @@ ivas_error create_cpe_enc_fx( { IF( EQ_16( ivas_format, STEREO_FORMAT ) || EQ_16( ivas_format, MASA_FORMAT ) || ( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) { - IF( ( hCPE->input_mem_fx[n] = (Word32 *) malloc( sizeof( Word32 ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) + IF( ( hCPE->input_mem_fx[n] = (Word16 *) malloc( sizeof( Word16 ) * NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); } - set_zero_fx( hCPE->input_mem_fx[n], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + set16_zero_fx( hCPE->input_mem_fx[n], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); } ELSE { @@ -2060,76 +2296,81 @@ void destroy_cpe_enc( hCPE->hStereoClassif = NULL; } - FOR( n = 0; n < CPE_CHANNELS; n++ ) - { - IF( hCPE->input_mem[n] != NULL ) - { + FOR( n = 0; n < CPE_CHANNELS; n++ ){ + IF( hCPE->input_mem[n] != NULL ){ free( hCPE->input_mem[n] ); - hCPE->input_mem[n] = NULL; - } - } - - ivas_destroy_MD_bstr_enc( &( hCPE->hMetaData ) ); + hCPE->input_mem[n] = NULL; +} +#ifdef IVAS_FLOAT_FIXED +IF( hCPE->input_mem_fx[n] != NULL ) +{ + free( hCPE->input_mem_fx[n] ); + hCPE->input_mem_fx[n] = NULL; +} +#endif +} - FOR( n = 0; n < CPE_CHANNELS; n++ ) - { - st = hCPE->hCoreCoder[n]; +ivas_destroy_MD_bstr_enc( &( hCPE->hMetaData ) ); - IF( st != NULL ) - { - destroy_core_enc( st ); - st = NULL; - } - } +FOR( n = 0; n < CPE_CHANNELS; n++ ) +{ + st = hCPE->hCoreCoder[n]; - IF( hCPE->hStereoDft != NULL ) + IF( st != NULL ) { - stereo_dft_enc_destroy( &hCPE->hStereoDft ); - hCPE->hStereoDft = NULL; + destroy_core_enc( st ); + st = NULL; } +} - IF( hCPE->hStereoTD != NULL ) - { - free( hCPE->hStereoTD ); - hCPE->hStereoTD = NULL; - } +IF( hCPE->hStereoDft != NULL ) +{ + stereo_dft_enc_destroy( &hCPE->hStereoDft ); + hCPE->hStereoDft = NULL; +} - IF( hCPE->hStereoMdct != NULL ) - { - stereo_mdct_enc_destroy( &hCPE->hStereoMdct ); - hCPE->hStereoMdct = NULL; - } +IF( hCPE->hStereoTD != NULL ) +{ + free( hCPE->hStereoTD ); + hCPE->hStereoTD = NULL; +} - IF( hCPE->hStereoTCA != NULL ) - { - free( hCPE->hStereoTCA ); - hCPE->hStereoTCA = NULL; - } +IF( hCPE->hStereoMdct != NULL ) +{ + stereo_mdct_enc_destroy( &hCPE->hStereoMdct ); + hCPE->hStereoMdct = NULL; +} - IF( hCPE->hStereoICBWE != NULL ) - { - free( hCPE->hStereoICBWE ); - hCPE->hStereoICBWE = NULL; - } +IF( hCPE->hStereoTCA != NULL ) +{ + free( hCPE->hStereoTCA ); + hCPE->hStereoTCA = NULL; +} - IF( hCPE->hStereoCng != NULL ) - { - free( hCPE->hStereoCng ); - hCPE->hStereoCng = NULL; - } +IF( hCPE->hStereoICBWE != NULL ) +{ + free( hCPE->hStereoICBWE ); + hCPE->hStereoICBWE = NULL; +} - IF( hCPE->hFrontVad[0] != NULL ) +IF( hCPE->hStereoCng != NULL ) +{ + free( hCPE->hStereoCng ); + hCPE->hStereoCng = NULL; +} + +IF( hCPE->hFrontVad[0] != NULL ) +{ + FOR( n = 0; n < CPE_CHANNELS; n++ ) { - FOR( n = 0; n < CPE_CHANNELS; n++ ) - { - front_vad_destroy( &hCPE->hFrontVad[n] ); - hCPE->hFrontVad[n] = NULL; - } + front_vad_destroy( &hCPE->hFrontVad[n] ); + hCPE->hFrontVad[n] = NULL; } +} - free( hCPE ); +free( hCPE ); - return; +return; } diff --git a/lib_enc/ivas_mct_core_enc.c b/lib_enc/ivas_mct_core_enc.c index ba72415325d6461cbb10c0083e3cb2f499fd0543..eaa2195a93f38fe762adec00811acdbf4b94f3d6 100644 --- a/lib_enc/ivas_mct_core_enc.c +++ b/lib_enc/ivas_mct_core_enc.c @@ -52,7 +52,7 @@ * find ratio of channel energy to total energy for * bit distribution *----------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void FindChannelRatio( Encoder_State **sts, /* i/o: encoder state structure */ int16_t chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ @@ -94,14 +94,70 @@ static void FindChannelRatio( return; } +#else +static void FindChannelRatio_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + Word16 chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ + const Word16 nChannels /* i : number of channels to be coded */ +) +{ + Word32 sum_nrg, chRatio; + Word16 i, sum_e, inv_e; + Word32 nrg[MCT_MAX_CHANNELS]; + Word16 nrg_e[MCT_MAX_CHANNELS]; + set32_fx( nrg, 0, MCT_MAX_CHANNELS ); + set16_fx( nrg_e, 0, MCT_MAX_CHANNELS ); + + getChannelEnergies_fx( sts, nrg, nrg_e, nChannels ); + + /*calculate total energy without LFE*/ + sum_nrg = 0; + sum_e = 0; + move32(); + move16(); + + FOR( i = 0; i < nChannels; i++ ) + { + IF( NE_32( sts[i]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + // sum_nrg += nrg[i]; + sum_nrg = BASOP_Util_Add_Mant32Exp( sum_nrg, sum_e, nrg[i], nrg_e[i], &sum_e ); + } + } + // sum_nrg = 1.0f / max( sum_nrg, EPSILON ); + sum_nrg = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_add_sat( sum_nrg, EPSILON_FX ), &inv_e ); + inv_e = add( inv_e, sub( 0, sum_e ) ); + + FOR( i = 0; i < nChannels; i++ ) + { + IF( NE_32( sts[i]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + // chRatio = nrg[i] * sum_nrg; + // chBitRatios[i] = s_min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * chRatio + 0.5f ) ) ); + + chRatio = Mpy_32_16_1( nrg[i], extract_l( sum_nrg ) ); // Q = (31 - nrg_e[i]) + (15 - inv_e) - 15 + chRatio = L_shr_r( chRatio, sub( 27, add( nrg_e[i], inv_e ) ) ); + chBitRatios[i] = s_min( BITRATE_MCT_RATIO_RANGE - 1, s_max( 1, (UWord16) chRatio ) ); + move16(); + } + ELSE IF( EQ_32( sts[i]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + chBitRatios[i] = 0; + move16(); + } + } + + return; +} +#endif /*----------------------------------------------------------* * AdjustChannelRatios() * * adjust ratio of channels for bit distribution *----------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void AdjustChannelRatios( int16_t chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ const int16_t nChannels, /* i/o: number of channels */ @@ -115,11 +171,7 @@ static void AdjustChannelRatios( float cur_ratio, tar_ratio, sum_ratio, sum_tar_ratio; int16_t ratio_diff, i; -#ifdef IVAS_FLOAT_FIXED - ivas_spar_bitrate_dist_fx( temp_brs, nAvailBits, ivas_total_brate, sba_order, (Word16) FB ); -#else ivas_spar_bitrate_dist( temp_brs, nAvailBits, ivas_total_brate, sba_order, (int16_t) FB ); -#endif sum_ratio = 0.0f; for ( i = 0; i < nChannels; i++ ) @@ -174,6 +226,110 @@ static void AdjustChannelRatios( return; } +#else +static void AdjustChannelRatios_fx( + Word16 chBitRatios[MCT_MAX_CHANNELS], /* o : bit-disctribution channel ratios */ + const Word16 nChannels, /* i/o: number of channels */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + const Word16 nAvailBits, /* i : number of available bits */ + const Word16 sba_order /* i : Ambisonic (SBA) order */ +) +{ + Word16 force_ch_bit_ratios[IVAS_SPAR_MAX_DMX_CHS]; + Word32 temp_brs[IVAS_SPAR_MAX_DMX_CHS]; + Word16 cur_ratio, tar_ratio, sum_tar_ratio; + Word32 sum_ratio; + Word16 ratio_diff, i, cur_ratio_e, tmp0, tmp1; + + tmp0 = 0; + tmp1 = 0; + move16(); + move16(); + + ivas_spar_bitrate_dist_fx( temp_brs, nAvailBits, ivas_total_brate, sba_order, (Word16) FB ); + + sum_ratio = 0; + move32(); + FOR( i = 0; i < nChannels; i++ ) + { + sum_ratio = L_add( sum_ratio, temp_brs[i] ); + } + FOR( i = 0; i < nChannels; i++ ) + { + // cur_ratio = temp_brs[i] / sum_ratio; + // force_ch_bit_ratios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * cur_ratio + 0.5f ) ) ); + + cur_ratio = BASOP_Util_Divide3232_Scale( temp_brs[i], sum_ratio, &cur_ratio_e ); + cur_ratio = shr_r( cur_ratio, sub( 11, cur_ratio_e ) ); + force_ch_bit_ratios[i] = s_min( BITRATE_MCT_RATIO_RANGE - 1, s_max( 1, (UWord16) ( cur_ratio ) ) ); + move16(); + } + + /* adjust the ratios further based on received chBitRatios[]*/ + ratio_diff = 0; + sum_ratio = 0; + sum_tar_ratio = 0; + move16(); + move32(); + move16(); + FOR( i = 0; i < nChannels; i++ ) + { + sum_ratio = L_add( sum_ratio, L_deposit_l( chBitRatios[i] ) ); // Q0 + sum_tar_ratio = add( sum_tar_ratio, force_ch_bit_ratios[i] ); // Q0 + } + if ( sum_ratio == 0 ) + { + tmp0 = 1; + move16(); + } + if ( sum_tar_ratio == 0 ) + { + tmp1 = 1; + move16(); + } + FOR( i = 3; i < nChannels; i++ ) + { + cur_ratio = div_s( chBitRatios[i], add( extract_l( sum_ratio ), tmp0 ) ); // Q15 + tar_ratio = div_s( force_ch_bit_ratios[i], add( sum_tar_ratio, tmp1 ) ); // Q15 + + tar_ratio = s_min( tar_ratio, cur_ratio ); + chBitRatios[i] = mult( tar_ratio, sum_tar_ratio ); // Q0 + chBitRatios[i] = s_max( 1, chBitRatios[i] ); + move16(); + move16(); + assert( chBitRatios[i] < ( BITRATE_MCT_RATIO_RANGE - 1 ) ); + ratio_diff = add( ratio_diff, sub( force_ch_bit_ratios[i], chBitRatios[i] ) ); + } + + FOR( i = 0; i < s_min( 3, nChannels ); i++ ) + { + assert( force_ch_bit_ratios[i] >= 0 ); + chBitRatios[i] = s_min( BITRATE_MCT_RATIO_RANGE - 1, force_ch_bit_ratios[i] ); + move16(); + } + chBitRatios[1] = add( chBitRatios[1], ratio_diff ); + move16(); + + /* make sure final ratios are within range*/ + sum_ratio = 0; + move32(); + FOR( i = 0; i < nChannels; i++ ) + { + sum_ratio = L_add( sum_ratio, chBitRatios[i] ); + } + FOR( i = 0; i < nChannels; i++ ) + { + // cur_ratio = chBitRatios[i] / sum_ratio; + // chBitRatios[i] = min( BITRATE_MCT_RATIO_RANGE - 1, max( 1, (uint16_t) ( BITRATE_MCT_RATIO_RANGE * cur_ratio + 0.5f ) ) ); + + cur_ratio = div_s( chBitRatios[i], extract_l( sum_ratio ) ); + chBitRatios[i] = s_min( BITRATE_MCT_RATIO_RANGE - 1, s_max( 1, (UWord16) mult_r( BITRATE_MCT_RATIO_RANGE, cur_ratio ) ) ); + move16(); + } + + return; +} +#endif /*-------------------------------------------------------------------* @@ -1069,70 +1225,63 @@ void ivas_mct_core_enc( /*--------------------------------------------------------------* * 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 ); + FindChannelRatio_fx( sts, chBitRatios, nChannels ); - nAvailBits = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - NBITS_BWIDTH - hMCT->nBitsMCT - lfe_bits ); + // nAvailBits = (int16_t) ( ( ivas_total_brate / FRAMES_PER_SEC ) - NBITS_BWIDTH - hMCT->nBitsMCT - lfe_bits ); + nAvailBits = sub( sub( sub( extract_l( Mpy_32_32( ivas_total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) ), NBITS_BWIDTH ), hMCT->nBitsMCT ), lfe_bits ); /* subtract IVAS format signaling bits */ - if ( ivas_format == MC_FORMAT ) + test(); + IF( EQ_32( ivas_format, MC_FORMAT ) ) { - nAvailBits -= IVAS_FORMAT_SIGNALING_NBITS; - nAvailBits -= MC_LS_SETUP_BITS; + nAvailBits = sub( nAvailBits, IVAS_FORMAT_SIGNALING_NBITS ); + nAvailBits = sub( nAvailBits, MC_LS_SETUP_BITS ); } - else if ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) + ELSE IF( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( 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 = sub( nAvailBits, IVAS_FORMAT_SIGNALING_NBITS_EXTENDED ); + nAvailBits = sub( nAvailBits, SBA_ORDER_BITS + SBA_PLANAR_BITS ); + test(); + if ( EQ_32( ivas_format, SBA_ISM_FORMAT ) && GT_16( nChannels, 4 ) ) { - nAvailBits -= IVAS_COMBINED_FORMAT_SIGNALLING_BITS; + nAvailBits = sub( nAvailBits, IVAS_COMBINED_FORMAT_SIGNALLING_BITS ); } } - for ( cpe_id = 0, i = 0; cpe_id < nCPE; cpe_id++ ) + 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; + nAvailBits = sub( nAvailBits, hCPE[cpe_id]->hMetaData->nb_bits_tot ); } } /*substract bits needed for the bitrate ratios */ - for ( ch = 0; ch < nChannels; ch++ ) + FOR( ch = 0; ch < nChannels; ch++ ) { - if ( - sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; } - nAvailBits -= NBBITS_MCT_RATIO; + nAvailBits = sub( 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 */ + nAvailBits = sub( nAvailBits, add( total_side_bits, hMCT->nchan_out_woLFE ) ); /* if MC 1 extra bit that was initially send to signal LFE_off */ - if ( hMCT->hbr_mct ) + IF( hMCT->hbr_mct ) { assert( ivas_total_brate >= IVAS_256k ); - AdjustChannelRatios( chBitRatios, nChannels, ivas_total_brate, nAvailBits, sba_order ); + AdjustChannelRatios_fx( chBitRatios, nChannels, ivas_total_brate, nAvailBits, sba_order ); } - for ( ch = 0; ch < nChannels; ch++ ) + FOR( ch = 0; ch < nChannels; ch++ ) { - if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; } push_next_indice( hBstr, chBitRatios[ch], NBBITS_MCT_RATIO ); @@ -1141,16 +1290,17 @@ void ivas_mct_core_enc( /*distribute bits amongst channels*/ splitAvailableBitsMCT( (void **) sts, nAvailBits, chBitRatios, ENC, nChannels ); - 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++ ) { st = hCPE[cpe_id]->hCoreCoder[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; } - st->total_brate = ( st->bits_frame_channel + st->side_bits_frame_channel ) * FRAMES_PER_SEC; + st->total_brate = L_mult0( add( st->bits_frame_channel, st->side_bits_frame_channel ), FRAMES_PER_SEC ); + move32(); } } diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index 0fac502c14803c5a9660fef328973a53b77c5eef..b87a0fe8a8397c7cac2e8b34d6171173fa99aaaf 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -458,6 +458,14 @@ ivas_error ivas_mct_enc( } } } + + 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 // 1 /* joint MCT encoding */ diff --git a/lib_enc/ivas_mct_enc_mct.c b/lib_enc/ivas_mct_enc_mct.c index 066f7a55770a385abc22d20b05252302d81a7cd7..8f7030dfbb797a1e32a8217206c5b625b245d921 100644 --- a/lib_enc/ivas_mct_enc_mct.c +++ b/lib_enc/ivas_mct_enc_mct.c @@ -56,7 +56,7 @@ * * Calculate energy for each cahnnel *-------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void getChannelEnergies( Encoder_State **sts, /* i/o: Encoder state structure */ float nrg[MCT_MAX_CHANNELS], /* o : buffer with energies for each channel */ @@ -87,7 +87,7 @@ void getChannelEnergies( return; } -#ifdef IVAS_FLOAT_FIXED +#else void getChannelEnergies_fx( Encoder_State **sts, /* i/o: Encoder state structure */ Word32 nrg[MCT_MAX_CHANNELS], /* o : buffer with energies for each channel */ diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index 1afadbb2caad9907ce7083f6a8e1cd8d1aaf8258..c06dc405a87a1fb842a4041ee9569b00051449df 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -128,18 +128,32 @@ const float xtalk_mean_dft[SIZE_XTALK_ISEL_DFT] = 14.629498f, 0.000570f, 0.011686f }; +const Word32 xtalk_mean_dft_q15[SIZE_XTALK_ISEL_DFT] = +{ + 60702, 6939, -106610, 24840, 778767, 53543, -102081000, 13874, 479379, 19, 383 +}; + const float xtalk_scale_dft[SIZE_XTALK_ISEL_DFT] = { 1.507352f, 0.159956f, 2.497517f, 0.469123f, 2.825375f, 0.932028f, 261.555949f, 0.205413f, 35.216496f, 0.001153f, 0.025744f }; +const Word32 xtalk_scale_dft_q15[SIZE_XTALK_ISEL_DFT] = +{ + 49393, 5241, 81839, 15372, 92582, 30541, 8570665, 6731, 1153974, 38, 844 +}; + const float xtalk_coef_dft[SIZE_XTALK_ISEL_DFT] = { -0.082911f, -0.057949f, 0.089754f, -0.167106f, 1.289470f, 0.054620f, 0.667244f, -0.358486f, 0.032200f, 1.141818f, 1.824479f }; +const Word32 xtalk_coef_dft_q30[SIZE_XTALK_ISEL_DFT] = +{ + -89025008, -62222264, 96372624, -179428704, 1384557824, 58647780, 716447808, -384921408, 34574488, 1226017792, 1959019392 +}; /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables @@ -268,6 +282,7 @@ const float win_ana_48k[STEREO_DFT_OVL_MAX] = { 0.9993626f, 0.9994536f, 0.9995375f, 0.9996144f, 0.9996844f, 0.9997473f, 0.9998033f, 0.9998523f, 0.9998942f, 0.9999292f, 0.9999572f, 0.9999781f, 0.9999921f, 0.9999991f }; +#if 0 const Word32 win_ana_8k_fx[STEREO_DFT_OVL_8k] = { 227468560, 393953952, 508506944, 601521984, 681832704, 753477952, 818704064, 878911808, 935043776, 987769024, 1037582080, 1084861312, 1129901952, 1172940800, 1214170112, 1253748608, 1291809152, 1328463616, 1363808000, 1397923968, 1430883328, 1462748160, 1493572736, 1523405312, 1552288384, 1580259968, 1607353984, @@ -362,6 +377,84 @@ const Word32 win_ana_48k_fx[STEREO_DFT_OVL_MAX] = { 2143680896, 2144011392, 2144327040, 2144627456, 2144913152, 2145183488, 2145438848, 2145679360, 2145904640, 2146114816, 2146310272, 2146490496, 2146655616, 2146805888, 2146940928, 2147061248, 2147166464, 2147256448, 2147331584, 2147391744, 2147436672, 2147466624, 2147481728 }; +#endif + +const Word16 win_ana_8k_fx[STEREO_DFT_OVL_8k] = { + 3471, 6011, 7759, 9178, 10404, 11497, 12492, 13411, 14268, 15072, 15832, 16554, 17241, 17898, 18527, 19131, 19711, 20271, + 20810, 21331, 21834, 22320, 22790, 23245, 23686, 24113, 24526, 24927, 25315, 25691, 26055, 26407, 26749, 27079, 27399, + 27708, 28007, 28295, 28574, 28843, 29102, 29352, 29592, 29823, 30045, 30257, 30461, 30656, 30841, 31018, 31186, 31345, + 31496, 31638, 31772, 31897, 32013, 32121, 32221, 32312, 32395, 32470, 32536, 32594, 32643, 32684, 32717, 32742, 32759, 32767 +}; + +const Word16 win_ana_12k8_fx[STEREO_DFT_OVL_12k8] = { + 2744, 4753, 6135, 7259, 8229, 9096, 9887, 10618, 11300, 11943, 12552, 13131, 13685, 14216, 14726, 15218, 15693, 16152, + 16598, 17030, 17449, 17857, 18255, 18642, 19019, 19388, 19747, 20098, 20441, 20777, 21105, 21426, 21741, 22048, 22350, + 22645, 22934, 23217, 23495, 23767, 24034, 24295, 24552, 24803, 25049, 25291, 25528, 25760, 25987, 26210, 26429, 26643, + 26853, 27059, 27260, 27457, 27651, 27840, 28025, 28206, 28384, 28557, 28727, 28892, 29054, 29213, 29367, 29518, 29665, + 29809, 29949, 30085, 30218, 30348, 30473, 30596, 30715, 30830, 30942, 31050, 31155, 31257, 31355, 31450, 31541, 31630, + 31714, 31796, 31874, 31949, 32020, 32088, 32153, 32215, 32273, 32328, 32380, 32429, 32474, 32516, 32555, 32590, 32622, + 32652, 32677, 32700, 32719, 32735, 32748, 32758, 32764, 32767 +}; + +const Word16 win_ana_16k_fx[STEREO_DFT_OVL_16k] = { + 2454, 4251, 5488, 6493, 7361, 8137, 8845, 9500, 10112, 10688, 11234, 11754, 12251, 12729, 13188, 13631, 14059, 14473, + 14875, 15266, 15646, 16016, 16377, 16729, 17072, 17408, 17736, 18057, 18372, 18680, 18982, 19278, 19568, 19853, 20133, + 20407, 20677, 20942, 21202, 21458, 21709, 21957, 22200, 22439, 22674, 22905, 23133, 23357, 23577, 23794, 24007, 24217, + 24424, 24628, 24828, 25025, 25219, 25410, 25598, 25783, 25965, 26144, 26320, 26494, 26664, 26832, 26997, 27160, 27320, + 27477, 27631, 27783, 27933, 28080, 28224, 28366, 28505, 28642, 28777, 28909, 29038, 29166, 29290, 29413, 29533, 29651, + 29766, 29879, 29990, 30099, 30205, 30309, 30411, 30510, 30608, 30703, 30796, 30886, 30975, 31061, 31145, 31227, 31306, + 31384, 31459, 31532, 31604, 31672, 31739, 31804, 31866, 31927, 31985, 32041, 32095, 32147, 32197, 32245, 32290, 32334, + 32375, 32414, 32452, 32487, 32520, 32551, 32580, 32607, 32632, 32654, 32675, 32693, 32710, 32724, 32737, 32747, 32755, + 32762, 32766, 32767 +}; + +const Word16 win_ana_32k_fx[STEREO_DFT_OVL_32k] = { + 1735, 3006, 3881, 4591, 5206, 5755, 6257, 6720, 7154, 7563, 7951, 8320, 8674, 9013, 9341, 9657, 9962, 10259, 10547, + 10827, 11100, 11366, 11626, 11881, 12129, 12373, 12611, 12845, 13075, 13300, 13521, 13739, 13953, 14164, 14371, 14575, + 14776, 14974, 15169, 15362, 15552, 15739, 15924, 16107, 16287, 16465, 16641, 16815, 16987, 17157, 17325, 17491, 17655, + 17817, 17978, 18137, 18294, 18450, 18604, 18756, 18907, 19057, 19205, 19351, 19496, 19640, 19782, 19924, 20063, 20202, + 20339, 20475, 20610, 20744, 20876, 21007, 21138, 21267, 21394, 21521, 21647, 21772, 21895, 22018, 22139, 22260, 22379, + 22498, 22616, 22732, 22848, 22963, 23076, 23189, 23301, 23412, 23522, 23632, 23740, 23848, 23954, 24060, 24165, 24269, + 24373, 24475, 24577, 24678, 24778, 24877, 24976, 25074, 25171, 25267, 25362, 25457, 25551, 25644, 25737, 25828, 25919, + 26010, 26099, 26188, 26276, 26364, 26450, 26536, 26622, 26706, 26790, 26874, 26956, 27038, 27119, 27200, 27280, 27359, + 27438, 27516, 27593, 27670, 27746, 27821, 27896, 27970, 28043, 28116, 28188, 28260, 28331, 28401, 28471, 28540, 28608, + 28676, 28743, 28810, 28876, 28941, 29006, 29070, 29134, 29197, 29259, 29321, 29383, 29443, 29503, 29563, 29622, 29680, + 29738, 29795, 29851, 29907, 29963, 30018, 30072, 30126, 30179, 30231, 30283, 30335, 30386, 30436, 30486, 30535, 30584, + 30632, 30679, 30726, 30773, 30819, 30864, 30909, 30953, 30996, 31040, 31082, 31124, 31166, 31207, 31247, 31287, 31326, + 31365, 31403, 31441, 31478, 31514, 31550, 31586, 31621, 31655, 31689, 31723, 31756, 31788, 31820, 31851, 31882, 31912, + 31941, 31971, 31999, 32027, 32055, 32082, 32108, 32134, 32160, 32185, 32209, 32233, 32256, 32279, 32301, 32323, 32344, + 32365, 32385, 32405, 32424, 32443, 32461, 32478, 32495, 32512, 32528, 32543, 32558, 32573, 32587, 32600, 32613, 32626, + 32637, 32649, 32660, 32670, 32680, 32689, 32698, 32706, 32714, 32721, 32728, 32734, 32740, 32745, 32749, 32753, 32757, + 32760, 32763, 32765, 32766, 32767, 32767, +}; + +const Word16 win_ana_48k_fx[STEREO_DFT_OVL_MAX] = { + 1417, 2454, 3168, 3749, 4251, 4699, 5109, 5488, 5842, 6176, 6493, 6795, 7084, 7361, 7629, 7887, 8137, 8380, 8616, 8845, + 9069, 9287, 9500, 9708, 9912, 10112, 10307, 10500, 10688, 10873, 11055, 11234, 11410, 11583, 11754, 11922, 12088, 12251, + 12413, 12572, 12729, 12884, 13037, 13188, 13337, 13485, 13631, 13775, 13918, 14059, 14198, 14337, 14473, 14609, 14743, + 14875, 15007, 15137, 15266, 15394, 15521, 15646, 15770, 15894, 16016, 16137, 16257, 16377, 16495, 16612, 16729, 16844, + 16958, 17072, 17185, 17297, 17408, 17518, 17628, 17736, 17844, 17951, 18057, 18163, 18268, 18372, 18475, 18578, 18680, + 18781, 18882, 18982, 19081, 19180, 19278, 19375, 19472, 19568, 19664, 19759, 19853, 19947, 20040, 20133, 20225, 20316, + 20407, 20498, 20588, 20677, 20766, 20854, 20942, 21029, 21116, 21202, 21288, 21373, 21458, 21542, 21626, 21709, 21792, + 21875, 21957, 22038, 22119, 22200, 22280, 22360, 22439, 22518, 22596, 22674, 22752, 22829, 22905, 22982, 23057, 23133, + 23208, 23283, 23357, 23431, 23504, 23577, 23650, 23722, 23794, 23866, 23937, 24007, 24078, 24148, 24217, 24287, 24356, + 24424, 24492, 24560, 24628, 24695, 24761, 24828, 24894, 24960, 25025, 25090, 25155, 25219, 25283, 25347, 25410, 25473, + 25535, 25598, 25660, 25721, 25783, 25844, 25904, 25965, 26025, 26084, 26144, 26203, 26262, 26320, 26378, 26436, 26494, + 26551, 26608, 26664, 26721, 26776, 26832, 26888, 26943, 26997, 27052, 27106, 27160, 27213, 27267, 27320, 27372, 27425, + 27477, 27529, 27580, 27631, 27682, 27733, 27783, 27834, 27883, 27933, 27982, 28031, 28080, 28128, 28176, 28224, 28272, + 28319, 28366, 28413, 28459, 28505, 28551, 28597, 28642, 28687, 28732, 28777, 28821, 28865, 28909, 28952, 28995, 29038, + 29081, 29123, 29166, 29207, 29249, 29290, 29332, 29372, 29413, 29453, 29493, 29533, 29573, 29612, 29651, 29690, 29728, + 29766, 29804, 29842, 29879, 29917, 29954, 29990, 30027, 30063, 30099, 30135, 30170, 30205, 30240, 30275, 30309, 30343, + 30377, 30411, 30444, 30478, 30510, 30543, 30576, 30608, 30640, 30671, 30703, 30734, 30765, 30796, 30826, 30856, 30886, + 30916, 30945, 30975, 31004, 31032, 31061, 31089, 31117, 31145, 31172, 31200, 31227, 31254, 31280, 31306, 31333, 31358, + 31384, 31409, 31434, 31459, 31484, 31508, 31532, 31556, 31580, 31604, 31627, 31650, 31672, 31695, 31717, 31739, 31761, + 31782, 31804, 31825, 31846, 31866, 31887, 31907, 31927, 31946, 31966, 31985, 32004, 32023, 32041, 32059, 32077, 32095, + 32113, 32130, 32147, 32164, 32180, 32197, 32213, 32229, 32245, 32260, 32275, 32290, 32305, 32319, 32334, 32348, 32361, + 32375, 32388, 32402, 32414, 32427, 32439, 32452, 32464, 32475, 32487, 32498, 32509, 32520, 32530, 32541, 32551, 32561, + 32570, 32580, 32589, 32598, 32607, 32615, 32623, 32632, 32639, 32647, 32654, 32661, 32668, 32675, 32681, 32687, 32693, + 32699, 32705, 32710, 32715, 32720, 32724, 32729, 32733, 32737, 32740, 32744, 32747, 32750, 32753, 32755, 32758, 32760, + 32762, 32763, 32765, 32766, 32767, 32767, 32767, 32767 +}; const float win_syn_8k[STEREO_DFT_OVL_8k] = { 0.0011884f, 0.0061737f, 0.0132770f, 0.0219768f, 0.0320069f, 0.0431939f, 0.0554104f, 0.0685561f, 0.0825479f, 0.0973143f, 0.1127919f, 0.1289238f, 0.1456574f, 0.1629441f, diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index bec7df35711e59daba6e246f1ef1c0f921bbfdaf..89cdee23f6bc3495404e026dd4b163e2672dba12 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -55,8 +55,11 @@ extern const float xtalk_coef_td[]; extern const int16_t xtalk_isel_dft[]; extern const float xtalk_mean_dft[]; +extern const Word32 xtalk_mean_dft_q15[]; extern const float xtalk_scale_dft[]; +extern const Word32 xtalk_scale_dft_q15[]; extern const float xtalk_coef_dft[]; +extern const Word32 xtalk_coef_dft_q30[]; extern const int16_t unclr_isel_dft[]; extern const float unclr_mean_dft[]; @@ -95,11 +98,11 @@ extern const float win_syn_48k[STEREO_DFT_OVL_MAX]; extern const float win_mdct_8k[STEREO_DFT_OVL_8k]; -extern const Word32 win_ana_8k_fx[STEREO_DFT_OVL_8k]; -extern const Word32 win_ana_12k8_fx[STEREO_DFT_OVL_12k8]; -extern const Word32 win_ana_16k_fx[STEREO_DFT_OVL_16k]; -extern const Word32 win_ana_32k_fx[STEREO_DFT_OVL_32k]; -extern const Word32 win_ana_48k_fx[STEREO_DFT_OVL_MAX]; +extern const Word16 win_ana_8k_fx[STEREO_DFT_OVL_8k]; +extern const Word16 win_ana_12k8_fx[STEREO_DFT_OVL_12k8]; +extern const Word16 win_ana_16k_fx[STEREO_DFT_OVL_16k]; +extern const Word16 win_ana_32k_fx[STEREO_DFT_OVL_32k]; +extern const Word16 win_ana_48k_fx[STEREO_DFT_OVL_MAX]; extern const Word32 win_syn_8k_fx[STEREO_DFT_OVL_8k]; extern const Word32 win_syn_12k8_fx[STEREO_DFT_OVL_12k8]; diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 668dc5a26f0d3e487dafd4346db956e46edaff07..00c909825f6688b0ddf65c40aa7667694857084d 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -71,35 +71,43 @@ typedef struct stereo_itd_data_struct int16_t detected_itd_flag; int16_t itd_tracking; float prev_max; - Word16 prev_max_fx; + Word32 prev_max_fx; // Q31 int16_t prev_index; float prev_avg_max; - Word16 prev_avg_max_fx; + Word32 prev_avg_max_fx; + Word16 prev_avg_max_fx_e; float currFlatness; - Word16 currFlatness_fx; + Word32 currFlatness_fx; + Word16 currFlatness_fx_e; /* Xtalk classifier */ float prev_m1; - Word16 prev_m1_fx; + Word32 prev_m1_fx; // Q31 float prev_m2; - Word16 prev_m2_fx; + Word32 prev_m2_fx; // Q31 int16_t prev_itd1; int16_t prev_itd2; /*flag for hybrid ITD for very large ITDs*/ int16_t hybrid_itd_max; + Word32 itd_fx[STEREO_DFT_ENC_DFT_NB]; // Q16 Word32 acorr_L_fx[STEREO_DFT_BAND_MAX]; + Word16 acorr_L_fx_e; Word32 acorr_R_fx[STEREO_DFT_BAND_MAX]; - Word16 cohSNR_fx; /*Q11*/ - Word16 itd_thres_fx; + Word16 acorr_R_fx_e; + Word32 cohSNR_fx; /*Q16*/ + Word32 itd_thres_fx; // Q31 Word32 prev_sum_nrg_L_lb_fx; + Word16 prev_sum_nrg_L_lb_fx_e; Word32 prev_xcorr_lb_fx[STEREO_DFT_XCORR_LB_MAX]; + Word16 prev_xcorr_lb_fx_e; Word32 E_band_n_fx[STEREO_DFT_ITD_VAD_BAND_NUM]; /*Q0*/ Word32 xcorr_smooth_fx[STEREO_DFT_N_32k_ENC]; - Word32 lp_phat_peak_fx; /* low-pass GCC PHAT peak value */ - Word32 itd_fx[STEREO_DFT_ENC_DFT_NB]; - Word32 deltaItd_fx[STEREO_DFT_ENC_DFT_NB]; + Word16 xcorr_smooth_fx_e; + Word32 lp_phat_peak_fx; /* low-pass GCC PHAT peak value */ // Q31 + // Word16 q_itd; + Word32 deltaItd_fx[STEREO_DFT_ENC_DFT_NB]; // Q16 } ITD_DATA, *ITD_DATA_HANDLE; @@ -117,7 +125,7 @@ typedef struct dft_ana_struct const float *dft_trigo; const float *dft_trigo_32k; - const Word32 *win_ana_fx; /* DFT analysis window */ + const Word16 *win_ana_fx; /* DFT analysis window */ const Word16 *dft_trigo_fx; const Word16 *dft_trigo_32k_fx; @@ -206,7 +214,7 @@ typedef struct stereo_dft_enc_data_struct /*Side Gain*/ float side_gain[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; - Word32 side_gain_fx[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; + Word32 side_gain_fx[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; // Q31 int16_t side_gain_flag_1; int16_t side_gain_flag_2; int16_t side_gain_index_ECDiff[STEREO_DFT_BAND_MAX]; @@ -326,9 +334,9 @@ typedef struct stereo_dft_enc_data_struct Word32 nrg_L_fx[2]; Word32 nrg_R_fx[2]; Word32 nrg_DMX_fx[2]; - Word32 res_pred_gain_fx[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; /*prediction gain for the residual HFs */ - Word32 gainIPD_sm_fx; /* long-term gain IPD for NIPD detection */ ////initilizae in Q31 - Word32 sfm_fx; + Word32 res_pred_gain_fx[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; /*prediction gain for the residual HFs */ /* Q31 */ + Word32 gainIPD_sm_fx; /* long-term gain IPD for NIPD detection */ ////initilizae in Q31 + Word32 sfm_fx; // Q31 Word32 sum_dot_prod_real_fx; Word32 sum_dot_prod_img_fx; Word32 dot_prod_real_smooth_fx[STEREO_DFT_BAND_MAX]; @@ -336,8 +344,11 @@ typedef struct stereo_dft_enc_data_struct Word32 ipd_buf_fx[STEREO_DFT_BAND_MAX][STEREO_DFT_IPD_BUF_LEN]; Word32 prev_gipd_fx; Word32 xspec_smooth_fx[STEREO_DFT_N_32k_ENC]; + Word16 xspec_smooth_fx_e; Word32 Spd_L_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; + Word16 Spd_L_smooth_fx_e; Word32 Spd_R_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; + Word16 Spd_R_smooth_fx_e; Word32 sid_gipd_fx; const Word32 *win_fx; /* DFT window */ const Word32 *win_8k_fx; /* DFT window */ @@ -345,11 +356,11 @@ typedef struct stereo_dft_enc_data_struct const Word32 *win_16k_fx; /* DFT window */ const Word32 *win_32k_fx; /* DFT window */ - const Word32 *win_ana_fx; /* DFT analysis window */ - const Word32 *win_ana_8k_fx; /* DFT analysis window */ - const Word32 *win_ana_12k8_fx; /* DFT analysis window */ - const Word32 *win_ana_16k_fx; /* DFT analysis window */ - const Word32 *win_ana_32k_fx; /* DFT analysis window */ + const Word16 *win_ana_fx; /* DFT analysis window */ + const Word16 *win_ana_8k_fx; /* DFT analysis window */ + const Word16 *win_ana_12k8_fx; /* DFT analysis window */ + const Word16 *win_ana_16k_fx; /* DFT analysis window */ + const Word16 *win_ana_32k_fx; /* DFT analysis window */ const Word32 *win_mdct_8k_fx; /* DFT analysis window */ @@ -374,8 +385,9 @@ typedef struct stereo_dft_enc_data_struct Word32 output_mem_dmx_16k_fx[STEREO_DFT_OVL_16k]; /*can hold 16, 12.8 or 32kHz signals*/ // Q16 Word32 output_mem_dmx_32k_fx[STEREO_DFT_OVL_32k]; /*can hold 16, 12.8 or 32kHz signals*/ // Q16 Word32 output_mem_dmx_16k_shb_fx[STEREO_DFT_OVL_16k]; // Q16 - Word32 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX]; - Word32 gipd_fx[STEREO_DFT_ENC_DFT_NB]; + Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX]; + Word16 q_input_mem_itd[CPE_CHANNELS]; + Word32 gipd_fx[STEREO_DFT_ENC_DFT_NB]; // Q13 } STEREO_DFT_ENC_DATA, *STEREO_DFT_ENC_DATA_HANDLE; @@ -669,7 +681,7 @@ typedef struct ivas_stereo_classifier_data_structure Word32 ps_diff_ch1_fx, ps_diff_ch2_fx; float ps_sta_ch1, ps_sta_ch2; float prev_g_IPD; - float prev_IPD; + float prev_IPD; // Q29 float prev_ratio_m1_m2; float ratio_L; Word16 vad_flag_glob; @@ -717,12 +729,14 @@ typedef struct ivas_stereo_classifier_data_structure Word32 non_sta_ch1_fx; Word32 sp_div_ch1_fx; Word32 ps_sta_ch1_fx, ps_sta_ch2_fx; - Word32 prev_g_IPD_fx; - Word32 prev_IPD_fx; - Word32 prev_ratio_m1_m2_fx; + Word32 prev_g_IPD_fx; // Q29 + Word32 prev_IPD_fx; // Q29 + Word32 prev_ratio_m1_m2_fx; // Q31 Word32 ratio_L_fx; Word32 ave_ener_L_fx; /* average energy of the L channel */ + Word16 ave_ener_L_fx_e; /* average energy of the L channel */ Word32 ave_ener_R_fx; /* average energy of the R channel */ + Word16 ave_ener_R_fx_e; /* average energy of the R channel */ Word32 Etot_dn_fx; /* average energy in dB - lower bound */ Word32 Etot_up_fx; /* average energy in dB - upper bound */ Word32 relE_buf_fx[UNCLR_L_RELE]; /* running buffer for relative energy */ @@ -731,11 +745,11 @@ typedef struct ivas_stereo_classifier_data_structure Word32 relE_0_1_LT_fx; Word32 unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER]; Word32 unclr_wscore_fx; - Word32 unclr_fv_fx[SSC_MAX_NFEA]; /* UNCLR - feature vector */ - Word32 xtalk_score_buf_fx[XTALK_SCORE_BUF_LEN]; - Word32 xtalk_fv_fx[SSC_MAX_NFEA]; /* xtalk - feature vector */ + Word32 unclr_fv_fx[SSC_MAX_NFEA]; /* UNCLR - feature vector */ // Q16 + Word32 xtalk_score_buf_fx[XTALK_SCORE_BUF_LEN]; // Q31 + Word32 xtalk_fv_fx[SSC_MAX_NFEA]; /* xtalk - feature vector */ // Q16 Word32 xtalk_wscore_fx; - Word32 xtalk_score_fx; + Word32 xtalk_score_fx; // Q31 Word32 xtalk_score_wrelE_fx; Word32 is_speech_fx; @@ -1251,7 +1265,8 @@ typedef struct cpe_enc_data_structure float *input_mem[CPE_CHANNELS]; /* input channels buffers memory; needed to be up-to-date for TD->DFT stereo switching */ Word32 brate_surplus; /* bitrate surplus for bitrate adaptation in combined format coding */ - Word32 *input_mem_fx[CPE_CHANNELS]; /* input channels buffers memory; needed to be up-to-date for TD->DFT stereo switching */ + Word16 *input_mem_fx[CPE_CHANNELS]; /* input channels buffers memory; needed to be up-to-date for TD->DFT stereo switching */ + Word16 q_input_mem[CPE_CHANNELS]; } CPE_ENC_DATA, *CPE_ENC_HANDLE; diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 22d07cf28cd8e2d2479d7299b1381b6e31f953a4..9f1275e97f9ca26b898e189b7b72caa8895ecdea 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -48,17 +48,20 @@ * Local constants *-------------------------------------------------------------------*/ -#define RC_FACT_UP 0.3f -#define RC_FACT_DOWN 0.7f -#define UNCLR_SCORE_THR 4.0f -#define XTALK_SCORE_THR_DFT 4.0f -#define XTALK_SCORE_THR_TD_UP 3.0f -#define XTALK_SCORE_THR_TD_DN 4.0f - -#define UNCLR_INTERCEPT_TD 0.780313f -#define UNCLR_INTERCEPT_DFT 1.226513f -#define XTALK_INTERCEPT_TD -1.770983f -#define XTALK_INTERCEPT_DFT -0.758556f +#define RC_FACT_UP 0.3f +#define RC_FACT_DOWN 0.7f +#define UNCLR_SCORE_THR 4.0f +#define XTALK_SCORE_THR_DFT 4.0f +#define XTALK_SCORE_THR_DFT_Q27 ( 1 << 29 ) +#define XTALK_SCORE_THR_TD_UP 3.0f +#define XTALK_SCORE_THR_TD_DN 4.0f + +#define UNCLR_INTERCEPT_TD 0.780313f +#define UNCLR_INTERCEPT_DFT 1.226513f +#define XTALK_INTERCEPT_TD -1.770983f +#define XTALK_INTERCEPT_DFT -0.758556f +#define XTALK_INTERCEPT_DFT_Q31 -1628986606 +#define XTALK_INTERCEPT_DFT_Q27 -101811663 #define EDGE_MAX_LEN 30 /* maximum length of buffer for edge detection */ #define REDGE_MAX_LEN 30 /* maximum length of buffer for rising edge detection */ @@ -74,6 +77,9 @@ static void rc_filter( const float x, float *y, const int16_t order, const float static void edge_detect( const float *inp, const int16_t len, const float inp_min, const float inp_max, float *edge_str, int16_t *edge_type ); +#ifdef IVAS_FLOAT_FIXED +static Word32 redge_detect_fx( const Word32 *inp, const Word16 len, const Word32 inp_min, const Word32 inp_max, Word16 *edge_min_e ); +#endif static float redge_detect( const float *inp, const int16_t len, const float inp_min, const float inp_max ); @@ -335,8 +341,10 @@ void stereo_classifier_init_fx( set32_fx( hStereoClassif->unclr_fv_fx, -2147483647 - 1, SSC_MAX_NFEA ); // Q31 hStereoClassif->unclr_corrLagMax_prev = 0; - hStereoClassif->ave_ener_L = 0; - hStereoClassif->ave_ener_R = 0; + hStereoClassif->ave_ener_L_fx = 0; + hStereoClassif->ave_ener_L_fx_e = 0; + hStereoClassif->ave_ener_R_fx = 0; + hStereoClassif->ave_ener_R_fx_e = 0; hStereoClassif->relE_0_1_fx = 21474836; // Q31 hStereoClassif->relE_0_1_LT_fx = 21474836; // Q31 @@ -873,6 +881,231 @@ void xtalk_classifier_td( * Classify current DFT frame as cross-talk frame (1) or normal stereo frame (0) *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void xtalk_classifier_dft_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word16 itd, /* i : ITD from DFT stereo - used as a feature */ + const Word32 gcc_phat[] /* i : GPHAT cross-channel correlation function Q31*/ +) +{ + Word16 i, ind, itd2, thr; + Word32 score, m1, m2; + STEREO_CLASSIF_HANDLE hStereoClassif; + ITD_DATA_HANDLE hItd; + Word32 fvn[SSC_MAX_NFEA] /*Q28*/, edge; + Word16 edge_e; + Word16 edge_0_1, wedge; + Word32 ratio_m1_m2, m2_m2, d_itd2, itd1_flip; + Word32 scr_min, scr_max; + + hStereoClassif = hCPE->hStereoClassif; + hItd = ( hCPE->hStereoDft != NULL ) ? hCPE->hStereoDft->hItd : hCPE->hStereoMdct->hItd; + + m1 = 0; + move32(); + m2 = 0; + move32(); + + itd2 = 0; + move16(); + // thr = ( hCPE->element_brate >= IVAS_32k ? 2 : 1 ) * CLASSIFIER_ITD_THRES; + IF( GE_32( hCPE->element_brate, IVAS_32k ) ) + { + thr = 2 * CLASSIFIER_ITD_THRES; + move16(); + } + ELSE + { + thr = CLASSIFIER_ITD_THRES; + move16(); + } + IF( GT_16( itd, thr ) ) + { + m1 = L_abs( gcc_phat[itd + XTALK_PHAT_LEN] ); + m2 = L_abs( gcc_phat[0] ); + itd2 = -XTALK_PHAT_LEN; + move16(); + FOR( i = 1; i < sub( XTALK_PHAT_LEN, thr ); i++ ) + { + IF( GT_32( L_abs( gcc_phat[i] ), m2 ) ) + { + itd2 = add( -XTALK_PHAT_LEN, i ); + m2 = L_abs( gcc_phat[i] ); + } + } + } + ELSE IF( LT_16( itd, negate( thr ) ) ) + { + m1 = L_abs( gcc_phat[itd + XTALK_PHAT_LEN] ); + m2 = L_abs( gcc_phat[XTALK_PHAT_LEN + thr + 1] ); + itd2 = add( thr, 1 ); + FOR( i = add( XTALK_PHAT_LEN + 2, thr ); i < 2 * XTALK_PHAT_LEN + 1; i++ ) + { + IF( GT_32( L_abs( gcc_phat[i] ), m2 ) ) + { + itd2 = add( -XTALK_PHAT_LEN, i ); + m2 = L_abs( gcc_phat[i] ); + } + } + } + + // ratio_m1_m2 = fabsf( m1 * m2 ) / fabsf( m1 + m2 + 1.0f ); + Word16 exp; + ratio_m1_m2 = BASOP_Util_Divide3232_Scale_cadence( L_abs( Mpy_32_32( m1, m2 ) ), L_abs( L_add( L_add( L_shr( m1, 2 ), L_shr( m2, 2 ) ), ONE_IN_Q29 ) ), &exp ); + exp = sub( exp, 2 ); + // m2_m2 = hItd->prev_m2 * m2; + m2_m2 = Mpy_32_32( hItd->prev_m2_fx, m2 ); + // d_itd2 = (float) abs( itd2 - hItd->prev_itd2 ); + d_itd2 = abs_s( sub( itd2, hItd->prev_itd2 ) ); // Q0 + // itd1_flip = (float) ( max( itd, hItd->prev_itd1 ) * ( -min( itd, hItd->prev_itd1 ) ) ); + itd1_flip = L_mult0( s_max( itd, hItd->prev_itd1 ), negate( s_min( itd, hItd->prev_itd1 ) ) ); // Q0 + + + hStereoClassif->xtalk_fv_fx[E_gphat_d_itd2] = L_shl( d_itd2, 15 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_gphat_itd1_flip] = L_shl( itd1_flip, 15 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_gphat_ratio_m1_m2] = L_shr_r( Mpy_32_32( ratio_m1_m2, hStereoClassif->prev_ratio_m1_m2_fx ), sub( Q16, exp ) ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_gphat_m2_m2] = L_shr_r( m2_m2, Q16 ); // Q15 + move32(); + + hStereoClassif->prev_ratio_m1_m2_fx = L_shl( ratio_m1_m2, exp ); + move32(); + + set32_fx( fvn, -ONE_IN_Q29, SSC_MAX_NFEA ); + + /* calcualte raw score based on LR */ + score = XTALK_INTERCEPT_DFT_Q27; + move32(); + FOR( i = 0; i < SIZE_XTALK_ISEL_DFT; i++ ) + { + ind = xtalk_isel_dft[i]; + move16(); + + /* mean & std removal */ + // fvn[i] = ( hStereoClassif->xtalk_fv[ind] - xtalk_mean_dft[i] ) / xtalk_scale_dft[i]; + fvn[i] = BASOP_Util_Divide3232_Scale_cadence( L_sub( hStereoClassif->xtalk_fv_fx[ind], xtalk_mean_dft_q15[i] ), xtalk_scale_dft_q15[i], &exp ); // Q15 + move32(); + fvn[i] = L_shl_sat( fvn[i], sub( exp, 2 ) ); // Q29 + move32(); + + /* LR */ + // score += fvn[i] * xtalk_coef_dft[i]; + score = L_add( score, L_shr( Mpy_32_32( fvn[i], xtalk_coef_dft_q30[i] ), 1 ) ); // Q27 + } + + /* normalize score to -1:+1 */ + IF( GT_32( score, XTALK_SCORE_THR_DFT_Q27 ) ) + { + score = MAX_32; // Q31 + move32(); + } + ELSE IF( LT_32( score, -XTALK_SCORE_THR_DFT_Q27 ) ) + { + score = MIN_32; // Q31 + move32(); + } + ELSE + { + // score /= XTALK_SCORE_THR_DFT; + score = L_shl_sat( score, 2 ); // Q27->Q31/XTALK_SCORE_THR_DFT + } + + /* raw score */ + hStereoClassif->xtalk_score_fx = score; + move32(); + // printf( "%f ", (float) hStereoClassif->xtalk_score_fx / 0x7fffffff ); + + if ( !hStereoClassif->vad_flag_glob ) + { + score = 0; + move32(); + } + + + /* rising edge detector on raw score -> yields 1 if strong rising edge is detected in the given buffer */ + Copy32( &hStereoClassif->xtalk_score_buf_fx[0], &hStereoClassif->xtalk_score_buf_fx[1], XTALK_SCORE_BUF_LEN - 1 ); + hStereoClassif->xtalk_score_buf_fx[0] = score; + + minimum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_min ); + maximum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_max ); + + test(); + IF( LT_32( scr_min, 429496730 /*0.2f*/ ) && scr_max > 0 ) + { + edge = redge_detect_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, -429496730 /*-0.2f*/, MAX_32 /*1.0f*/, &edge_e ); + // edge_0_1 = lin_interp( 1 - edge, 1.0f, 1.0f, 0.83f, 0.0f, 1 ); + Word16 temp; + Word16 temp_e = BASOP_Util_Add_MantExp( MAX_16, 0, negate( extract_h( edge ) ), edge_e, &temp ); + temp = shl( temp, temp_e ); // Q15 + edge_0_1 = lin_interp_ivas_fx( temp, MAX_16, MAX_16, 27197, 0, 1 ); + } + ELSE + { + edge_0_1 = 0; + move16(); + } + + /* weight raw score based on rising edge detector */ + // wedge = lin_interp( edge_0_1, 0.0f, 0.95f, 1.0f, 0.3f, 1 ); + wedge = lin_interp_ivas_fx( edge_0_1, 0, 31129, MAX_16, 9830, 1 ); + // hStereoClassif->xtalk_wscore = wedge * hStereoClassif->xtalk_wscore + ( 1 - wedge ) * score; + hStereoClassif->xtalk_wscore_fx = L_add( Mpy_32_16_1( hStereoClassif->xtalk_wscore_fx, wedge ), Mpy_32_16_1( score, sub( MAX_16, wedge ) ) ); + move32(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( itd == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 ) ) + { + hStereoClassif->xtalk_decision = 0; + move16(); + } + ELSE IF( GE_32( hCPE->element_brate, IVAS_24k4 ) && + hStereoClassif->xtalk_decision == 0 && ( ( LT_32( Mpy_32_32( m1, 1717986918 /*0.8f*/ ), m2 ) && LT_32( Mpy_32_32( hItd->prev_m1_fx, 1717986918 /*0.8*/ ), hItd->prev_m2_fx ) && LT_16( abs_s( sub( itd2, hItd->prev_itd2 ) ), 4 ) && GT_32( m1, 322122547 /*0.15*/ ) && GT_32( hItd->prev_m1_fx, 322122547 /*0.15*/ ) ) || GT_32( hStereoClassif->xtalk_wscore_fx, 1717986918 /*0.8*/ ) || ( GT_16( itd, thr ) && LT_16( hItd->prev_itd1, negate( thr ) ) && hStereoClassif->silence_flag == 0 ) || ( GT_16( hItd->prev_itd1, thr ) && LT_16( itd, negate( thr ) ) && hStereoClassif->silence_flag == 0 ) ) && + EQ_16( hCPE->hCoreCoder[0]->vad_flag, 1 ) && hCPE->hCoreCoder[0]->flag_noisy_speech_snr == 0 && GT_16( hCPE->hCoreCoder[0]->hNoiseEst->aEn_inac_cnt, 15 ) ) + { + hStereoClassif->xtalk_decision = 1; + move16(); + } + ELSE IF( GE_32( hCPE->element_brate, IVAS_16k4 ) && hStereoClassif->xtalk_decision == 0 && GT_16( abs_s( itd ), STEREO_DFT_ITD_MAX ) && GT_16( sub( hCPE->hCoreCoder[0]->lp_speech_fx, hCPE->hCoreCoder[0]->lp_noise_fx ), 25 << 8 ) ) + { + hStereoClassif->xtalk_decision = 1; + move16(); + } + + + /* updates */ + hItd->prev_m1_fx = m1; + move32(); + hItd->prev_m2_fx = m2; + move32(); + hItd->prev_itd1 = itd; + move16(); + hItd->prev_itd2 = itd2; + move16(); + + return; +} +#endif void xtalk_classifier_dft( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const int16_t itd, /* i : ITD from DFT stereo - used as a feature */ @@ -1162,6 +1395,101 @@ static void edge_detect( * Analyzes the input buffer and outputs value close to 1 when it detects strong rising edge *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/*! r: rising edge strength normalized to 0-1 */ +static Word32 redge_detect_fx( + const Word32 *inp, /* i : input buffer (ordered from newest to oldest values)*/ + const Word16 len, /* i : length of the input buffer */ + const Word32 inp_min, /* i : minimum value for edge detection */ + const Word32 inp_max, /* i : maximum value for edge detection */ + Word16 *edge_min_e ) +{ + Word16 i, j; + Word32 y, err, edge_slope, edge[REDGE_MAX_LEN]; + Word16 y_e, edge_slope_e, edge_e[REDGE_MAX_LEN]; + Word32 edge_min, err0; + Word16 err0_e; + Word16 L_temp_e; + Word32 L_temp; + + set32_fx( edge, 0, REDGE_MAX_LEN ); + set16_fx( edge_e, 0, REDGE_MAX_LEN ); + edge_min = 10000000 /*1e7f*/; // Q0 + move32(); + *edge_min_e = 31; + move16(); + + /* test rising edges on intervals from 2 to len */ + IF( GT_32( inp[0], inp_max ) ) + { + err0 = 0; + move32(); + err0_e = 0; + move16(); + } + ELSE + { + // err0 = powf( inp[0] - inp_max, 2 ); + // Word32 temp = L_sub( inp[0], inp_max ); + err0 = BASOP_Util_Add_Mant32Exp( inp[0], 0, L_negate( inp_max ), 0, &err0_e ); + err0 = Mpy_32_32( err0, err0 ); + err0_e = shl( err0_e, 1 ); + } + FOR( i = 1; i < len; i++ ) + { + // edge_slope = ( inp_max - inp_min ) / i; + L_temp = BASOP_Util_Add_Mant32Exp( inp_max, 0, L_negate( inp_min ), 0, &L_temp_e ); + edge_slope = BASOP_Util_Divide3232_Scale_cadence( L_temp, i, &edge_slope_e ); + edge_slope_e = add( edge_slope_e, sub( L_temp_e, 31 ) ); + edge[i] = err0; + move32(); + edge_e[i] = err0_e; + move16(); + FOR( j = 1; j < i; j++ ) + { + // y = inp_max - edge_slope * j; + y = BASOP_Util_Add_Mant32Exp( inp_max, 0, L_negate( Mpy_32_32( edge_slope, L_shl( j, 28 ) ) ), add( edge_slope_e, 3 ), &y_e ); + y = L_shl( y, y_e ); + IF( EQ_32( inp[j], inp[j - 1] ) && EQ_32( inp[j], inp_max ) ) + { + /* we are saturated at inp_max */ + err = 0; + move32(); + } + ELSE IF( LT_32( inp[j], inp_min ) ) + { + /* we are below inp_min */ + err = L_sub( y, inp_min ); + } + ELSE + { + err = L_sub( y, inp[j] ); + } + err = Mpy_32_32( err, err ); + // edge[i] = L_add( edge[i], err ); + edge[i] = BASOP_Util_Add_Mant32Exp( edge[i], edge_e[i], err, 0, &edge_e[i] ); + move32(); + } + + // edge[i] /= i + 1; + edge[i] = BASOP_Util_Divide3232_Scale_cadence( edge[i], add( i, 1 ), &L_temp_e ); + move32(); + edge_e[i] = add( L_temp_e, sub( edge_e[i], 31 ) ); + move16(); + + // if ( edge[i] < edge_min ) + IF( BASOP_Util_Cmp_Mant32Exp( edge[i], edge_e[i], edge_min, *edge_min_e ) < 0 ) + { + edge_min = edge[i]; + move32(); + *edge_min_e = edge_e[i]; + move16(); + } + } + + return edge_min; // Q31 +} +#endif /*! r: rising edge strength normalized to 0-1 */ static float redge_detect( const float *inp, /* i : input buffer (ordered from newest to oldest values)*/ diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index 8fb7d28c8e57be01883dc9bd897db97dfb8d251f..78503c93840775f866112194f6a6ce86dd6cb67a 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -26,7 +26,7 @@ Any dispute, controversy or claim arising under or in relation to providing this software shall be submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. + the United Nations Convention on Contracts on the International Sales of Goods.q_inp *******************************************************************************************************/ @@ -389,12 +389,35 @@ static void stereo_dft_enc_open( hStereoDft->win_16k = win_syn_16k; hStereoDft->win_32k = win_syn_32k; +// need to remove this once fixed function is called // +#ifdef IVAS_FLOAT_FIXED + hStereoDft->dft_trigo_8k_fx = dft_trigo_32k_fx; + hStereoDft->dft_trigo_12k8_fx = dft_trigo_12k8_fx; + hStereoDft->dft_trigo_16k_fx = dft_trigo_32k_fx; + hStereoDft->dft_trigo_32k_fx = dft_trigo_32k_fx; + + hStereoDft->win_ana_8k_fx = win_ana_8k_fx; + hStereoDft->win_ana_12k8_fx = win_ana_12k8_fx; + hStereoDft->win_ana_16k_fx = win_ana_16k_fx; + hStereoDft->win_ana_32k_fx = win_ana_32k_fx; + + hStereoDft->win_8k_fx = win_syn_8k_fx; + hStereoDft->win_12k8_fx = win_syn_12k8_fx; + hStereoDft->win_16k_fx = win_syn_16k_fx; + hStereoDft->win_32k_fx = win_syn_32k_fx; +#endif + if ( input_Fs == 16000 ) { hStereoDft->dft_trigo = dft_trigo_32k; hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP; hStereoDft->win_ana = win_ana_16k; hStereoDft->win = win_syn_16k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->dft_trigo_fx = dft_trigo_32k_fx; + hStereoDft->win_ana_fx = win_ana_16k_fx; + hStereoDft->win_fx = win_syn_16k_fx; +#endif } else if ( input_Fs == 32000 ) { @@ -402,6 +425,11 @@ static void stereo_dft_enc_open( hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_32k_STEP; hStereoDft->win_ana = win_ana_32k; hStereoDft->win = win_syn_32k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->dft_trigo_fx = dft_trigo_32k_fx; + hStereoDft->win_ana_fx = win_ana_32k_fx; + hStereoDft->win_fx = win_syn_32k_fx; +#endif } else { @@ -410,9 +438,17 @@ static void stereo_dft_enc_open( hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_48k_STEP; hStereoDft->win_ana = win_ana_48k; hStereoDft->win = win_syn_48k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->dft_trigo_fx = dft_trigo_48k_fx; + hStereoDft->win_ana_fx = win_ana_48k_fx; + hStereoDft->win_fx = win_syn_48k_fx; +#endif } hStereoDft->win_mdct_8k = win_mdct_8k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->win_mdct_8k_fx = win_mdct_8k_fx; +#endif /*I/O Buffers*/ set_zero( hStereoDft->output_mem_dmx, STEREO_DFT_OVL_MAX ); @@ -717,6 +753,9 @@ void stereo_dft_enc_reset( stereo_enc_itd_init( hStereoDft->hItd ); +#ifdef IVAS_FLOAT_FIXED + stereo_enc_itd_init_fx( hStereoDft->hItd ); +#endif return; } @@ -883,18 +922,23 @@ void stereo_enc_itd_init_fx( set16_fx( hItd->td_itd_32k, 0, STEREO_DFT_ENC_DFT_NB ); set16_fx( hItd->itd_index, 0, STEREO_DFT_ENC_DFT_NB ); set32_fx( hItd->xcorr_smooth_fx, 0, STEREO_DFT_N_32k_ENC ); + hItd->xcorr_smooth_fx_e = 0; hItd->lp_phat_peak_fx = 0; hItd->itd_hangover = 0; hItd->itd_cnt = 0; hItd->prev_sum_nrg_L_lb_fx = 0; + hItd->prev_sum_nrg_L_lb_fx_e = 0; set32_fx( hItd->prev_xcorr_lb_fx, 0, STEREO_DFT_XCORR_LB_MAX ); + hItd->prev_xcorr_lb_fx_e = 0; set32_fx( hItd->E_band_n_fx, ITD_VAD_E_BAND_N_INIT, STEREO_DFT_ITD_VAD_BAND_NUM ); hItd->vad_frm_cnt = 0; hItd->pre_vad = 0; hItd->itd_nonzero_cnt = 0; set32_fx( hItd->acorr_L_fx, 0, STEREO_DFT_BAND_MAX ); + hItd->acorr_L_fx_e = 0; set32_fx( hItd->acorr_R_fx, 0, STEREO_DFT_BAND_MAX ); - hItd->cohSNR_fx = 30720; /*Q11*/ + hItd->acorr_R_fx_e = 0; + hItd->cohSNR_fx = 983040; /*Q16*/ hItd->itd_thres_fx = 0; hItd->valid_itd_cnt = 0; @@ -903,7 +947,9 @@ void stereo_enc_itd_init_fx( hItd->prev_max_fx = 0; hItd->prev_index = 0; hItd->prev_avg_max_fx = 0; + hItd->prev_avg_max_fx_e = 0; hItd->currFlatness_fx = 0; + hItd->currFlatness_fx_e = 0; /* Xtalk classifier */ hItd->prev_m1_fx = 0; @@ -921,6 +967,97 @@ void stereo_enc_itd_init_fx( * Update DFT stereo memories for new frame *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_update_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word16 max_bwidth /* i : maximum encoded bandwidth */ +) +{ + Word16 i, k_offset; + Word16 NFFT_inner; + + /* Initialization */ + k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ + move32(); + + /* Update the parameters and serial */ + FOR( i = 0; i < imult1616( k_offset, STEREO_DFT_BAND_MAX ); i++ ) + { + hStereoDft->side_gain_fx[i] = hStereoDft->side_gain_fx[STEREO_DFT_BAND_MAX + i]; + move32(); + hStereoDft->res_pred_gain_fx[i] = hStereoDft->res_pred_gain_fx[STEREO_DFT_BAND_MAX + i]; + move32(); + } + + FOR( i = 0; i < k_offset; i++ ) + { + hStereoDft->gipd_fx[i] = hStereoDft->gipd_fx[i + 1]; + move32(); + } + + /*Update configurations*/ + FOR( i = 0; i < k_offset; i++ ) + { + hStereoDft->band_res[i] = hStereoDft->band_res[i + 1]; + move16(); + hStereoDft->hItd->itd_fx[i] = hStereoDft->hItd->itd_fx[i + 1]; + move32(); + hStereoDft->res_cod_mode[i] = hStereoDft->res_cod_mode[i + 1]; + move16(); + hStereoDft->res_pred_mode[i] = hStereoDft->res_pred_mode[i + 1]; + move16(); + } + + /*Set new configurations*/ + hStereoDft->band_res[k_offset] = hStereoDft->hConfig->band_res; + move16(); + + IF( hStereoDft->hConfig->ada_wb_res_cod_mode && EQ_16( hStereoDft->NFFT, STEREO_DFT_N_16k_ENC ) ) + { + hStereoDft->res_cod_mode[k_offset] = hStereoDft->hConfig->ada_wb_res_cod_mode; + move16(); + } + ELSE + { + hStereoDft->res_cod_mode[k_offset] = hStereoDft->hConfig->res_cod_mode; + move16(); + } + hStereoDft->res_pred_mode[k_offset] = hStereoDft->hConfig->res_pred_mode; + move16(); + + hStereoDft->last_res_cod_mode_modify_flag = hStereoDft->res_cod_sw_flag; + move16(); + hStereoDft->res_cod_sw_flag = 0; + move16(); + + /* update band limits in case of rate switching assuming max_bwidth as BWD output not yet know here */ + NFFT_inner = shl( inner_frame_tbl[max_bwidth], 1 ) /* * STEREO_DFT_N_MAX_ENC / L_FRAME48k*/; + + hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->hConfig->band_res, NFFT_inner, ENC ); + move16(); + hStereoDft->nbands_dmx = stereo_dft_band_config_fx( hStereoDft->band_limits_dmx, 1, NFFT_inner, ENC ); + move16(); + + /*Compute main parameters*/ + hStereoDft->gipd_band_max = dft_band_ipd[1][3]; + move16(); + hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; + move16(); + // hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * hStereoDft->N / (float) ( hStereoDft->NFFT ) ); + Word32 tmp = L_shl( L_mult0( sub( hStereoDft->band_limits[hStereoDft->res_cod_band_max], 1 ), hStereoDft->N ), 1 ); + Word16 exp; + tmp = BASOP_Util_Divide3232_Scale_cadence( tmp, hStereoDft->N, &exp ); + hStereoDft->res_cod_line_max = extract_l( L_shr( tmp, sub( 31, exp ) ) ); + move16(); + hStereoDft->res_cod_line_max = shl( shr( hStereoDft->res_cod_line_max, 3 ), 3 ); + move16(); + hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + move16(); + + + return; +} +#else void stereo_dft_enc_update( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ const int16_t max_bwidth /* i : maximum encoded bandwidth */ @@ -990,7 +1127,7 @@ void stereo_dft_enc_update( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_destroy() @@ -1155,6 +1292,194 @@ void stereo_dft_enc_analyze( return; } +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_analyze_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + const Word16 n_channels, /* i : number of input channels */ + const Word16 input_frame, /* i : input frame length */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ) +{ + Word16 i, n; + Word32 *pDFT_L, *pDFT_R; + Word16 N, NFFT; + Word16 dft_zp, dft_ovl; + const Word16 *pWin; + const Word16 *pTrigo; + Word16 offset; + Word16 *input[CPE_CHANNELS], *mem[CPE_CHANNELS]; + Word16 trigo_enc[STEREO_DFT_N_MAX_ENC / 2 + 1]; + Word16 trigo_step; + + + push_wmops( "DFT_analysis" ); + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + FOR( n = 0; n < n_channels; n++ ) + { + input[n] = sts[n]->input_fx; + mem[n] = input_mem[n]; + } + + + /*-----------------------------------------------------------------* + * DFT Analysis + *-----------------------------------------------------------------*/ + + pDFT_L = DFT[0]; + pDFT_R = DFT[1]; + + IF( hStereoDft != NULL ) + { + N = hStereoDft->N; + move16(); + NFFT = hStereoDft->NFFT; + move16(); + dft_zp = hStereoDft->dft_zp; + move16(); + dft_ovl = hStereoDft->dft_ovl; + move16(); + offset = negate( dft_ovl ); + pWin = hStereoDft->win_ana_fx; + pTrigo = hStereoDft->dft_trigo_fx; + trigo_step = hStereoDft->dft_trigo_step; + move16(); + } + ELSE + { + N = hStereoMdct->hDft_ana->N; + move16(); + NFFT = hStereoMdct->hDft_ana->NFFT; + move16(); + dft_zp = hStereoMdct->hDft_ana->dft_zp; + move16(); + dft_ovl = hStereoMdct->hDft_ana->dft_ovl; + move16(); + offset = negate( dft_ovl ); + pWin = hStereoMdct->hDft_ana->win_ana_fx; + pTrigo = hStereoMdct->hDft_ana->dft_trigo_fx; + trigo_step = hStereoMdct->hDft_ana->dft_trigo_step; + move16(); + } + + FOR( i = 0; i < shr( NFFT, 2 ); i++ ) + { + trigo_enc[i] = pTrigo[i * trigo_step]; + move16(); + trigo_enc[sub( shr( NFFT, 1 ), i )] = pTrigo[L_mult0( i, trigo_step )]; + move16(); + } + trigo_enc[shr( NFFT, 2 )] = pTrigo[L_mult0( shr( NFFT, 2 ), trigo_step )]; + move16(); + + /*Forwards FFT: L and R*/ + /*zero padding*/ + FOR( i = 0; i < dft_zp; i++ ) + { + pDFT_L[i] = 0; + move32(); + pDFT_L[sub( sub( NFFT, 1 ), i )] = 0; + move32(); + + pDFT_R[i] = 0; + move32(); + pDFT_R[sub( sub( NFFT, 1 ), i )] = 0; + move32(); + } + + FOR( n = 0; n < n_channels; n++ ) + { + Scale_sig( &mem[n][0], dft_ovl, sts[n]->q_inp - q_input_mem[n] ); + q_input_mem[n] = sts[n]->q_inp; + move16(); + } + /*overlapping parts*/ + FOR( i = 0; i < dft_ovl; i++ ) + { + pDFT_L[add( dft_zp, i )] = L_mult0( mem[0][i], pWin[i] ); + move32(); + pDFT_L[sub( add( add( dft_zp, N ), dft_ovl ) - 1, i )] = L_mult0( input[0][sub( add( add( offset, N ), dft_ovl ) - 1, i )], pWin[i] ); + move32(); + + pDFT_R[add( dft_zp, i )] = L_mult0( mem[1][i], pWin[i] ); + move32(); + pDFT_R[sub( add( add( dft_zp, N ), dft_ovl ) - 1, i )] = L_mult0( input[1][sub( add( add( offset, N ), dft_ovl ) - 1, i )], pWin[i] ); + move32(); + } + + /*middle part*/ + FOR( i = 0; i < N - dft_ovl; i++ ) + { + pDFT_L[add( add( dft_zp, dft_ovl ), i )] = L_shr( L_deposit_h( input[0][add( add( offset, dft_ovl ), i )] ), 1 ); + move32(); + + pDFT_R[add( add( dft_zp, dft_ovl ), i )] = L_shr( L_deposit_h( input[1][add( add( offset, dft_ovl ), i )] ), 1 ); + move32(); + } + hStereoDft->DFT_fx_e[0] = sub( 31, add( 15, sts[0]->q_inp ) ); + move16(); + hStereoDft->DFT_fx_e[1] = sub( 31, add( 15, sts[1]->q_inp ) ); + move16(); + + Word16 q_shift, guarded_bits; + guarded_bits = find_guarded_bits_fx( NFFT ); + q_shift = sub( getScaleFactor32( pDFT_L, NFFT ), guarded_bits ); + q_shift = s_min( q_shift, sub( getScaleFactor32( pDFT_R, NFFT ), guarded_bits ) ); + FOR( Word16 j = 0; j < NFFT; j++ ) + { + pDFT_L[j] = L_shl( pDFT_L[j], q_shift ); + move32(); + } + + hStereoDft->DFT_fx_e[0] = sub( hStereoDft->DFT_fx_e[0], q_shift ); + move16(); + + FOR( Word16 j = 0; j < NFFT; j++ ) + { + pDFT_R[j] = L_shl( pDFT_R[j], q_shift ); + move32(); + } + + hStereoDft->DFT_fx_e[1] = sub( hStereoDft->DFT_fx_e[1], q_shift ); + move16(); + + rfft_fx( pDFT_L, trigo_enc, NFFT, -1 ); + rfft_fx( pDFT_R, trigo_enc, NFFT, -1 ); + + /* update pointers to overlap memory */ + FOR( n = 0; n < n_channels; n++ ) + { + mem[n] = &input[n][sub( N, dft_ovl )]; + } + + IF( hStereoDft != NULL && hStereoDft->hConfig->hybrid_itd_flag && hStereoDft->hItd->td_itd[STEREO_DFT_OFFSET] ) + { + FOR( n = 0; n < n_channels; n++ ) + { + Scale_sig( hStereoDft->input_mem_itd_fx[n], STEREO_DFT_OVL_MAX, sts[n]->q_inp - hStereoDft->q_input_mem_itd[n] ); + hStereoDft->q_input_mem_itd[n] = sts[n]->q_inp; + move16(); + Copy( hStereoDft->input_mem_itd_fx[n], input_mem[n], dft_ovl ); + } + } + ELSE + { + FOR( n = 0; n < n_channels; n++ ) + { + Copy( input[n] + input_frame - dft_ovl, input_mem[n], dft_ovl ); + } + } + + pop_wmops(); + return; +} +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_synthesize() @@ -1187,7 +1512,8 @@ Word32 stereo_dft_enc_synthesize_fx( Word32 *mem_fx; // const float *trigo, *win, *win_ana; const Word16 *trigo_fx; - const Word32 *win_fx, *win_ana_fx; + const Word32 *win_fx; + const Word16 *win_ana_fx; // float tmp[STEREO_DFT_N_MAX_ENC]; Word32 tmp_fx[STEREO_DFT_N_MAX_ENC]; // float nrg; @@ -1560,7 +1886,7 @@ Word32 stereo_dft_enc_synthesize_fx( move32(); // output[offset + N + i] = ( tmp[zp + N + i] - ifft_deviation ) / win_ana[ovl - 1 - i] + ifft_deviation; Word16 L_temp_e; - Word32 L_temp = BASOP_Util_Divide3232_Scale_cadence( L_sub_sat( tmp_fx[zp + N + i], ifft_deviation ), win_ana_fx[ovl - 1 - i], &L_temp_e ); + Word32 L_temp = BASOP_Util_Divide3232_Scale_cadence( L_sub_sat( tmp_fx[zp + N + i], ifft_deviation ), L_deposit_h( win_ana_fx[ovl - 1 - i] ), &L_temp_e ); L_temp = L_shl_sat( L_temp, L_temp_e ); output_fx[offset + N + i] = L_add_sat( L_temp, ifft_deviation ); // Q16 move32(); @@ -1869,34 +2195,949 @@ float stereo_dft_enc_synthesize( * 1) compute/encode stereo parameters * 2) Mid/Side computation *-------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +#if 0 // def IVAS_FLOAT_FIXED void stereo_dft_enc_process( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ - const int16_t vad_hover_flag[], /* i : VAD hangover flags */ - const int16_t input_frame /* i : input frame length */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : input frame length */ ) { - int16_t i, j, b; - float *pDFT_L, *pDFT_R; - float *pDFT_DMX; - float *pDFT_RES; - int16_t k_offset; - float *pgIpd; - float *pSideGain; - float c, alpha, g; - float wL, wR, wS; - float tmp; - float s, c1, s1; - float fac_att; + Word16 i, j, b; + Word32 *pDFT_L, *pDFT_R; + Word32 *pDFT_DMX; + Word32 *pDFT_RES; + Word16 k_offset; + Word32 *pgIpd; + Word32 *pSideGain; + Word32 c, alpha, g; + Word32 wL, wR, wS; + Word32 tmp; + Word32 s, c1, s1; + Word32 fac_att; STEREO_DFT_ENC_DATA_HANDLE hStereoDft; - float DFT_DMX[STEREO_DFT_N_MAX_ENC]; - float DFT_RES[STEREO_DFT_N_8k_ENC]; - int32_t input_Fs; - float bin_nrgL[STEREO_DFT_N_MAX_ENC]; - float bin_nrgR[STEREO_DFT_N_MAX_ENC]; - float *pNrgL, *pNrgR; - float res_nrg_all_curr, dmx_nrg_all_curr; + Word32 DFT_DMX[STEREO_DFT_N_MAX_ENC]; + Word32 DFT_RES[STEREO_DFT_N_8k_ENC]; + Word32 input_Fs; + Word32 bin_nrgL[STEREO_DFT_N_MAX_ENC]; + Word32 bin_nrgR[STEREO_DFT_N_MAX_ENC]; + Word32 *pNrgL, *pNrgR; + Word32 res_nrg_all_curr, dmx_nrg_all_curr; + Word32 res_dmx_ratio, frame_nrg_ratio; + Word32 dot_prod_nrg_ratio[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands */ + Word32 sum_nrg_L2, sum_nrg_R2, dot_prod_real2; + Word32 sum_nrg_Mid, sum_abs; + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + input_Fs = L_mult0( input_frame, FRAMES_PER_SEC ); + + hStereoDft = hCPE->hStereoDft; + + wL = 0; /* avoid compilation warning */ + wR = 0; /* avoid compilation warning */ + + /* Initialization */ + k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ + + hStereoDft->gipd_band_max = dft_band_ipd[1][3]; + hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->res_cod_mode[k_offset]]; + //hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * input_frame / (float) ( hStereoDft->NFFT ) ); + Word32 tmp = L_shl(L_mult0(sub(hStereoDft->band_limits[hStereoDft->res_cod_band_max], 1), hStereoDft->N), 1); + Word16 exp; + tmp = BASOP_Util_Divide1616_Scale(tmp, hStereoDft->N, &exp); + hStereoDft->res_cod_line_max = extract_l(L_shr(tmp, sub(31, exp))); + hStereoDft->res_cod_line_max = shl(shr(hStereoDft->res_cod_line_max, 3), 3); + + hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + + + // hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[0]; + // hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[1]; + + hStereoDft->voicing_lt_fx = L_add( Mpy_32_16_1( hStereoDft->voicing_lt_fx, 24576 ), L_mult( 8192, hCPE->hCoreCoder[0]->voicing_fx[0] ) ); + hStereoDft->voicing_lt_fx = L_add( Mpy_32_16_1( hStereoDft->voicing_lt_fx, 24576 ), L_mult( 8192, hCPE->hCoreCoder[0]->voicing_fx[1] ) ); + /*------------------------------------------------------------------* + * Compute stereo parameters + *-----------------------------------------------------------------*/ + + /*ITD in Frequency domain*/ + fac_att = MAX_32; + + pDFT_L = hStereoDft->DFT_fx[0]; + pDFT_R = hStereoDft->DFT_fx[1]; + + { + stereo_dft_enc_compute_itd( hCPE, pDFT_L, pDFT_R, k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL, bin_nrgR ); + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + return; + } + + if ( hStereoDft->hItd->deltaItd[k_offset] != 0 && hStereoDft->hConfig->dmx_active ) + { + /*time shift channels*/ + alpha = -2.0f * EVS_PI * hStereoDft->hItd->deltaItd[k_offset] / hStereoDft->NFFT; + c = 1.f; /*cos(0)*/ + s = 0.f; /*sin(0)*/ + c1 = cosf( alpha ); + s1 = sinf( alpha ); + + if ( alpha >= 0 ) + { + for ( i = 1; i < hStereoDft->NFFT / 2; i++ ) + { + tmp = s * c1 + c * s1; + c = c * c1 - s * s1; + s = tmp; + + /*time shift of L*/ + tmp = pDFT_L[2 * i] * c - pDFT_L[2 * i + 1] * s; + pDFT_L[2 * i + 1] = pDFT_L[2 * i] * s + pDFT_L[2 * i + 1] * c; + pDFT_L[2 * i] = tmp; + } + } + else + { + for ( i = 1; i < hStereoDft->NFFT / 2; i++ ) + { + tmp = s * c1 + c * s1; + c = c * c1 - s * s1; + s = tmp; + + /*time shift of R*/ + tmp = pDFT_R[2 * i] * c + pDFT_R[2 * i + 1] * s; + pDFT_R[2 * i + 1] = -pDFT_R[2 * i] * s + pDFT_R[2 * i + 1] * c; + pDFT_R[2 * i] = tmp; + } + } + + if ( fabsf( hStereoDft->hItd->deltaItd[k_offset] * 32000.f / input_Fs ) > 80.0f ) + { + fac_att = min( 1.0f, max( 0.2f, 2.6f - 0.02f * fabsf( hStereoDft->hItd->deltaItd[1] ) * 32000.f / input_Fs ) ); + } + } + + /* compute remaining binwise energies for FB mode (ITD function only computes energies up to 16 kHz) */ + for ( i = STEREO_DFT_N_32k_ENC / 2; i < hStereoDft->NFFT / 2; i++ ) + { + bin_nrgL[i] = pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + bin_nrgR[i] = pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + } + } + + /* DFT stereo parameters */ + stereo_dft_enc_compute_prm( hStereoDft, pDFT_L, pDFT_R, k_offset, 1, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->vad_flag, bin_nrgL, bin_nrgR, dot_prod_nrg_ratio ); + + if ( vad_flag_dtx[0] == 0 ) + { + if ( hCPE->hStereoCng->cng_counter == 0 && !hCPE->hStereoCng->first_SID_after_TD ) + { + hStereoDft->sid_gipd = hStereoDft->prev_sid_gipd; + hStereoDft->no_ipd_flag = hStereoDft->prev_sid_no_ipd_flag; + } + + if ( hCPE->hStereoCng->cng_counter > ITD_SID_PREV_FRAMES ) + { + hStereoDft->prev_sid_gipd = hStereoDft->sid_gipd; + hStereoDft->prev_sid_no_ipd_flag = hStereoDft->no_ipd_flag; + } + } + + /*----------------------------------------------------------------* + * UNCLR classifier (detection of uncorrelated L and R channels) + *----------------------------------------------------------------*/ + + unclr_classifier_dft( hCPE ); + + /*------------------------------------------------------------------* + * Channel mapping: computation of DMX and RES + *-----------------------------------------------------------------*/ + + res_nrg_all_curr = EPSILON; + dmx_nrg_all_curr = EPSILON; + + pDFT_DMX = DFT_DMX; + pDFT_RES = DFT_RES; + pNrgL = bin_nrgL; + pNrgR = bin_nrgR; + + set_zero( pDFT_DMX, STEREO_DFT_N_MAX_ENC ); + set_zero( pDFT_RES, STEREO_DFT_N_8k_ENC ); + + pgIpd = hStereoDft->gipd + k_offset; + pSideGain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; + + if ( hStereoDft->hConfig->dmx_active ) + { + /*Active DMX*/ + alpha = 0; /* to avoid compilation warning */ + g = 1.f; + + /*Apply active DMX*/ + pDFT_DMX[0] = 0.f; + pDFT_RES[0] = 0.f; + for ( b = 0; b < hStereoDft->nbands_dmx; b++ ) + { + g = pSideGain[b]; + + if ( pgIpd[0] != 0.f ) + { + c = cosf( pgIpd[0] ); + s = sinf( pgIpd[0] ); + for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + { + /*rotate L*/ + tmp = pDFT_L[2 * i] * c + pDFT_L[2 * i + 1] * s; + pDFT_L[2 * i + 1] = pDFT_L[2 * i + 1] * c - pDFT_L[2 * i] * s; + pDFT_L[2 * i] = tmp; + } + } + + if ( b < hStereoDft->res_cod_band_max && vad_flag_dtx[0] ) + { + + /*Get the previous frame energy*/ + if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + /*Calculate the energy of RES and DMX*/ + /* 90% of old frame ... */ + dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.9f; + res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.9f; + } + hStereoDft->res_cod_NRG_M[b] = EPSILON; + hStereoDft->res_cod_NRG_S[b] = EPSILON; + + for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + { + pDFT_DMX[2 * i] = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * 0.5f; + pDFT_DMX[2 * i + 1] = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * 0.5f; + + pDFT_RES[2 * i] = ( pDFT_L[2 * i] - pDFT_R[2 * i] ) * 0.5f; + pDFT_RES[2 * i + 1] = ( pDFT_L[2 * i + 1] - pDFT_R[2 * i + 1] ) * 0.5f; + + /*Prediction of RES with DMX*/ + pDFT_RES[2 * i] = pDFT_RES[2 * i] - g * pDFT_DMX[2 * i]; + pDFT_RES[2 * i + 1] = pDFT_RES[2 * i + 1] - g * pDFT_DMX[2 * i + 1]; + + pDFT_RES[2 * i] *= fac_att; + pDFT_RES[2 * i + 1] *= fac_att; + + /*Energy of the DMX and RES*/ + hStereoDft->res_cod_NRG_M[b] += pDFT_DMX[2 * i] * pDFT_DMX[2 * i] + pDFT_DMX[2 * i + 1] * pDFT_DMX[2 * i + 1]; + hStereoDft->res_cod_NRG_S[b] += pDFT_RES[2 * i] * pDFT_RES[2 * i] + pDFT_RES[2 * i + 1] * pDFT_RES[2 * i + 1]; + } + + if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + /*Calculate the energy of RES and DMX*/ + /* ... + 10% of current frame. */ + dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.1f; + res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.1f; + } + } + else + { + int16_t upper_border; + int16_t triple_bin; + float frac_dot_prod; /* fraction of dot product according to energy ratio of current bins and whole band */ + float Sr, Si; + float comb_nrgL, comb_nrgR; + + upper_border = min( STEREO_DFT_DMX_CROSSOVER, hStereoDft->band_limits_dmx[b + 1] ); + + triple_bin = 0; + if ( upper_border > hStereoDft->band_limits_dmx[b] && ( upper_border - hStereoDft->band_limits_dmx[b] ) % 2 ) + { + /* if odd number of bins in band, combine last 3 bins */ + triple_bin = 1; + upper_border -= 3; + } + + for ( i = hStereoDft->band_limits_dmx[b]; i < upper_border; i += 2 ) + { + comb_nrgL = pNrgL[i] + pNrgL[i + 1]; + comb_nrgR = pNrgR[i] + pNrgR[i + 1]; + Sr = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * ( pDFT_L[2 * i] + pDFT_R[2 * i] ) + ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ) * ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ); + Si = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) + ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ) * ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ); + + sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + + wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + + /*DMX Mapping*/ + pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 2] = ( wL * pDFT_L[2 * i + 2] + wR * pDFT_R[2 * i + 2] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 3] = ( wL * pDFT_L[2 * i + 3] + wR * pDFT_R[2 * i + 3] ) * INV_SQRT_2; + } + + if ( triple_bin ) + { + comb_nrgL = comb_nrgR = 0.f; + Sr = Si = 0.f; + for ( j = i; j < i + 3; j++ ) + { + comb_nrgL += pNrgL[j]; + comb_nrgR += pNrgR[j]; + Sr += ( pDFT_L[2 * j] + pDFT_R[2 * j] ) * ( pDFT_L[2 * j] + pDFT_R[2 * j] ); + Si += ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ) * ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ); + } + + sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + + for ( j = i; j < i + 3; j++ ) + { + pDFT_DMX[2 * j] = ( wL * pDFT_L[2 * j] + wR * pDFT_R[2 * j] ) * INV_SQRT_2; + pDFT_DMX[2 * j + 1] = ( wL * pDFT_L[2 * j + 1] + wR * pDFT_R[2 * j + 1] ) * INV_SQRT_2; + } + i += 3; + } + + if ( i < hStereoDft->band_limits_dmx[b + 1] ) + { + sum_nrg_L2 = EPSILON; + sum_nrg_R2 = EPSILON; + dot_prod_real2 = EPSILON; + for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + { + sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + } + + sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + sum_abs = sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) + EPSILON; + wR = sqrtf( 0.5f * ( sum_nrg_L2 + sum_nrg_R2 ) + dot_prod_nrg_ratio[b] ) / sum_abs; + wL = wR + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs ); + } + + for ( ; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + { + /*DMX Mapping*/ + pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + } + } + } + + for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->NFFT / 2; i++ ) + { + pDFT_DMX[2 * i] = 0.f; + pDFT_DMX[2 * i + 1] = 0.f; + } + + /*Nyquist Freq.*/ + if ( hStereoDft->band_limits_dmx[b] >= hStereoDft->NFFT / 2 ) + { + pDFT_DMX[1] = ( pDFT_L[1] + pDFT_R[1] ) * 0.5f; + } + else + { + pDFT_DMX[1] = 0.f; + } + + /* DC component */ + pDFT_DMX[0] = ( pDFT_L[0] + pDFT_R[0] ) * 0.5f; + } + else + { + /*passive DMX*/ + assert( hStereoDft->nbands == hStereoDft->nbands_dmx && "Don't use coarser stereo parameter resolution for residual coding bitrates!" ); + for ( i = 0; i < hStereoDft->band_limits[hStereoDft->res_cod_band_max]; i++ ) + { + pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + pDFT_RES[i] = ( pDFT_L[i] - pDFT_R[i] ) * 0.5f; + } + for ( ; i < hStereoDft->NFFT; i++ ) + { + pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + } + } + + /*------------------------------------------------------------------* + * Recalculate RES and DMX + *-----------------------------------------------------------------*/ + + if ( hStereoDft->NFFT == STEREO_DFT_N_16k_ENC && hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + stereo_dft_enc_get_res_cod_mode_flag( hStereoDft, res_nrg_all_curr, dmx_nrg_all_curr, &res_dmx_ratio, &frame_nrg_ratio ); + + if ( hStereoDft->res_cod_sw_flag ) + { + int16_t res_cod_band_max; + + res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->hConfig->ada_wb_res_cod_mode]; + + /* Recalculate RES and DMX */ + for ( b = 0; b < res_cod_band_max; b++ ) + { + sum_nrg_L2 = EPSILON; + sum_nrg_R2 = EPSILON; + dot_prod_real2 = EPSILON; + for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + { + sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + } + + sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) * inv_sqrt( sum_nrg_L2 + EPSILON ); + wS = 1; + + if ( hStereoDft->res_cod_sw_flag ) + { + wL *= ( 1 - hStereoDft->switch_fade_factor ); + wS = hStereoDft->switch_fade_factor; + } + + for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + { + /*DMX Recalculation*/ + DFT_DMX[2 * i] += wL * pDFT_L[2 * i]; + DFT_DMX[2 * i + 1] += wL * pDFT_L[2 * i + 1]; + + /*RES Recalculation*/ + DFT_RES[2 * i] *= wS; + DFT_RES[2 * i + 1] *= wS; + } + } + } + } + + if ( input_Fs >= 32000 ) + { + stereo_dft_enc_calculate_nrg_for_icbwe( hStereoDft, DFT_DMX, input_Fs ); + } + + mvr2r( DFT_DMX, hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ); + mvr2r( DFT_RES, hStereoDft->DFT[1], STEREO_DFT_N_8k_ENC ); + set_zero( hStereoDft->DFT[1] + STEREO_DFT_N_8k_ENC, STEREO_DFT_N_MAX_ENC - STEREO_DFT_N_8k_ENC ); + + return; +} +#else +void stereo_dft_enc_process( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ + const int16_t vad_hover_flag[], /* i : VAD hangover flags */ + const int16_t input_frame /* i : input frame length */ +) +{ + int16_t i, j, b; + float *pDFT_L, *pDFT_R; +#ifdef IVAS_FLOAT_FIXED + Word32 *pDFT_L_fx, *pDFT_R_fx; +#endif + float *pDFT_DMX; + float *pDFT_RES; + int16_t k_offset; + float *pgIpd; + float *pSideGain; + float c, alpha, g; + float wL, wR, wS; + float tmp; + float s, c1, s1; + float fac_att; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + float DFT_DMX[STEREO_DFT_N_MAX_ENC]; + float DFT_RES[STEREO_DFT_N_8k_ENC]; + int32_t input_Fs; + float bin_nrgL[STEREO_DFT_N_MAX_ENC]; +#ifdef IVAS_FLOAT_FIXED + Word32 bin_nrgL_fx[STEREO_DFT_N_MAX_ENC]; + Word16 bin_nrgL_fx_e[STEREO_DFT_N_MAX_ENC]; +#endif + float bin_nrgR[STEREO_DFT_N_MAX_ENC]; +#ifdef IVAS_FLOAT_FIXED + Word32 bin_nrgR_fx[STEREO_DFT_N_MAX_ENC]; + Word16 bin_nrgR_fx_e[STEREO_DFT_N_MAX_ENC]; +#endif + float *pNrgL, *pNrgR; + float res_nrg_all_curr, dmx_nrg_all_curr; + float res_dmx_ratio, frame_nrg_ratio; + float dot_prod_nrg_ratio[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands */ + float sum_nrg_L2, sum_nrg_R2, dot_prod_real2; + float sum_nrg_Mid, sum_abs; + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + input_Fs = input_frame * FRAMES_PER_SEC; + + hStereoDft = hCPE->hStereoDft; + + wL = 0; /* avoid compilation warning */ + wR = 0; /* avoid compilation warning */ + + /* Initialization */ + k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ + + hStereoDft->gipd_band_max = dft_band_ipd[1][3]; + hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->res_cod_mode[k_offset]]; + hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * input_frame / (float) ( hStereoDft->NFFT ) ); + hStereoDft->res_cod_line_max = 8 * ( hStereoDft->res_cod_line_max / 8 ); + + hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + + + hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[0]; + hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[1]; + + /*------------------------------------------------------------------* + * Compute stereo parameters + *-----------------------------------------------------------------*/ + + /*ITD in Frequency domain*/ + fac_att = 1.0f; + + pDFT_L = hStereoDft->DFT[0]; + pDFT_R = hStereoDft->DFT[1]; +#ifdef IVAS_FLOAT_FIXED + pDFT_L_fx = hStereoDft->DFT_fx[0]; + pDFT_R_fx = hStereoDft->DFT_fx[1]; +#endif + { +#ifdef IVAS_FLOAT_FIXED + /*flt2fix*/ + hStereoDft->sfm_fx = floatToFixed( hStereoDft->sfm, 31 ); + f2me_buf( hStereoDft->xspec_smooth, hStereoDft->xspec_smooth_fx, &hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); + f2me_buf( hStereoDft->Spd_L_smooth, hStereoDft->Spd_L_smooth_fx, &hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + f2me_buf( hStereoDft->Spd_R_smooth, hStereoDft->Spd_R_smooth_fx, &hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + floatToFixed_arrL( hStereoDft->hItd->itd, hStereoDft->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hStereoDft->hItd->deltaItd, hStereoDft->hItd->deltaItd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_fv, hCPE->hStereoClassif->xtalk_fv_fx, 15, SSC_MAX_NFEA ); + floatToFixed_arrL( hCPE->hStereoClassif->unclr_fv, hCPE->hStereoClassif->unclr_fv_fx, 15, SSC_MAX_NFEA ); + f2me( hCPE->hStereoClassif->ave_ener_L, &hCPE->hStereoClassif->ave_ener_L_fx, &hCPE->hStereoClassif->ave_ener_L_fx_e ); + f2me( hCPE->hStereoClassif->ave_ener_R, &hCPE->hStereoClassif->ave_ener_R_fx, &hCPE->hStereoClassif->ave_ener_R_fx_e ); + hStereoDft->hItd->prev_m1_fx = floatToFixed( hStereoDft->hItd->prev_m1, 31 ); + hStereoDft->hItd->prev_m2_fx = floatToFixed( hStereoDft->hItd->prev_m2, 31 ); + f2me( hStereoDft->hItd->currFlatness, &hStereoDft->hItd->currFlatness_fx, &hStereoDft->hItd->currFlatness_fx_e ); + hCPE->hStereoClassif->xtalk_score_fx = floatToFixed( hCPE->hStereoClassif->xtalk_score, 31 ); + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_score_buf, hCPE->hStereoClassif->xtalk_score_buf_fx, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore_fx = floatToFixed( hCPE->hStereoClassif->xtalk_wscore, 31 ); + + stereo_dft_enc_compute_itd_fx( hCPE, pDFT_L_fx, hStereoDft->DFT_fx_e[0], pDFT_R_fx, hStereoDft->DFT_fx_e[1], k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL_fx, bin_nrgL_fx_e, bin_nrgR_fx, bin_nrgR_fx_e ); + + /*fix2flt*/ + hStereoDft->sfm = fixedToFloat( hStereoDft->sfm_fx, 31 ); + me2f_buf( hStereoDft->xspec_smooth_fx, hStereoDft->xspec_smooth_fx_e, hStereoDft->xspec_smooth, STEREO_DFT_N_32k_ENC ); + me2f_buf( hStereoDft->Spd_L_smooth_fx, hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_L_smooth, STEREO_DFT_N_32k_ENC / 2 ); + me2f_buf( hStereoDft->Spd_R_smooth_fx, hStereoDft->Spd_R_smooth_fx_e, hStereoDft->Spd_R_smooth, STEREO_DFT_N_32k_ENC / 2 ); + fixedToFloat_arrL( hStereoDft->hItd->itd_fx, hStereoDft->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hStereoDft->hItd->deltaItd_fx, hStereoDft->hItd->deltaItd, 16, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, 15, SSC_MAX_NFEA ); + fixedToFloat_arrL( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, 15, SSC_MAX_NFEA ); + hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); + hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); + hStereoDft->hItd->prev_m1 = fixedToFloat( hStereoDft->hItd->prev_m1_fx, 31 ); + hStereoDft->hItd->prev_m2 = fixedToFloat( hStereoDft->hItd->prev_m2_fx, 31 ); + hCPE->hStereoClassif->xtalk_score = fixedToFloat( hCPE->hStereoClassif->xtalk_score_fx, 31 ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_score_buf_fx, hCPE->hStereoClassif->xtalk_score_buf, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore = fixedToFloat( hCPE->hStereoClassif->xtalk_wscore_fx, 31 ); + + /*local fix2flt*/ + for ( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + bin_nrgL[i] = me2f( bin_nrgL_fx[i], bin_nrgL_fx_e[i] ); + bin_nrgR[i] = me2f( bin_nrgR_fx[i], bin_nrgR_fx_e[i] ); + } + +#else + stereo_dft_enc_compute_itd( hCPE, pDFT_L, pDFT_R, k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL, bin_nrgR ); +#endif + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + return; + } + + if ( hStereoDft->hItd->deltaItd[k_offset] != 0 && hStereoDft->hConfig->dmx_active ) + { + /*time shift channels*/ + alpha = -2.0f * EVS_PI * hStereoDft->hItd->deltaItd[k_offset] / hStereoDft->NFFT; + c = 1.f; /*cos(0)*/ + s = 0.f; /*sin(0)*/ + c1 = cosf( alpha ); + s1 = sinf( alpha ); + + if ( alpha >= 0 ) + { + for ( i = 1; i < hStereoDft->NFFT / 2; i++ ) + { + tmp = s * c1 + c * s1; + c = c * c1 - s * s1; + s = tmp; + + /*time shift of L*/ + tmp = pDFT_L[2 * i] * c - pDFT_L[2 * i + 1] * s; + pDFT_L[2 * i + 1] = pDFT_L[2 * i] * s + pDFT_L[2 * i + 1] * c; + pDFT_L[2 * i] = tmp; + } + } + else + { + for ( i = 1; i < hStereoDft->NFFT / 2; i++ ) + { + tmp = s * c1 + c * s1; + c = c * c1 - s * s1; + s = tmp; + + /*time shift of R*/ + tmp = pDFT_R[2 * i] * c + pDFT_R[2 * i + 1] * s; + pDFT_R[2 * i + 1] = -pDFT_R[2 * i] * s + pDFT_R[2 * i + 1] * c; + pDFT_R[2 * i] = tmp; + } + } + + if ( fabsf( hStereoDft->hItd->deltaItd[k_offset] * 32000.f / input_Fs ) > 80.0f ) + { + fac_att = min( 1.0f, max( 0.2f, 2.6f - 0.02f * fabsf( hStereoDft->hItd->deltaItd[1] ) * 32000.f / input_Fs ) ); + } + } + + /* compute remaining binwise energies for FB mode (ITD function only computes energies up to 16 kHz) */ + for ( i = STEREO_DFT_N_32k_ENC / 2; i < hStereoDft->NFFT / 2; i++ ) + { + bin_nrgL[i] = pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + bin_nrgR[i] = pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + } + } + + /* DFT stereo parameters */ + stereo_dft_enc_compute_prm( hStereoDft, pDFT_L, pDFT_R, k_offset, 1, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->vad_flag, bin_nrgL, bin_nrgR, dot_prod_nrg_ratio ); + + if ( vad_flag_dtx[0] == 0 ) + { + if ( hCPE->hStereoCng->cng_counter == 0 && !hCPE->hStereoCng->first_SID_after_TD ) + { + hStereoDft->sid_gipd = hStereoDft->prev_sid_gipd; + hStereoDft->no_ipd_flag = hStereoDft->prev_sid_no_ipd_flag; + } + + if ( hCPE->hStereoCng->cng_counter > ITD_SID_PREV_FRAMES ) + { + hStereoDft->prev_sid_gipd = hStereoDft->sid_gipd; + hStereoDft->prev_sid_no_ipd_flag = hStereoDft->no_ipd_flag; + } + } + + /*----------------------------------------------------------------* + * UNCLR classifier (detection of uncorrelated L and R channels) + *----------------------------------------------------------------*/ + + unclr_classifier_dft( hCPE ); + + /*------------------------------------------------------------------* + * Channel mapping: computation of DMX and RES + *-----------------------------------------------------------------*/ + + res_nrg_all_curr = EPSILON; + dmx_nrg_all_curr = EPSILON; + + pDFT_DMX = DFT_DMX; + pDFT_RES = DFT_RES; + pNrgL = bin_nrgL; + pNrgR = bin_nrgR; + + set_zero( pDFT_DMX, STEREO_DFT_N_MAX_ENC ); + set_zero( pDFT_RES, STEREO_DFT_N_8k_ENC ); + + pgIpd = hStereoDft->gipd + k_offset; + pSideGain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; + + if ( hStereoDft->hConfig->dmx_active ) + { + /*Active DMX*/ + alpha = 0; /* to avoid compilation warning */ + g = 1.f; + + /*Apply active DMX*/ + pDFT_DMX[0] = 0.f; + pDFT_RES[0] = 0.f; + for ( b = 0; b < hStereoDft->nbands_dmx; b++ ) + { + g = pSideGain[b]; + + if ( pgIpd[0] != 0.f ) + { + c = cosf( pgIpd[0] ); + s = sinf( pgIpd[0] ); + for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + { + /*rotate L*/ + tmp = pDFT_L[2 * i] * c + pDFT_L[2 * i + 1] * s; + pDFT_L[2 * i + 1] = pDFT_L[2 * i + 1] * c - pDFT_L[2 * i] * s; + pDFT_L[2 * i] = tmp; + } + } + + if ( b < hStereoDft->res_cod_band_max && vad_flag_dtx[0] ) + { + + /*Get the previous frame energy*/ + if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + /*Calculate the energy of RES and DMX*/ + /* 90% of old frame ... */ + dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.9f; + res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.9f; + } + hStereoDft->res_cod_NRG_M[b] = EPSILON; + hStereoDft->res_cod_NRG_S[b] = EPSILON; + + for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + { + pDFT_DMX[2 * i] = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * 0.5f; + pDFT_DMX[2 * i + 1] = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * 0.5f; + + pDFT_RES[2 * i] = ( pDFT_L[2 * i] - pDFT_R[2 * i] ) * 0.5f; + pDFT_RES[2 * i + 1] = ( pDFT_L[2 * i + 1] - pDFT_R[2 * i + 1] ) * 0.5f; + + /*Prediction of RES with DMX*/ + pDFT_RES[2 * i] = pDFT_RES[2 * i] - g * pDFT_DMX[2 * i]; + pDFT_RES[2 * i + 1] = pDFT_RES[2 * i + 1] - g * pDFT_DMX[2 * i + 1]; + + pDFT_RES[2 * i] *= fac_att; + pDFT_RES[2 * i + 1] *= fac_att; + + /*Energy of the DMX and RES*/ + hStereoDft->res_cod_NRG_M[b] += pDFT_DMX[2 * i] * pDFT_DMX[2 * i] + pDFT_DMX[2 * i + 1] * pDFT_DMX[2 * i + 1]; + hStereoDft->res_cod_NRG_S[b] += pDFT_RES[2 * i] * pDFT_RES[2 * i] + pDFT_RES[2 * i + 1] * pDFT_RES[2 * i + 1]; + } + + if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + /*Calculate the energy of RES and DMX*/ + /* ... + 10% of current frame. */ + dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.1f; + res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.1f; + } + } + else + { + int16_t upper_border; + int16_t triple_bin; + float frac_dot_prod; /* fraction of dot product according to energy ratio of current bins and whole band */ + float Sr, Si; + float comb_nrgL, comb_nrgR; + + upper_border = min( STEREO_DFT_DMX_CROSSOVER, hStereoDft->band_limits_dmx[b + 1] ); + + triple_bin = 0; + if ( upper_border > hStereoDft->band_limits_dmx[b] && ( upper_border - hStereoDft->band_limits_dmx[b] ) % 2 ) + { + /* if odd number of bins in band, combine last 3 bins */ + triple_bin = 1; + upper_border -= 3; + } + + for ( i = hStereoDft->band_limits_dmx[b]; i < upper_border; i += 2 ) + { + comb_nrgL = pNrgL[i] + pNrgL[i + 1]; + comb_nrgR = pNrgR[i] + pNrgR[i + 1]; + Sr = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * ( pDFT_L[2 * i] + pDFT_R[2 * i] ) + ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ) * ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ); + Si = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) + ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ) * ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ); + + sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + + wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + + /*DMX Mapping*/ + pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 2] = ( wL * pDFT_L[2 * i + 2] + wR * pDFT_R[2 * i + 2] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 3] = ( wL * pDFT_L[2 * i + 3] + wR * pDFT_R[2 * i + 3] ) * INV_SQRT_2; + } + + if ( triple_bin ) + { + comb_nrgL = comb_nrgR = 0.f; + Sr = Si = 0.f; + for ( j = i; j < i + 3; j++ ) + { + comb_nrgL += pNrgL[j]; + comb_nrgR += pNrgR[j]; + Sr += ( pDFT_L[2 * j] + pDFT_R[2 * j] ) * ( pDFT_L[2 * j] + pDFT_R[2 * j] ); + Si += ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ) * ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ); + } + + sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + + for ( j = i; j < i + 3; j++ ) + { + pDFT_DMX[2 * j] = ( wL * pDFT_L[2 * j] + wR * pDFT_R[2 * j] ) * INV_SQRT_2; + pDFT_DMX[2 * j + 1] = ( wL * pDFT_L[2 * j + 1] + wR * pDFT_R[2 * j + 1] ) * INV_SQRT_2; + } + i += 3; + } + + if ( i < hStereoDft->band_limits_dmx[b + 1] ) + { + sum_nrg_L2 = EPSILON; + sum_nrg_R2 = EPSILON; + dot_prod_real2 = EPSILON; + for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + { + sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + } + + sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + sum_abs = sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) + EPSILON; + wR = sqrtf( 0.5f * ( sum_nrg_L2 + sum_nrg_R2 ) + dot_prod_nrg_ratio[b] ) / sum_abs; + wL = wR + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs ); + } + + for ( ; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + { + /*DMX Mapping*/ + pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + } + } + } + + for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->NFFT / 2; i++ ) + { + pDFT_DMX[2 * i] = 0.f; + pDFT_DMX[2 * i + 1] = 0.f; + } + + /*Nyquist Freq.*/ + if ( hStereoDft->band_limits_dmx[b] >= hStereoDft->NFFT / 2 ) + { + pDFT_DMX[1] = ( pDFT_L[1] + pDFT_R[1] ) * 0.5f; + } + else + { + pDFT_DMX[1] = 0.f; + } + + /* DC component */ + pDFT_DMX[0] = ( pDFT_L[0] + pDFT_R[0] ) * 0.5f; + } + else + { + /*passive DMX*/ + assert( hStereoDft->nbands == hStereoDft->nbands_dmx && "Don't use coarser stereo parameter resolution for residual coding bitrates!" ); + for ( i = 0; i < hStereoDft->band_limits[hStereoDft->res_cod_band_max]; i++ ) + { + pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + pDFT_RES[i] = ( pDFT_L[i] - pDFT_R[i] ) * 0.5f; + } + for ( ; i < hStereoDft->NFFT; i++ ) + { + pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + } + } + + /*------------------------------------------------------------------* + * Recalculate RES and DMX + *-----------------------------------------------------------------*/ + + if ( hStereoDft->NFFT == STEREO_DFT_N_16k_ENC && hStereoDft->hConfig->ada_wb_res_cod_mode ) + { + stereo_dft_enc_get_res_cod_mode_flag( hStereoDft, res_nrg_all_curr, dmx_nrg_all_curr, &res_dmx_ratio, &frame_nrg_ratio ); + + if ( hStereoDft->res_cod_sw_flag ) + { + int16_t res_cod_band_max; + + res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->hConfig->ada_wb_res_cod_mode]; + + /* Recalculate RES and DMX */ + for ( b = 0; b < res_cod_band_max; b++ ) + { + sum_nrg_L2 = EPSILON; + sum_nrg_R2 = EPSILON; + dot_prod_real2 = EPSILON; + for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + { + sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + } + + sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) * inv_sqrt( sum_nrg_L2 + EPSILON ); + wS = 1; + + if ( hStereoDft->res_cod_sw_flag ) + { + wL *= ( 1 - hStereoDft->switch_fade_factor ); + wS = hStereoDft->switch_fade_factor; + } + + for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + { + /*DMX Recalculation*/ + DFT_DMX[2 * i] += wL * pDFT_L[2 * i]; + DFT_DMX[2 * i + 1] += wL * pDFT_L[2 * i + 1]; + + /*RES Recalculation*/ + DFT_RES[2 * i] *= wS; + DFT_RES[2 * i + 1] *= wS; + } + } + } + } + + if ( input_Fs >= 32000 ) + { + stereo_dft_enc_calculate_nrg_for_icbwe( hStereoDft, DFT_DMX, input_Fs ); + } + + mvr2r( DFT_DMX, hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ); + mvr2r( DFT_RES, hStereoDft->DFT[1], STEREO_DFT_N_8k_ENC ); + set_zero( hStereoDft->DFT[1] + STEREO_DFT_N_8k_ENC, STEREO_DFT_N_MAX_ENC - STEREO_DFT_N_8k_ENC ); + + return; +} +#endif +#else +void stereo_dft_enc_process( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ + const int16_t vad_hover_flag[], /* i : VAD hangover flags */ + const int16_t input_frame /* i : input frame length */ +) +{ + int16_t i, j, b; + float *pDFT_L, *pDFT_R; + float *pDFT_DMX; + float *pDFT_RES; + int16_t k_offset; + float *pgIpd; + float *pSideGain; + float c, alpha, g; + float wL, wR, wS; + float tmp; + float s, c1, s1; + float fac_att; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + float DFT_DMX[STEREO_DFT_N_MAX_ENC]; + float DFT_RES[STEREO_DFT_N_8k_ENC]; + int32_t input_Fs; + float bin_nrgL[STEREO_DFT_N_MAX_ENC]; + float bin_nrgR[STEREO_DFT_N_MAX_ENC]; + float *pNrgL, *pNrgR; + float res_nrg_all_curr, dmx_nrg_all_curr; float res_dmx_ratio, frame_nrg_ratio; float dot_prod_nrg_ratio[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands */ float sum_nrg_L2, sum_nrg_R2, dot_prod_real2; @@ -2292,8 +3533,7 @@ void stereo_dft_enc_process( return; } - - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_get_res_cod_mode_flag() * @@ -2451,7 +3691,6 @@ static void stereo_dft_enc_get_res_cod_mode_flag( return; } - /*------------------------------------------------------------------------- * stereo_dft_enc_res() * diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index e01e9b5ba383c9dd6933f956335de55aee8ff25f..1c429867971ff2901ae24c222c5f2100e4c944ab 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -38,6 +38,7 @@ #include "rom_enc.h" #include "rom_com.h" #include "prot.h" +#include "prot_fx.h" #include "ivas_prot.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" @@ -49,35 +50,48 @@ * Local constants *------------------------------------------------------------------------*/ -#define LP_GCC_PHAT_UP 0.9f /* LP filter coefficient, going up */ -#define LP_GCC_PHAT_DOWN 0.1f /* LP filter coefficient, going down */ -#define ITD_CNT_MAX 2 /* Minimum number of consecutive ITD estimates for ITD hangover */ -#define ITD_HO_GCC_PHAT_MAX 0.6f /* LP GCC PHAT value which gives zero hangover */ -#define ITD_HO_GCC_PHAT_MIN 0.3f /* LP GCC PHAT value which gives ITD_HO_MAX ITD hangover frames */ -#define ITD_HO_MAX 6 /* Maximum number of ITD hangover frames */ -#define ITD_HO_GCC_PHAT_INCL ( -( ITD_HO_MAX - 1 ) / ( ITD_HO_GCC_PHAT_MAX - ITD_HO_GCC_PHAT_MIN ) ) -#define ITD_HO_GCC_PHAT_OFFS ( -ITD_HO_GCC_PHAT_INCL * ITD_HO_GCC_PHAT_MAX + 1 ) -#define SFM_PROD_GRP 4 /*maximum grouping of products for calculating SFM in ITD estimation*/ -#define B_DENOM 0.083333333333333f -#define L_SAMPLES 20 -#define SUBDIV ( 2 * STEREO_DFT_ITD_MAX_ANA / L_SAMPLES ) -#define DENOM 0.05f +#define LP_GCC_PHAT_UP 0.9f /* LP filter coefficient, going up */ +#define LP_GCC_PHAT_UP_Q31 1932735283 /* LP filter coefficient, going up */ +#define LP_GCC_PHAT_DOWN 0.1f /* LP filter coefficient, going down */ +#define LP_GCC_PHAT_DOWN_Q31 214748365 /* LP filter coefficient, going down */ +#define ITD_CNT_MAX 2 /* Minimum number of consecutive ITD estimates for ITD hangover */ +#define ITD_HO_GCC_PHAT_MAX 0.6f /* LP GCC PHAT value which gives zero hangover */ +#define ITD_HO_GCC_PHAT_MIN 0.3f /* LP GCC PHAT value which gives ITD_HO_MAX ITD hangover frames */ +#define ITD_HO_MAX 6 /* Maximum number of ITD hangover frames */ +#define ITD_HO_GCC_PHAT_INCL ( -( ITD_HO_MAX - 1 ) / ( ITD_HO_GCC_PHAT_MAX - ITD_HO_GCC_PHAT_MIN ) ) +#define ITD_HO_GCC_PHAT_INCL_Q26 -1118481021 +#define ITD_HO_GCC_PHAT_OFFS ( -ITD_HO_GCC_PHAT_INCL * ITD_HO_GCC_PHAT_MAX + 1 ) +#define ITD_HO_GCC_PHAT_OFFS_Q26 738197504 +#define SFM_PROD_GRP 4 /*maximum grouping of products for calculating SFM in ITD estimation*/ +#define B_DENOM 0.083333333333333f +#define B_DENOM_Q31 178956971 +#define L_SAMPLES 20 +#define SUBDIV ( 2 * STEREO_DFT_ITD_MAX_ANA / L_SAMPLES ) +#define DENOM 0.05f +#define DENOM_Q31 107374182 #define XSPEC_ALPHA ( 1.f / 32 ) +#define XSPEC_ALPHA_Q31 ONE_IN_Q26 #define CORR_FILT 0.8f +#define CORR_FILT_Q31 1717986918 #define CORR_RESET_FRAMES_MAX 20 -#define ITD_VAD_NOISE_INIT_FRAMES 30 -#define ITD_VAD_THRSHOLD 0.001f -#define ITD_VAD_MS_SNR_UPDATE_THRESH 15.0f -#define HIGHT_SNR_VOICE_TH 10000.0f -#define MAX_ITD_VAD_HANGOVER 10 +#define ITD_VAD_NOISE_INIT_FRAMES 30 +#define ITD_VAD_THRSHOLD 0.001f +#define ITD_VAD_THRSHOLD_Q31 2147484 +#define ITD_VAD_MS_SNR_UPDATE_THRESH 15.0f +#define ITD_VAD_MS_SNR_UPDATE_THRESH_FX 15 +#define HIGHT_SNR_VOICE_TH 10000.0f +#define HIGHT_SNR_VOICE_TH_FX 10000 +#define MAX_ITD_VAD_HANGOVER 10 -#define XCORR_LB_NUM_BANDS 3 -#define XCORR_LB_BAND_WIDTH 8 +#define XCORR_LB_NUM_BANDS 3 +#define ONE_BY_XCORR_LB_NUM_BANDS_Q31 715827883 +#define XCORR_LB_BAND_WIDTH 8 #define ITD_MAX_MDCT 80 +#define LOG_E_2 1488522236 /*------------------------------------------------------------------------- * set_band_limits() @@ -85,6 +99,29 @@ * configure bands as used in DFT Stereo *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void set_band_limits_fx( + Word16 *nbands, + Word16 band_limits[STEREO_DFT_BAND_MAX + 1], + Word16 NFFT ) +{ + band_limits[0] = 1; + move16(); + *nbands = 0; + move16(); + WHILE( LT_16( band_limits[( *nbands )++], shr( NFFT, 1 ) ) ) + { + band_limits[*nbands] = extract_l( Mpy_32_32_r( shl( dft_band_limits_erb4[*nbands], 1 ), 1717986918 /*( (float) ( STEREO_DFT_N_NS_ENC ) / STEREO_DFT_N_NS ) in Q 30*/ ) ); + move16(); + } + ( *nbands ) = sub( *nbands, 1 ); + move16(); + band_limits[*nbands] = shr( NFFT, 1 ); /*Nyquist Freq*/ + move16(); + + return; +} +#endif static void set_band_limits( int16_t *nbands, int16_t band_limits[STEREO_DFT_BAND_MAX + 1], @@ -141,6 +178,41 @@ void stereo_dft_hybrid_ITD_flag( * Quantize the ITD *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void stereo_dft_quantize_itd_fx( + const Word16 in, + Word32 *out, + const Word32 input_Fs, + Word16 *ind ) +{ + Word16 itd; + + // itd = (int16_t) ( sign( in ) * 0.5f + in ); + itd = in; + move16(); + + /*Limit ITD*/ + // if ( ( ABSVAL( itd ) > STEREO_DFT_ITD_MAX ) || ( ABSVAL( itd ) < STEREO_DFT_ITD_MIN ) ) + test(); + IF( GT_16( abs_s( itd ), STEREO_DFT_ITD_MAX ) || LT_16( abs_s( itd ), STEREO_DFT_ITD_MIN ) ) + { + itd = 0; + move16(); + } + ELSE + { + *ind = sub( add( shl( ( itd < 0 ), ( STEREO_DFT_ITD_NBITS - 1 ) ), abs_s( itd ) ), STEREO_DFT_ITD_MIN ); + move16(); + } + + /*Convert back @ fs*/ + //*out = (float) ( itd * input_Fs ) / ( (float) ( STEREO_DFT_ITD_FS ) ); + *out = Mpy_32_32( L_shl( itd * input_Fs, 2 ), 1099511628 /*Q45*/ ); // Q45+Q2-Q31 = Q16 + move32(); + + return; +} +#endif static void stereo_dft_quantize_itd( const int16_t in, float *out, @@ -174,6 +246,81 @@ static void stereo_dft_quantize_itd( * *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word32 itd_vad_ms_snr_calc_fx( + Word32 E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], // Q0 + Word32 *Spd, + Word16 *Spd_e, + Word32 *E_band, + Word16 *E_band_e, + Word16 *ms_snr_e ) +{ + Word32 snr[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word16 snr_e[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word32 msnr[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word16 msnr_e[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word32 ms_snr; + Word16 i, j; + Word16 exp; + + FOR( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + E_band[i] = 0; + move32(); + E_band_e[i] = 0; + move16(); + for ( j = itd_vad_band_tbl[i]; j < itd_vad_band_tbl[i + 1]; j++ ) + { + // E_band[i] += Spd[j]; + E_band[i] = BASOP_Util_Add_Mant32Exp( E_band[i], E_band_e[i], Spd[j], Spd_e[j], &E_band_e[i] ); + move32(); + } + // E_band[i] = E_band[i] / ( itd_vad_band_tbl[i + 1] - itd_vad_band_tbl[i] ); + E_band[i] = BASOP_Util_Divide3232_Scale_cadence( E_band[i], L_sub( itd_vad_band_tbl[i + 1], itd_vad_band_tbl[i] ), &exp ); + move32(); + E_band_e[i] = add( exp, sub( E_band_e[i], 31 ) ); + move16(); + } + + ms_snr = 0; + move32(); + *ms_snr_e = 0; + move16(); + FOR( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + // snr[i] = E_band[i] / E_band_n[i]; + snr[i] = BASOP_Util_Divide3232_Scale_cadence( E_band[i], E_band_n[i], &snr_e[i] ); + move32(); + snr_e[i] = add( snr_e[i], sub( E_band_e[i], 31 ) ); + move16(); + // if ( snr[i] < 1 ) + IF( BASOP_Util_Cmp_Mant32Exp( snr[i], snr_e[i], 1, 31 ) < 0 ) + { + // snr[i] = 1; + snr[i] = MAX_32; + move32(); + snr_e[i] = 0; + move16(); + } + // msnr[i] = snr[i] - 1.0f; + msnr[i] = BASOP_Util_Add_Mant32Exp( snr[i], snr_e[i], MIN_32, 0, &msnr_e[i] ); + move32(); + // if ( msnr[i] < 6 ) + IF( BASOP_Util_Cmp_Mant32Exp( msnr[i], msnr_e[i], 6, 31 ) < 0 ) + { + // msnr[i] = powf( msnr[i], 2 ) / 6.0f; + msnr[i] = Mpy_32_32( Mpy_32_32( msnr[i], msnr[i] ), 357913941 ); + move32(); + msnr_e[i] = shl( msnr_e[i], 1 ); + move16(); + } + // ms_snr += msnr[i]; + ms_snr = BASOP_Util_Add_Mant32Exp( ms_snr, *ms_snr_e, msnr[i], msnr_e[i], ms_snr_e ); + } + + return ( ms_snr ); +} +#endif static float itd_vad_ms_snr_calc( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], float *Spd, @@ -219,7 +366,105 @@ static float itd_vad_ms_snr_calc( * * *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void itd_vad_background_update_fx( + Word32 E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], // Q0 + Word16 *vad_frm_cnt, + const Word32 ms_snr, + const Word16 ms_snr_e, + Word32 *E_band, + Word16 *E_band_e ) +{ + Word16 i; + Word32 energy; + Word16 energy_e; + + Word32 L_temp; + Word16 L_temp_e; + + Word16 E_band_n_e_tmp; + + energy = 0; + move32(); + energy_e = 0; + move16(); + FOR( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + // energy += E_band[i] / (float) STEREO_DFT_ITD_VAD_BAND_NUM; + energy = BASOP_Util_Add_Mant32Exp( energy, energy_e, Mpy_32_32( E_band[i], 107374182 ), E_band_e[i], &energy_e ) /*/ (float) STEREO_DFT_ITD_VAD_BAND_NUM*/; + } + + IF( LT_16( *vad_frm_cnt, ITD_VAD_NOISE_INIT_FRAMES ) ) + { + ( *vad_frm_cnt ) = add( *vad_frm_cnt, 1 ); + move16(); + } + + test(); + IF( LT_16( *vad_frm_cnt, ITD_VAD_NOISE_INIT_FRAMES ) && ( BASOP_Util_Cmp_Mant32Exp( energy, energy_e, 40000000, 31 ) < 0 ) ) + { + FOR( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + /* using the init values as frame (-1) values */ + // E_band_n[i] = ( E_band_n[i] * ( (float) ( *vad_frm_cnt ) ) + E_band[i] ) / ( (float) ( *vad_frm_cnt + 1 ) ); + Word16 q_temp = norm_l( *vad_frm_cnt ); + L_temp = L_shl( *vad_frm_cnt, q_temp ); + L_temp_e = sub( 31, q_temp ); + L_temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( E_band_n[i], L_temp ), add( 31, L_temp_e ), E_band[i], E_band_e[i], &L_temp_e ); + E_band_n[i] = BASOP_Util_Divide3232_Scale_cadence( L_temp, L_add( *vad_frm_cnt, 1 ), &E_band_n_e_tmp ); + move32(); + E_band_n_e_tmp = add( E_band_n_e_tmp, sub( L_temp_e, 31 ) ); + E_band_n[i] = L_shr_r( E_band_n[i], sub( 31, E_band_n_e_tmp ) ); // Q31 + move16(); + } + /*Word16 max_exp = E_band_n_e_tmp[0]; + for ( i = 1; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + max_exp = s_max( max_exp, E_band_n_e_tmp[i] ); + } + *E_band_n_e = max_exp; + for ( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + E_band_n[i] = L_shr_r( E_band_n[i], sub( *E_band_n_e, E_band_n_e_tmp[i] ) ); + }*/ + } + ELSE + { + // if ( ms_snr < ITD_VAD_MS_SNR_UPDATE_THRESH ) + IF( BASOP_Util_Cmp_Mant32Exp( ms_snr, ms_snr_e, ITD_VAD_MS_SNR_UPDATE_THRESH_FX, 31 ) < 0 ) + { + FOR( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + // E_band_n[i] = 0.96f * E_band_n[i] + 0.04f * E_band[i]; + E_band_n[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( 2061584302, E_band_n[i] ), 31, Mpy_32_32( 85899346, E_band[i] ), E_band_e[i], &E_band_n_e_tmp ); + move32(); + // if ( E_band_n[i] < 1.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( E_band_n[i], E_band_n_e_tmp, MAX_32, 0 ) < 0 ) + { + E_band_n[i] = MAX_32; + move32(); + E_band_n_e_tmp = 0; + move16(); + } + E_band_n[i] = L_shr_r( E_band_n[i], sub( 31, E_band_n_e_tmp ) ); // Q31 + move32(); + } + /*Word16 max_exp = E_band_n_e_tmp[0]; + for ( i = 1; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + max_exp = s_max( max_exp, E_band_n_e_tmp[i] ); + } + *E_band_n_e = max_exp; + for ( i = 0; i < STEREO_DFT_ITD_VAD_BAND_NUM; i++ ) + { + E_band_n[i] = L_shr_r( E_band_n[i], sub( *E_band_n_e, E_band_n_e_tmp[i] ) ); + }*/ + } + } + return; +} +#endif static void itd_vad_background_update( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], int16_t *vad_frm_cnt, @@ -272,6 +517,54 @@ static void itd_vad_background_update( * *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 stereo_dft_enc_itd_vad_fx( + Word32 E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], // Q0 + Word16 *vad_frm_cnt, + Word32 *Spd_L, + Word16 *Spd_L_e, + Word32 *Spd_R, + Word16 *Spd_R_e, + Word32 *mssnr, + Word16 *mssnr_e ) +{ + Word16 i; + Word32 E_band[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word16 E_band_e[STEREO_DFT_ITD_VAD_BAND_NUM]; + Word16 vad_flag_itd; + + Word32 Spd[STEREO_DFT_N_16k_ENC / 2 + 1]; + Word16 Spd_e[STEREO_DFT_N_16k_ENC / 2 + 1]; + + FOR( i = 0; i <= STEREO_DFT_N_16k_ENC / 2; i++ ) + { + // Spd[i] = 0.5f * ( Spd_L[i] + Spd_R[i] ); + Spd[i] = BASOP_Util_Add_Mant32Exp( Spd_L[i], Spd_L_e[i], Spd_R[i], Spd_R_e[i], &Spd_e[i] ); + move32(); + Spd_e[i] = sub( Spd_e[i], 1 ); + move16(); + } + + *mssnr = itd_vad_ms_snr_calc_fx( E_band_n, Spd, Spd_e, E_band, E_band_e, mssnr_e ); + move32(); + + itd_vad_background_update_fx( E_band_n, vad_frm_cnt, *mssnr, *mssnr_e, E_band, E_band_e ); + + // if ( *mssnr < ITD_VAD_THRSHOLD ) + IF( BASOP_Util_Cmp_Mant32Exp( *mssnr, *mssnr_e, ITD_VAD_THRSHOLD_Q31, 0 ) < 0 ) + { + vad_flag_itd = 0; + move16(); + } + ELSE + { + vad_flag_itd = 1; + move16(); + } + + return ( vad_flag_itd ); +} +#endif static int16_t stereo_dft_enc_itd_vad( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], int16_t *vad_frm_cnt, @@ -313,6 +606,179 @@ static int16_t stereo_dft_enc_itd_vad( * calculates mean energy of main-to-background signal ratio *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word32 calc_mean_E_ratio_fx( + ITD_DATA_HANDLE hItd, + Word16 nbands, + Word16 band_limits[], + const Word32 sfm, + const Word32 nrg_L[STEREO_DFT_N_32k_ENC / 2], + const Word16 nrg_L_e[STEREO_DFT_N_32k_ENC / 2], + const Word32 nrg_R[STEREO_DFT_N_32k_ENC / 2], + const Word16 nrg_R_e[STEREO_DFT_N_32k_ENC / 2], + Word32 *total_mEr, + Word16 *total_mEr_e, + Word16 *sum_Er_e ) +{ + Word32 sum_xcorr[2]; + Word16 sum_xcorr_e[2]; + Word32 Sxcorr; + Word16 Sxcorr_e; + Word32 Er[STEREO_DFT_BAND_MAX], fi[STEREO_DFT_BAND_MAX], a, acorr; + Word16 Er_e[STEREO_DFT_BAND_MAX], fi_e[STEREO_DFT_BAND_MAX], a_e, acorr_e; + Word32 sum_nrg_L, sum_nrg_R; + Word16 sum_nrg_L_e, sum_nrg_R_e; + Word16 b, i; + Word32 sum_Er; + Word32 total_fi; + Word16 total_fi_e; + Word32 grand_nrg_L, grand_nrg_R, grand_sum_xcorr_real, grand_sum_xcorr_img; + Word16 grand_nrg_L_e, grand_nrg_R_e, grand_sum_xcorr_real_e, grand_sum_xcorr_img_e; + + Word32 L_temp1, L_temp2; + Word16 L_temp1_e, L_temp2_e; + + Word16 acorr_L_fx_tmp_e[STEREO_DFT_BAND_MAX]; + set16_fx( acorr_L_fx_tmp_e, hItd->acorr_L_fx_e, nbands ); + Word16 acorr_R_fx_tmp_e[STEREO_DFT_BAND_MAX]; + set16_fx( acorr_R_fx_tmp_e, hItd->acorr_R_fx_e, nbands ); + + grand_nrg_L = 0; + move32(); + grand_nrg_L_e = 0; + move16(); + grand_nrg_R = 0; + move32(); + grand_nrg_R_e = 0; + move16(); + grand_sum_xcorr_real = 0; + move32(); + grand_sum_xcorr_real_e = 0; + move16(); + grand_sum_xcorr_img = 0; + move32(); + grand_sum_xcorr_img_e = 0; + move16(); + + /*take bands up to 32kHz bandwidth as ITD is always calculated at 32kHz sampling rate*/ + nbands -= ( band_limits[nbands] > STEREO_DFT_N_32k_ENC / 2 ); + + sum_Er = 0; + move32(); + *sum_Er_e = 0; + move16(); + FOR( b = 0; b < nbands; b++ ) + { + /*reset buffers*/ + sum_xcorr[0] = 0; + move32(); + sum_xcorr_e[0] = 0; + move16(); + sum_xcorr[1] = 0; + move32(); + sum_xcorr_e[1] = 0; + move16(); + sum_nrg_L = 0; + move32(); + sum_nrg_L_e = 0; + move16(); + sum_nrg_R = 0; + move32(); + sum_nrg_R_e = 0; + move16(); + + FOR( i = band_limits[b]; i < min( band_limits[b + 1], STEREO_DFT_N_32k_ENC / 2 ); i++ ) + { + // sum_xcorr[0] += hItd->xcorr_smooth[2 * i]; + sum_xcorr[0] = BASOP_Util_Add_Mant32Exp( sum_xcorr[0], sum_xcorr_e[0], hItd->xcorr_smooth_fx[2 * i], hItd->xcorr_smooth_fx_e, &sum_xcorr_e[0] ); + move32(); + // sum_xcorr[1] += hItd->xcorr_smooth[2 * i + 1]; + sum_xcorr[1] = BASOP_Util_Add_Mant32Exp( sum_xcorr[1], sum_xcorr_e[1], hItd->xcorr_smooth_fx[2 * i + 1], hItd->xcorr_smooth_fx_e, &sum_xcorr_e[1] ); + move32(); + // sum_nrg_L += nrg_L[i]; + sum_nrg_L = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, nrg_L[i], nrg_L_e[i], &sum_nrg_L_e ); + // sum_nrg_R += nrg_R[i]; + sum_nrg_R = BASOP_Util_Add_Mant32Exp( sum_nrg_R, sum_nrg_R_e, nrg_R[i], nrg_R_e[i], &sum_nrg_R_e ); + } + + // Sxcorr = sum_xcorr[0] * sum_xcorr[0] + sum_xcorr[1] * sum_xcorr[1]; + Sxcorr = BASOP_Util_Add_Mant32Exp( Mpy_32_32( sum_xcorr[0], sum_xcorr[0] ), shl( sum_xcorr_e[0], 1 ), Mpy_32_32( sum_xcorr[1], sum_xcorr[1] ), shl( sum_xcorr_e[1], 1 ), &Sxcorr_e ); + // hItd->acorr_L[b] = ( 1.f - sfm ) * hItd->acorr_L[b] + sfm * sum_nrg_L; + hItd->acorr_L_fx[b] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm ), hItd->acorr_L_fx[b] ), hItd->acorr_L_fx_e, Mpy_32_32( sfm, sum_nrg_L ), sum_nrg_L_e, &acorr_L_fx_tmp_e[b] ); + move32(); + // hItd->acorr_R[b] = ( 1.f - sfm ) * hItd->acorr_R[b] + sfm * sum_nrg_R; + hItd->acorr_R_fx[b] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm ), hItd->acorr_R_fx[b] ), hItd->acorr_R_fx_e, Mpy_32_32( sfm, sum_nrg_R ), sum_nrg_R_e, &acorr_R_fx_tmp_e[b] ); + move32(); + + // a = hItd->acorr_L[b] - hItd->acorr_R[b]; + a = BASOP_Util_Add_Mant32Exp( hItd->acorr_L_fx[b], acorr_L_fx_tmp_e[b], L_negate( hItd->acorr_R_fx[b] ), acorr_R_fx_tmp_e[b], &a_e ); + // acorr = hItd->acorr_L[b] + hItd->acorr_R[b]; + acorr = BASOP_Util_Add_Mant32Exp( hItd->acorr_L_fx[b], acorr_L_fx_tmp_e[b], hItd->acorr_R_fx[b], acorr_R_fx_tmp_e[b], &acorr_e ); + // fi[b] = sqrtf( a * a + 4 * Sxcorr ); + fi[b] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( a, a ), shl( a_e, 1 ), Sxcorr, add( Sxcorr_e, 2 ), &fi_e[b] ); + move32(); + fi[b] = Sqrt32( fi[b], &fi_e[b] ); + move32(); + // Er[b] = ( acorr + fi[b] ) / ( acorr - fi[b] + EPSILON ); + L_temp1 = BASOP_Util_Add_Mant32Exp( acorr, acorr_e, fi[b], fi_e[b], &L_temp1_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( acorr, acorr_e, L_negate( fi[b] ), fi_e[b], &L_temp2_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( L_temp2, L_temp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_temp2_e ); + Er[b] = BASOP_Util_Divide3232_Scale_cadence( L_temp1, L_temp2, &Er_e[b] ); + move32(); + Er_e[b] = add( Er_e[b], sub( L_temp1_e, L_temp2_e ) ); + move16(); + // sum_Er += Er[b]; + sum_Er = BASOP_Util_Add_Mant32Exp( sum_Er, *sum_Er_e, Er[b], Er_e[b], sum_Er_e ); + + // grand_nrg_L += sum_nrg_L; + grand_nrg_L = BASOP_Util_Add_Mant32Exp( grand_nrg_L, grand_nrg_L_e, sum_nrg_L, sum_nrg_L_e, &grand_nrg_L_e ); + // grand_nrg_R += sum_nrg_R; + grand_nrg_R = BASOP_Util_Add_Mant32Exp( grand_nrg_R, grand_nrg_R_e, sum_nrg_R, sum_nrg_R_e, &grand_nrg_R_e ); + // grand_sum_xcorr_real += sum_xcorr[0]; + grand_sum_xcorr_real = BASOP_Util_Add_Mant32Exp( grand_sum_xcorr_real, grand_sum_xcorr_real_e, sum_xcorr[0], sum_xcorr_e[0], &grand_sum_xcorr_real_e ); + // grand_sum_xcorr_img += sum_xcorr[1]; + grand_sum_xcorr_img = BASOP_Util_Add_Mant32Exp( grand_sum_xcorr_img, grand_sum_xcorr_img_e, sum_xcorr[1], sum_xcorr_e[1], &grand_sum_xcorr_img_e ); + } + + /*making common exp*/ + Word16 max_exp1 = MIN_16, max_exp2 = MIN_16; + FOR( b = 0; b < nbands; b++ ) + { + max_exp1 = s_max( max_exp1, acorr_L_fx_tmp_e[b] ); + max_exp2 = s_max( max_exp2, acorr_R_fx_tmp_e[b] ); + } + hItd->acorr_L_fx_e = max_exp1; + hItd->acorr_R_fx_e = max_exp2; + FOR( b = 0; b < nbands; b++ ) + { + hItd->acorr_L_fx[b] = L_shr_r( hItd->acorr_L_fx[b], sub( hItd->acorr_L_fx_e, acorr_L_fx_tmp_e[b] ) ); + move32(); + hItd->acorr_R_fx[b] = L_shr_r( hItd->acorr_R_fx[b], sub( hItd->acorr_R_fx_e, acorr_R_fx_tmp_e[b] ) ); + move32(); + } + + // Sxcorr = grand_sum_xcorr_real * grand_sum_xcorr_real + grand_sum_xcorr_img * grand_sum_xcorr_img; + Sxcorr = BASOP_Util_Add_Mant32Exp( Mpy_32_32( grand_sum_xcorr_real, grand_sum_xcorr_real ), shl( grand_sum_xcorr_real_e, 1 ), Mpy_32_32( grand_sum_xcorr_img, grand_sum_xcorr_img ), shl( grand_sum_xcorr_img_e, 1 ), &Sxcorr_e ); + // a = grand_nrg_L - grand_nrg_R; + a = BASOP_Util_Add_Mant32Exp( grand_nrg_L, grand_nrg_L_e, L_negate( grand_nrg_R ), grand_nrg_R_e, &a_e ); + // acorr = grand_nrg_L + grand_nrg_R; + acorr = BASOP_Util_Add_Mant32Exp( grand_nrg_L, grand_nrg_L_e, grand_nrg_R, grand_nrg_R_e, &acorr_e ); + // total_fi = sqrtf( a * a + 4 * Sxcorr ); + total_fi = BASOP_Util_Add_Mant32Exp( Mpy_32_32( a, a ), shl( a_e, 1 ), Sxcorr, add( Sxcorr_e, 2 ), &total_fi_e ); + total_fi = Sqrt32( total_fi, &total_fi_e ); + //*total_mEr = ( acorr + total_fi ) / ( acorr - total_fi + EPSILON ); + L_temp1 = BASOP_Util_Add_Mant32Exp( acorr, acorr_e, total_fi, total_fi_e, &L_temp1_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( acorr, acorr_e, L_negate( total_fi ), total_fi_e, &L_temp2_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( L_temp2, L_temp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_temp2_e ); + *total_mEr = BASOP_Util_Divide3232_Scale_cadence( L_temp1, L_temp2, total_mEr_e ); + move32(); + *total_mEr_e = add( *total_mEr_e, sub( L_temp1_e, L_temp2_e ) ); + move16(); + + // return ( sum_Er * B_DENOM ); + return Mpy_32_32( sum_Er, B_DENOM_Q31 ); +} +#endif static float calc_mean_E_ratio( ITD_DATA_HANDLE hItd, int16_t nbands, @@ -387,7 +853,25 @@ static float calc_mean_E_ratio( * * resets long term estimates to initial values. *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void resetEstimates_fx( + ITD_DATA_HANDLE hItd ) +{ + set32_fx( hItd->xcorr_smooth_fx, 0, STEREO_DFT_N_32k_ENC ); + hItd->xcorr_smooth_fx_e = 0; + move16(); + set32_fx( hItd->acorr_L_fx, 0, STEREO_DFT_BAND_MAX ); + hItd->acorr_L_fx_e = 0; + move16(); + set32_fx( hItd->acorr_R_fx, 0, STEREO_DFT_BAND_MAX ); + hItd->acorr_R_fx_e = 0; + move16(); + hItd->cohSNR_fx = 983040; + move32(); + return; +} +#endif static void resetEstimates( ITD_DATA_HANDLE hItd ) { @@ -404,7 +888,35 @@ static void resetEstimates( * * time-domain smoothing filter for smoothing the cross-correlation vector *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void td_sm_filter_fx( + Word32 *x, + Word32 *y, + const Word16 L ) +{ + Word16 i; + Word32 tmp_x[STEREO_DFT_N_32k_ENC + 1]; + // Word16 a0, a1; + + set32_fx( tmp_x, 0, STEREO_DFT_N_32k_ENC + 1 ); + Copy32( x, tmp_x, L ); + + // a0 = 0.5f; + // a1 = 0.25f; + // y[0] = a0 * tmp_x[0] + a1 * x[1]; + y[0] = L_add( L_shr_r( tmp_x[0], 1 ), L_shr_r( x[1], 2 ) ); + move32(); + FOR( i = 1; i < L; i++ ) + { + // y[i] = a1 * tmp_x[i + 1] + a0 * tmp_x[i] + a1 * tmp_x[i - 1]; + y[i] = L_add( L_add( L_shr_r( tmp_x[i + 1], 2 ), L_shr_r( tmp_x[i], 1 ) ), L_shr_r( tmp_x[i - 1], 2 ) ); + move32(); + } + + return; +} +#endif static void td_sm_filter( float *x, float *y, @@ -435,7 +947,222 @@ static void td_sm_filter( * function for calculating the threshold for peak detection of the * cross-correlation vector *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word32 peak_detect_fx( + Word32 *xcorr_itd, + Word32 *max_max, // xcorr_itd_e + Word16 *index, + Word16 *zero_itd_flag, + const Word32 snr, // Q16 + const Word16 vad, + Word32 *second_max, + Word16 *second_max_lag, + const Word16 prev_itd, + const Word16 flag_noisy_speech_snr, + const Word16 detected_itd_flag, + Word32 *prev_max, // Q31 + Word16 *prev_index, + Word32 *prev_avg_max, + Word16 *prev_avg_max_e, + Word32 *total_max, // xcorr_itd_e + Word16 *out_e ) +{ + Word16 i; + Word32 tmp_max[SUBDIV], tmp_xcorr_itd[2 * STEREO_DFT_ITD_MAX_ANA + 1], tmp_xcorr_itd_sm[2 * STEREO_DFT_ITD_MAX_ANA + 1]; + Word16 index_subd[SUBDIV], ind; + Word32 avg_max, max_low, max_high, sum_max, tmp_max_max; + Word16 sum_max_e; + Word32 thres_diff; + Word16 thres_diff_e; + Word32 wfac; // Q29 + Word16 d, i1, i2; + + wfac = 1342177280; // 2.5f in Q29 + move32(); + // if ( snr > 50.f ) + IF( BASOP_Util_Cmp_Mant32Exp( snr, 15, 50, 31 ) > 0 ) + { + wfac = 1610612736; // 3.f in Q29 + move32(); + } + /*detect maxima outside the [-5, 5] ms boundaries */ + maximum_l( xcorr_itd, STEREO_DFT_N_32k_ENC / 2 - STEREO_DFT_ITD_MAX_ANA, &max_low ); + maximum_l( xcorr_itd + STEREO_DFT_N_32k_ENC / 2 + STEREO_DFT_ITD_MAX_ANA + 1, STEREO_DFT_N_32k_ENC / 2 - STEREO_DFT_ITD_MAX_ANA - 1, &max_high ); + + /* create temp buffer that includes xcorr within [-5, 5] ms */ + Copy32( xcorr_itd + STEREO_DFT_N_32k_ENC / 2 - STEREO_DFT_ITD_MAX_ANA, tmp_xcorr_itd, 2 * STEREO_DFT_ITD_MAX_ANA + 1 ); // Q31 + + *index = maximumAbs_l( tmp_xcorr_itd, 2 * STEREO_DFT_ITD_MAX_ANA + 1, max_max ); + move16(); + *total_max = *max_max; // Q31 + move32(); + + // d = max( 2, (int16_t) round_f( fabsf( prev_itd ) / 16.f ) ); + d = s_max( 2, shr_r( abs_s( prev_itd ), 4 ) ); + // i1 = max( 0, (int16_t) prev_itd + STEREO_DFT_ITD_MAX_ANA - d ); + i1 = s_max( 0, add( prev_itd, sub( STEREO_DFT_ITD_MAX_ANA, d ) ) ); + // i2 = min( 2 * STEREO_DFT_ITD_MAX_ANA, (int16_t) prev_itd + STEREO_DFT_ITD_MAX_ANA + d ); + i2 = s_min( 2 * STEREO_DFT_ITD_MAX_ANA, add( prev_itd, add( STEREO_DFT_ITD_MAX_ANA, d ) ) ); + //*second_max_lag = maximumAbs( tmp_xcorr_itd + i1, i2 - i1 + 1, second_max ); + *second_max_lag = maximumAbs_l( tmp_xcorr_itd + i1, i2 - i1 + 1, second_max ); // Q31 + move16(); + *second_max_lag = add( *second_max_lag, i1 ); + move16(); + + + /*if maximum is out of boundaries signal zero itd OR maximum value is negative*/ + test(); + *zero_itd_flag = ( L_sub( *max_max, 4294968 ) < max_low || *max_max < max_high ); + move16(); + // adjustment is done for matching processing path with float code (differing due to precision loss) + + IF( *zero_itd_flag ) + { + *out_e = 0; + move16(); + return 0; + } + ELSE + { + sum_max = 0; + move32(); + sum_max_e = 0; + move16(); + + // if ( snr >= 25.f ) + IF( BASOP_Util_Cmp_Mant32Exp( snr, 15, 25, 31 ) >= 0 ) + { + /*apply smoothing filter*/ + td_sm_filter_fx( tmp_xcorr_itd, tmp_xcorr_itd_sm, 2 * STEREO_DFT_ITD_MAX_ANA + 1 ); // Q31 + + /*subdivide the area of interest and look for local maxima*/ + FOR( i = 0; i < SUBDIV - 1; i++ ) + { + index_subd[i] = maximumAbs_l( &tmp_xcorr_itd_sm[i * L_SAMPLES], L_SAMPLES, &tmp_max[i] ); + move16(); + // sum_max += tmp_max[i]; + sum_max = BASOP_Util_Add_Mant32Exp( sum_max, sum_max_e, tmp_max[i], 0, &sum_max_e ); + } + + index_subd[i] = maximumAbs_l( &tmp_xcorr_itd_sm[i * L_SAMPLES], L_SAMPLES + 1, &tmp_max[i] ); + move16(); + // sum_max += tmp_max[i]; + sum_max = BASOP_Util_Add_Mant32Exp( sum_max, sum_max_e, tmp_max[i], 0, &sum_max_e ); + + ind = maximumAbs_l( tmp_max, SUBDIV, &tmp_max_max ); + + /*final position of maxmimum*/ + *index = add( index_subd[ind], imult1616( ind, L_SAMPLES ) ); + move16(); + *max_max = tmp_max_max; + move16(); + /*calculate average of all maxima to determine the threshold*/ + // avg_max = sum_max * DENOM; + avg_max = Mpy_32_32( sum_max, DENOM_Q31 ); // sum_max_e + + // d = max( 2, (int16_t) round_f( fabsf( prev_itd ) / 16.f ) ); + d = s_max( 2, shr_r( abs_s( prev_itd ), 4 ) ); + // i1 = max( 0, (int16_t) prev_itd + STEREO_DFT_ITD_MAX_ANA - d ); + i1 = s_max( 0, add( prev_itd, sub( STEREO_DFT_ITD_MAX_ANA, d ) ) ); + // i2 = min( 2 * STEREO_DFT_ITD_MAX_ANA, (int16_t) prev_itd + STEREO_DFT_ITD_MAX_ANA + d ); + i2 = s_min( 2 * STEREO_DFT_ITD_MAX_ANA, add( prev_itd, add( STEREO_DFT_ITD_MAX_ANA, d ) ) ); + *second_max_lag = maximumAbs_l( tmp_xcorr_itd_sm + i1, add( sub( i2, i1 ), 1 ), second_max ); + move16(); + *second_max_lag = add( *second_max_lag, i1 ); + move16(); + } + ELSE + { + /*determine weight for threshold depending on snr value*/ + // if ( snr <= 20.f && snr > 15.f ) + test(); + IF( ( BASOP_Util_Cmp_Mant32Exp( snr, 15, 20, 31 ) <= 0 ) && ( BASOP_Util_Cmp_Mant32Exp( snr, 15, 15, 31 ) > 0 ) ) + { + // wfac = snr * 0.1f + 0.5f; + wfac = L_add( Mpy_32_32( L_shl( snr, 10 ) /*Q16+10=Q26*/, 1717986918 /*0.1 in Q34*/ ) /*Q26*Q34=Q29*/, ONE_IN_Q28 ); + } + ELSE + { + wfac = 1342177280; // 2.5f in Q29 + move16(); + } + + FOR( i = 0; i < SUBDIV - 1; i++ ) + { + index_subd[i] = maximumAbs_l( &tmp_xcorr_itd[i * L_SAMPLES], L_SAMPLES, &tmp_max[i] ); + move16(); + // sum_max += tmp_max[i]; + sum_max = BASOP_Util_Add_Mant32Exp( sum_max, sum_max_e, tmp_max[i], 0, &sum_max_e ); + } + + index_subd[i] = maximumAbs_l( &tmp_xcorr_itd[i * L_SAMPLES], L_SAMPLES + 1, &tmp_max[i] ); + move16(); + // sum_max += tmp_max[i]; + sum_max = BASOP_Util_Add_Mant32Exp( sum_max, sum_max_e, tmp_max[i], 0, &sum_max_e ); + + /*calculate average of all maxima to determine the threshold*/ + // avg_max = sum_max * DENOM; + avg_max = Mpy_32_32( sum_max, DENOM_Q31 ); // sum_max_e + } + + /*relax threshold if threshold is very close to max: when 7 0.f && ( ( thres_diff < 0.05f && ( snr <= 15 && snr > 7.f ) ) || ( thres_diff < 0.01f && ( snr > 15.f && snr < 30.f ) ) ) ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ( vad && thres_diff > 0 && ( ( BASOP_Util_Cmp_Mant32Exp( thres_diff, thres_diff_e, 107374182, 0 ) < 0 && ( BASOP_Util_Cmp_Mant32Exp( snr, 15, 15, 31 ) <= 0 && BASOP_Util_Cmp_Mant32Exp( snr, 15, 7, 31 ) > 0 ) ) || ( BASOP_Util_Cmp_Mant32Exp( thres_diff, thres_diff_e, 21474836, 0 ) < 0 && ( BASOP_Util_Cmp_Mant32Exp( snr, 15, 15, 31 ) > 0 && BASOP_Util_Cmp_Mant32Exp( snr, 15, 30, 31 ) < 0 ) ) ) ) + { + wfac = ONE_IN_Q30; // 2.0f + move32(); + } + + IF( EQ_16( flag_noisy_speech_snr, 1 ) ) + { + test(); + test(); + test(); + IF( vad == 0 ) + { + wfac = 1342177280; // 2.5f in Q29 + move32(); + } + // else if ( detected_itd_flag == 0 && *max_max > 1.5f * avg_max && *prev_max > 1.5f * *prev_avg_max && abs( *index - *prev_index ) <= 2 ) + ELSE IF( detected_itd_flag == 0 && BASOP_Util_Cmp_Mant32Exp( *max_max, 0, Mpy_32_32( 1610612736, avg_max ), add( sum_max_e, 1 ) ) > 0 && BASOP_Util_Cmp_Mant32Exp( *prev_max, 0, Mpy_32_32( 1610612736, *prev_avg_max ), add( *prev_avg_max_e, 1 ) ) > 0 && LE_16( abs_s( sub( *index, *prev_index ) ), 2 ) ) + { + wfac = 1610612736; // 1.5f in Q29 + move32(); + } + ELSE + { + wfac = ONE_IN_Q30; // 2.0fin Q29 + move32(); + } + } + *prev_max = *max_max; + move32(); + *prev_avg_max = avg_max; + move32(); + *prev_avg_max_e = sum_max_e; + move16(); + *prev_index = *index; + move16(); + + // return ( wfac * avg_max ); + *out_e = add( 2, sum_max_e ); + move16(); + return Mpy_32_32( wfac, avg_max ); // 2+sum_max_e + } +} +#endif static float peak_detect( float *xcorr_itd, float *max_max, @@ -586,7 +1313,1648 @@ static float peak_detect( * Compute stereo parameter: ITD * ITD: Interchannel Time Difference *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_compute_itd_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word32 *DFT_L, + Word16 DFT_L_e, + Word32 *DFT_R, + Word16 DFT_R_e, + const Word16 k_offset, + const Word16 input_frame, + const Word16 vad_flag_dtx[], + const Word16 vad_hover_flag[], + Word32 *bin_nrgL, + Word16 *bin_nrgL_e, + Word32 *bin_nrgR, + Word16 *bin_nrgR_e ) +{ + Word16 i, j; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + ITD_DATA_HANDLE hItd; + Word32 *pDFT_L, *pDFT_R; + Word16 DFT_L_e_tmp[STEREO_DFT_N_MAX_ENC], DFT_R_e_tmp[STEREO_DFT_N_MAX_ENC]; + Word32 abs_L, abs_R, prod_L, prod_R, sum_abs_L, sum_abs_R; + Word16 abs_L_e, abs_R_e, prod_L_e, prod_R_e, sum_abs_L_e, sum_abs_R_e; + Word32 log_prod_L, log_prod_R; + Word16 log_prod_L_e, log_prod_R_e; + Word32 sum_nrg_L, sum_nrg_R; + Word16 sum_nrg_L_e, sum_nrg_R_e; + Word32 sfm_L, sfm_R; + Word16 sfm_L_e, sfm_R_e; + Word32 xcorr[STEREO_DFT_N_32k_ENC]; + Word16 xcorr_e[STEREO_DFT_N_32k_ENC]; + Word16 xcorr_e_final; + Word16 itd, itd_td; + Word32 xcorr_itd[STEREO_DFT_N_32k_ENC]; + // Word16 xcorr_itd_e[STEREO_DFT_N_32k_ENC]; + Word32 tmpf1, tmpf2, tmpf3; + Word16 tmpf1_e, tmpf2_e, tmpf3_e; + Word32 thres, alpha; + Word16 thres_e; + Word16 index; + Word32 xcorr_max, sum_nrg_L_lb, par_L[XCORR_LB_NUM_BANDS], par_L_avrg, sum_nrg_L_tmp; + Word16 xcorr_max_e, sum_nrg_L_lb_e, par_L_e[XCORR_LB_NUM_BANDS], /* par_L_avrg_e,*/ sum_nrg_L_tmp_e; + Word32 xcorr_lb[STEREO_DFT_XCORR_LB_MAX]; + Word16 xcorr_lb_e[STEREO_DFT_XCORR_LB_MAX]; + Word32 num_cor, den_cor_cur, den_cor_prev, cor_lb_avrg; + Word16 num_cor_e, den_cor_cur_e, den_cor_prev_e /*, cor_lb_avrg_e*/; + Word32 cor_lb[XCORR_LB_NUM_BANDS]; + Word16 cor_lb_e[XCORR_LB_NUM_BANDS]; + Word32 Spd_L[STEREO_DFT_N_32k_ENC / 2 + 1]; + Word16 Spd_L_e[STEREO_DFT_N_32k_ENC / 2 + 1]; + Word32 Spd_R[STEREO_DFT_N_32k_ENC / 2 + 1]; + Word16 Spd_R_e[STEREO_DFT_N_32k_ENC / 2 + 1]; + Word16 vad_flag_itd; + Word32 mssnr; + Word16 mssnr_e; + Word16 itd_cal_flag; + Word16 NFFT, NFFT_mid; + Word16 zero_itd; + Word32 mEr; + Word16 mEr_e; + Word32 cohSNR; // Q16 + Word32 *pNrgL, *pNrgR; + Word16 *pNrgL_e, *pNrgR_e; + Word32 second_max; + Word16 second_max_lag; + Word16 fc_condition_1, fc_condition_2, fc_condition_3, fc_condition_4, fc_condition_5, fc_condition_6_a, fc_condition_6_b, fc_condition_6_c; + Word16 fc_condition_1234; + Word16 split, shift, flag_noisy_speech_snr; + Word32 gcc_phat[2 * XTALK_PHAT_LEN + 1]; + Word32 grand_dot_prod_real, grand_dot_prod_img; + Word16 grand_dot_prod_real_e, grand_dot_prod_img_e; + Word32 xcorr_abs[STEREO_DFT_N_32k_ENC], sum_xcorr, prod_LL, prod_RR, total_mEr, total_max; + Word16 xcorr_abs_e[STEREO_DFT_N_32k_ENC], sum_xcorr_e, prod_LL_e, prod_RR_e, total_mEr_e; + STEREO_CLASSIF_HANDLE hStereoClassif; + const Word16 *dft_trigo32k; + Word16 trigo_enc[STEREO_DFT_N_32k_ENC / 2 + 1]; + + Word32 cng_xcorr_filt; + Word16 cng_xcorr_filt_e; + + Word16 prev_itd_max; + Word16 itd_max_flip; + + Word32 L_temp; + Word16 L_temp_e; + Word32 L_temp2; + Word16 L_temp2_e; + Word16 max_exp; + Word16 q_temp; + Word64 W_temp; + Word16 W_temp_q; + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + hStereoDft = hCPE->hStereoDft; + hItd = hCPE->hStereoDft->hItd; + NFFT = s_min( STEREO_DFT_N_32k_ENC, hStereoDft->NFFT ); + dft_trigo32k = hStereoDft->dft_trigo_32k_fx; + } + ELSE + { + hStereoDft = NULL; + hItd = hCPE->hStereoMdct->hItd; + NFFT = s_min( STEREO_DFT_N_32k_ENC, hCPE->hStereoMdct->hDft_ana->NFFT ); + dft_trigo32k = hCPE->hStereoMdct->hDft_ana->dft_trigo_32k_fx; + } + hStereoClassif = hCPE->hStereoClassif; + + FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 4; i++ ) + { + trigo_enc[i] = dft_trigo32k[i]; + move16(); + trigo_enc[STEREO_DFT_N_32k_ENC / 2 - i] = dft_trigo32k[i]; + move16(); + } + trigo_enc[STEREO_DFT_N_32k_ENC / 4] = dft_trigo32k[STEREO_DFT_N_32k_ENC / 4]; + move16(); + + flag_noisy_speech_snr = hCPE->hCoreCoder[0]->flag_noisy_speech_snr; /* flag from the previous frame */ + move16(); + + /* initializations to avoid compilation warnings */ + sum_nrg_L = 0; + move32(); + sum_nrg_L_e = 0; + move16(); + sum_nrg_R = 0; + move32(); + sum_nrg_R_e = 0; + move16(); + sum_nrg_L_lb = 0; + move32(); + sum_nrg_L_lb_e = 0; + move16(); + mssnr = 0; + move32(); + mssnr_e = 0; + move16(); + sfm_L = 0; + move32(); + sfm_L_e = 0; + move16(); + + + NFFT_mid = shr( s_min( STEREO_DFT_N_16k_ENC, NFFT ), 1 ); + + pDFT_L = DFT_L; + pDFT_R = DFT_R; + FOR( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + L_temp_e = norm_l( pDFT_L[i] ); + pDFT_L[i] = L_shl( pDFT_L[i], L_temp_e ); + move32(); + DFT_L_e_tmp[i] = sub( DFT_L_e, L_temp_e ); + move16(); + L_temp_e = norm_l( pDFT_R[i] ); + pDFT_R[i] = L_shl( pDFT_R[i], L_temp_e ); + move32(); + DFT_R_e_tmp[i] = sub( DFT_R_e, L_temp_e ); + move16(); + } + + pNrgL = bin_nrgL; + pNrgL_e = bin_nrgL_e; + pNrgR = bin_nrgR; + pNrgR_e = bin_nrgR_e; + xcorr[0] = 0; + move32(); + xcorr_e[0] = 0; + move16(); + xcorr[1] = 0; + move32(); + xcorr_e[1] = 0; + move16(); + // log_prod_L = logf( max( FLT_MIN, ABSVAL( pDFT_L[0] ) ) ); + IF( L_abs( pDFT_L[0] ) <= 0 ) + { + log_prod_L = -1272712205; + move32(); + } + ELSE + { + // log_prod_L = Mpy_32_32( L_add( BASOP_Util_Log2( L_abs( pDFT_L[0] ) ), L_shl( DFT_L_e_tmp[0], 25 ) ), LOG_E_2 ); + log_prod_L = BASOP_Util_Loge( L_abs( pDFT_L[0] ), DFT_L_e_tmp[0] ); + } + log_prod_L_e = 6; + move16(); + + // log_prod_R = logf( max( FLT_MIN, ABSVAL( pDFT_R[0] ) ) ); + IF( L_abs( pDFT_R[0] ) <= 0 ) + { + log_prod_R = -1272712205; + move32(); + } + ELSE + { + // log_prod_R = Mpy_32_32( L_add( BASOP_Util_Log2( L_abs( pDFT_R[0] ) ), L_shl( DFT_R_e_tmp[0], 25 ) ), LOG_E_2 ); + log_prod_R = BASOP_Util_Loge( L_abs( pDFT_R[0] ), DFT_R_e_tmp[0] ); + } + log_prod_R_e = 6; + move16(); + + prod_L = MAX_32; // Q31 + move32(); + prod_L_e = 0; + move16(); + prod_R = MAX_32; // Q31 + move32(); + prod_R_e = 0; + move16(); + sum_nrg_L = Mpy_32_32( pDFT_L[0], pDFT_L[0] ) /*+ FLT_MIN*/; + sum_nrg_L_e = shl( DFT_L_e_tmp[0], 1 ); + sum_nrg_R = Mpy_32_32( pDFT_R[0], pDFT_R[0] ) /*+ FLT_MIN*/; + sum_nrg_R_e = shl( DFT_R_e_tmp[0], 1 ); + sum_abs_L = BASOP_Util_Add_Mant32Exp( L_abs( pDFT_L[0] ), DFT_L_e_tmp[0], EPSILON_FX_M, EPSILON_FX_E, &sum_abs_L_e ) /*+ EPSILON*/; + sum_abs_R = BASOP_Util_Add_Mant32Exp( L_abs( pDFT_R[0] ), DFT_R_e_tmp[0], EPSILON_FX_M, EPSILON_FX_E, &sum_abs_R_e ) /*+ EPSILON*/; + xcorr_lb[0] = Mpy_32_32( pDFT_L[0], pDFT_L[0] ); + move32(); + xcorr_lb_e[0] = shl( DFT_L_e_tmp[0], 1 ); + move16(); + xcorr_lb[0] = BASOP_Util_Add_Mant32Exp( xcorr_lb[0], xcorr_lb_e[0], EPSILON_FX_M, EPSILON_FX_E, &xcorr_lb_e[0] ) /*+ EPSILON*/; + move32(); + sum_nrg_L_lb = xcorr_lb[0]; + sum_nrg_L_lb_e = xcorr_lb_e[0]; + prod_LL = MAX_32; // Q31 + move32(); + prod_LL_e = 0; + move16(); + prod_RR = MAX_32; // Q31 + move32(); + prod_RR_e = 0; + move16(); + grand_dot_prod_real = EPSILON_FX_M; + move32(); + grand_dot_prod_real_e = EPSILON_FX_E; + move16(); + grand_dot_prod_img = EPSILON_FX_M; + move32(); + grand_dot_prod_img_e = EPSILON_FX_E; + move16(); + + /* This initialization is added in fixed pt code, float code needs to be checked for this! */ + set32_fx( Spd_L, 0, STEREO_DFT_N_32k_ENC / 2 + 1 ); + set16_fx( Spd_L_e, 0, STEREO_DFT_N_32k_ENC / 2 + 1 ); + set32_fx( Spd_R, 0, STEREO_DFT_N_32k_ENC / 2 + 1 ); + set16_fx( Spd_R_e, 0, STEREO_DFT_N_32k_ENC / 2 + 1 ); + + j = 0; // for loop statement + FOR( i = 1; i < NFFT_mid; i++ ) + { + /*if ( i == 121 ) + { + i = i; + }*/ + // xcorr[2 * i] = pDFT_L[2 * i] * pDFT_R[2 * i] + pDFT_L[2 * i + 1] * pDFT_R[2 * i + 1]; + xcorr[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_R[2 * i] ), add( DFT_L_e_tmp[2 * i], DFT_R_e_tmp[2 * i] ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_R[2 * i + 1] ), add( DFT_L_e_tmp[2 * i + 1], DFT_R_e_tmp[2 * i + 1] ), &xcorr_e[2 * i] ); + move32(); + // xcorr[2 * i + 1] = pDFT_L[2 * i + 1] * pDFT_R[2 * i] - pDFT_L[2 * i] * pDFT_R[2 * i + 1]; + xcorr[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i + 1], pDFT_R[2 * i] ), add( DFT_L_e_tmp[2 * i + 1], DFT_R_e_tmp[2 * i] ), L_negate( Mpy_32_32( pDFT_L[2 * i], pDFT_R[2 * i + 1] ) ), add( DFT_L_e_tmp[2 * i], DFT_R_e_tmp[2 * i + 1] ), &xcorr_e[2 * i + 1] ); + move32(); + + // pNrgL[i] = pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + pNrgL[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_L[2 * i] ), shl( DFT_L_e_tmp[2 * i], 1 ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_L[2 * i + 1] ), shl( DFT_L_e_tmp[2 * i + 1], 1 ), &pNrgL_e[i] ); + move32(); + // pNrgR[i] = pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + pNrgR[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R[2 * i], pDFT_R[2 * i] ), shl( DFT_R_e_tmp[2 * i], 1 ), Mpy_32_32( pDFT_R[2 * i + 1], pDFT_R[2 * i + 1] ), shl( DFT_R_e_tmp[2 * i + 1], 1 ), &pNrgR_e[i] ); + move32(); + + Spd_L[i] = pNrgL[i]; + move32(); + Spd_L_e[i] = pNrgL_e[i]; + move16(); + Spd_R[i] = pNrgR[i]; + move32(); + Spd_R_e[i] = pNrgR_e[i]; + move16(); + + abs_L_e = pNrgL_e[i]; + move16(); + abs_L = Sqrt32( pNrgL[i], &abs_L_e ); + abs_R_e = pNrgR_e[i]; + move16(); + abs_R = Sqrt32( pNrgR[i], &abs_R_e ); + + // sum_nrg_L += pNrgL[i]; + sum_nrg_L = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, pNrgL[i], pNrgL_e[i], &sum_nrg_L_e ); + // sum_nrg_R += pNrgR[i]; + sum_nrg_R = BASOP_Util_Add_Mant32Exp( sum_nrg_R, sum_nrg_R_e, pNrgR[i], pNrgR_e[i], &sum_nrg_R_e ); + + // sum_abs_L += abs_L; + sum_abs_L = BASOP_Util_Add_Mant32Exp( sum_abs_L, sum_abs_L_e, abs_L, abs_L_e, &sum_abs_L_e ); + // sum_abs_R += abs_R; + sum_abs_R = BASOP_Util_Add_Mant32Exp( sum_abs_R, sum_abs_R_e, abs_R, abs_R_e, &sum_abs_R_e ); + // prod_L *= abs_L; + prod_L = Mpy_32_32( prod_L, abs_L ); + prod_L_e = add( prod_L_e, abs_L_e ); + // prod_R *= abs_R; + prod_R = Mpy_32_32( prod_R, abs_R ); + prod_R_e = add( prod_R_e, abs_R_e ); + + // grand_dot_prod_real += xcorr[2 * i]; + grand_dot_prod_real = BASOP_Util_Add_Mant32Exp( grand_dot_prod_real, grand_dot_prod_real_e, xcorr[2 * i], xcorr_e[2 * i], &grand_dot_prod_real_e ); + // grand_dot_prod_img += xcorr[2 * i + 1]; + grand_dot_prod_img = BASOP_Util_Add_Mant32Exp( grand_dot_prod_img, grand_dot_prod_img_e, xcorr[2 * i + 1], xcorr_e[2 * i + 1], &grand_dot_prod_img_e ); + + // xcorr_abs[i] = sqrtf( xcorr[2 * i] * xcorr[2 * i] + xcorr[2 * i + 1] * xcorr[2 * i + 1] ); + xcorr_abs[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( xcorr[2 * i], xcorr[2 * i] ), add( xcorr_e[2 * i], xcorr_e[2 * i] ), Mpy_32_32( xcorr[2 * i + 1], xcorr[2 * i + 1] ), add( xcorr_e[2 * i + 1], xcorr_e[2 * i + 1] ), &xcorr_abs_e[i] ); + move32(); + xcorr_abs[i] = Sqrt32( xcorr_abs[i], &xcorr_abs_e[i] ); + move32(); + /* VM: prod_LL tends to overflow, better to replace with sum(log(prod_L)) and retrain the classifier */ + prod_LL = prod_L; + move32(); + prod_LL_e = prod_L_e; + move16(); + prod_RR = prod_R; + move32(); + prod_RR_e = prod_R_e; + move16(); + + test(); + IF( EQ_16( j, SFM_PROD_GRP ) || EQ_16( i, sub( NFFT_mid, 1 ) ) ) + { + prod_L = L_max( 0, prod_L ); + prod_R = L_max( 0, prod_R ); + IF( prod_L <= 0 ) + { + L_temp = -1272712205; + move32(); + L_temp_e = 6; + move16(); + } + ELSE + { + // L_temp = Mpy_32_32( L_add( BASOP_Util_Log2( prod_L ), L_shl( prod_L_e, 25 ) ), LOG_E_2 ); + q_temp = norm_l( prod_L_e ); + L_temp = Mpy_32_32( BASOP_Util_Add_Mant32Exp( BASOP_Util_Log2( prod_L ), 6, L_shl( prod_L_e, q_temp ), sub( 31, q_temp ), &L_temp_e ), LOG_E_2 ); + } + // log_prod_L += logf( prod_L ); + log_prod_L = BASOP_Util_Add_Mant32Exp( log_prod_L, log_prod_L_e, L_temp, L_temp_e, &log_prod_L_e ); + IF( L_abs( prod_R ) <= 0 ) + { + L_temp = -1272712205; + move32(); + L_temp_e = 6; + move16(); + } + ELSE + { + // L_temp = Mpy_32_32( L_add( BASOP_Util_Log2( prod_R ), L_shl( prod_R_e, 25 ) ), LOG_E_2 ); + q_temp = norm_l( prod_R_e ); + L_temp = Mpy_32_32( BASOP_Util_Add_Mant32Exp( BASOP_Util_Log2( prod_R ), 6, L_shl( prod_R_e, q_temp ), sub( 31, q_temp ), &L_temp_e ), LOG_E_2 ); + } + // log_prod_R += logf( prod_R ); + log_prod_R = BASOP_Util_Add_Mant32Exp( log_prod_R, log_prod_R_e, L_temp, L_temp_e, &log_prod_R_e ); + + prod_L = MAX_32; + move32(); + prod_L_e = 0; + move16(); + prod_R = MAX_32; + move32(); + prod_R_e = 0; + move16(); + + j = 0; + move16(); + } + j++; // for loop statement + } + + /* collect UNCLR classifier parameters */ + { + Word32 IPD, d_IPD, g_IPD, g_ILD, angle_rot, g_side, g_pred, abs_L_R, grand_nrg_DMX; + Word16 /*IPD_e, */ d_IPD_e, g_IPD_e, g_ILD_e, /* angle_rot_e,*/ g_side_e, g_pred_e, abs_L_R_e, grand_nrg_DMX_e; + + IF( NE_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + // hStereoClassif->prev_g_IPD = 0.5f; + hStereoClassif->prev_g_IPD_fx = ONE_IN_Q28; + move32(); + // hStereoClassif->prev_IPD = 0.0f; + hStereoClassif->prev_IPD = 0; + move16(); + } + + // abs_L_R = sqrtf( grand_dot_prod_real * grand_dot_prod_real + grand_dot_prod_img * grand_dot_prod_img ); + abs_L_R = BASOP_Util_Add_Mant32Exp( Mpy_32_32( grand_dot_prod_real, grand_dot_prod_real ), shl( grand_dot_prod_real_e, 1 ), Mpy_32_32( grand_dot_prod_img, grand_dot_prod_img ), shl( grand_dot_prod_img_e, 1 ), &abs_L_R_e ); + abs_L_R = Sqrt32( abs_L_R, &abs_L_R_e ); + + // grand_nrg_DMX = sum_nrg_L + sum_nrg_R + 2 * abs_L_R; + L_temp = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, sum_nrg_R, sum_nrg_R_e, &L_temp_e ); + grand_nrg_DMX = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, abs_L_R, add( abs_L_R_e, 1 ), &grand_nrg_DMX_e ); + + // g_ILD = sqrtf( sum_nrg_L / ( sum_nrg_R + 1.0f ) ); + L_temp = BASOP_Util_Add_Mant32Exp( sum_nrg_R, sum_nrg_R_e, MAX_32, 0, &L_temp_e ); + g_ILD = BASOP_Util_Divide3232_Scale_cadence( sum_nrg_L, L_temp, &g_ILD_e ); + g_ILD_e = add( g_ILD_e, sub( sum_nrg_L_e, L_temp_e ) ); + g_ILD = Sqrt32( g_ILD, &g_ILD_e ); + + // g_ILD = fabsf( ( g_ILD - 1 ) / ( g_ILD + 1 ) ); + L_temp = BASOP_Util_Add_Mant32Exp( g_ILD, g_ILD_e, MIN_32, 0, &L_temp_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( g_ILD, g_ILD_e, MAX_32, 0, &L_temp2_e ); + g_ILD = L_abs( BASOP_Util_Divide3232_Scale_cadence( L_temp, L_temp2, &g_ILD_e ) ); + g_ILD_e = add( g_ILD_e, sub( L_temp_e, L_temp2_e ) ); + g_ILD = L_shl_sat( g_ILD, g_ILD_e ); // Q31 + + hStereoClassif->unclr_fv_fx[E_gainILD] = L_shr_r( g_ILD, 16 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_gainILD] = L_shr_r( g_ILD, 16 ); // Q15 + move32(); + + // IPD = atan2f( grand_dot_prod_img, grand_dot_prod_real ); + IPD = BASOP_util_atan2( grand_dot_prod_img, grand_dot_prod_real, sub( grand_dot_prod_img_e, grand_dot_prod_real_e ) ); // Q13 + + hStereoClassif->unclr_fv_fx[E_IPD] = L_shl( IPD, 2 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_IPD] = L_shl( IPD, 2 ); // Q15 + move32(); + + // d_IPD = fabsf( IPD - hStereoClassif->prev_IPD ); + d_IPD = BASOP_Util_Add_Mant32Exp( IPD, 18, L_negate( hStereoClassif->prev_IPD_fx ), 2, &d_IPD_e ); + d_IPD = L_abs( d_IPD ); + hStereoClassif->unclr_fv_fx[E_d_IPD] = L_shl( IPD, 2 ); // Q15 /* VM: need to replace IPD by d_IPD and re-train the UNCLR classifier for DFT stereo */ + move32(); + hStereoClassif->xtalk_fv_fx[E_d_IPD] = L_shr_r( d_IPD, sub( 16, d_IPD_e ) ); /// Q15 + move32(); + hStereoClassif->prev_IPD_fx = L_shl( IPD, 16 ); // Q29 + move32(); + + // g_IPD = ( sum_nrg_L + sum_nrg_R + 2 * grand_dot_prod_real ) / grand_nrg_DMX; + L_temp = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, sum_nrg_R, sum_nrg_R_e, &L_temp_e ); + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, grand_dot_prod_real, add( grand_dot_prod_real_e, 1 ), &L_temp_e ); + g_IPD = BASOP_Util_Divide3232_Scale_cadence( L_temp, grand_nrg_DMX, &g_IPD_e ); + g_IPD_e = add( g_IPD_e, sub( L_temp_e, grand_nrg_DMX_e ) ); + // if ( g_IPD >= 1.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( g_IPD, g_IPD_e, ONE_IN_Q29 - ONE_IN_Q14 /*Adjusting threshold for precision loss*/, 2 ) >= 0 ) + { + g_IPD = hStereoClassif->prev_g_IPD_fx; + move32(); + g_IPD_e = 2; + move16(); + } + ELSE + { + hStereoClassif->prev_g_IPD_fx = L_shr_r( g_IPD, sub( 2, g_IPD_e ) ); // Q29 + move32(); + } + // g_IPD = logf( 1.0f - g_IPD ); + L_temp = BASOP_Util_Add_Mant32Exp( MAX_32, 0, L_negate( g_IPD ), g_IPD_e, &L_temp_e ); + // g_IPD = Mpy_32_32( L_add( BASOP_Util_Log2( L_temp ), L_shl( L_temp_e, 25 ) ), LOG_E_2 ); + g_IPD = BASOP_Util_Loge( L_temp, L_temp_e ); + hStereoClassif->unclr_fv_fx[E_gainIPD] = L_shr_r( g_IPD, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_gainIPD] = L_shr_r( g_IPD, 10 ); // Q15 + move32(); + + // angle_rot = fabsf( atanf( 2.0f * ( grand_dot_prod_real ) / ( sum_nrg_L - sum_nrg_R + 1.0f ) ) ); + L_temp = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, L_negate( sum_nrg_R ), sum_nrg_R_e, &L_temp_e ); + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, MAX_32, 0, &L_temp_e ); + L_temp2 = BASOP_Util_Divide3232_Scale_cadence( grand_dot_prod_real, L_temp, &L_temp2_e ); + L_temp2_e = add( L_temp2_e, sub( add( grand_dot_prod_real_e, 1 ), L_temp_e ) ); + angle_rot = L_abs( BASOP_util_atan( L_shr_r_sat( L_temp2, ( sub( 6, L_temp2_e ) ) ) ) ); // Q14 + // angle_rot = L_abs( BASOP_util_atan2( grand_dot_prod_real, L_temp, sub( add( grand_dot_prod_real_e, 1 ), L_temp_e ) ) ); // Q13 + + hStereoClassif->unclr_fv_fx[E_angle_rot] = L_shl( angle_rot, 1 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_angle_rot] = L_shl( angle_rot, 1 ); // Q15 + move32(); + + // g_side = fabsf( sum_nrg_L - sum_nrg_R ) / ( grand_nrg_DMX ); + L_temp = L_abs( BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, L_negate( sum_nrg_R ), sum_nrg_R_e, &L_temp_e ) ); + g_side = BASOP_Util_Divide3232_Scale_cadence( L_temp, grand_nrg_DMX, &g_side_e ); + g_side_e = add( g_side_e, sub( L_temp_e, grand_nrg_DMX_e ) ); + g_side = L_shl_sat( g_side, g_side_e ); // Q31 + g_side_e = 0; + + // g_side = max( 0.01f, min( g_side, 0.99f ) ); + g_side = L_max( 21474836, L_min( g_side, 2126008811 ) ); + hStereoClassif->unclr_fv_fx[E_g_side] = L_shr_r( g_side, 16 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_g_side] = L_shr_r( g_side, 16 ); // Q15 + move32(); + + // g_pred = logf( max( 0, ( ( 1 - g_side ) * sum_nrg_L + ( 1 + g_side ) * sum_nrg_R - 2 * abs_L_R ) ) + 1.0f ); + L_temp = BASOP_Util_Add_Mant32Exp( MAX_32, 0, L_negate( g_side ), g_side_e, &L_temp_e ); + L_temp = Mpy_32_32( L_temp, sum_nrg_L ); + L_temp_e = add( L_temp_e, sum_nrg_L_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( MAX_32, 0, g_side, g_side_e, &L_temp2_e ); + L_temp2 = Mpy_32_32( L_temp2, sum_nrg_R ); + L_temp2_e = add( L_temp2_e, sum_nrg_R_e ); + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, L_temp2, L_temp2_e, &L_temp_e ); + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, L_negate( abs_L_R ), add( abs_L_R_e, 1 ), &L_temp_e ); + L_temp = L_max( 0, L_temp ); + g_pred = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, MAX_32, 0, &g_pred_e ); + // g_pred = Mpy_32_32( L_add( BASOP_Util_Log2( g_pred ), L_shl( g_pred_e, 25 ) ), LOG_E_2 ); // Q25 + g_pred = BASOP_Util_Loge( g_pred, g_pred_e ); // Q25 + g_pred_e = 6; + move16(); + + // g_pred = max( 14.0f, g_pred ); + g_pred = L_max( 14 << 25, g_pred ); + hStereoClassif->unclr_fv_fx[E_g_pred] = L_shr_r( g_pred, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_g_pred] = L_shr_r( g_pred, 10 ); // Q15 + move32(); + } + + // mvr2r( &Spd_L[1], &xcorr_lb[1], STEREO_DFT_XCORR_LB_MAX - 1 ); + Copy32( &Spd_L[1], &xcorr_lb[1], STEREO_DFT_XCORR_LB_MAX - 1 ); + Copy( &Spd_L_e[1], &xcorr_lb_e[1], STEREO_DFT_XCORR_LB_MAX - 1 ); + + // sum_nrg_L_lb = sum_nrg_L_lb + sum_f( &Spd_L[1], 11 ); + L_temp = 0; + move32(); + L_temp_e = 0; + move16(); + FOR( i = 0; i < 11; i++ ) + { + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, Spd_L[i + 1], Spd_L_e[i + 1], &L_temp_e ); + } + // L_temp = sum2_32_fx( &Spd_L[1], 11, &L_temp_e ); + sum_nrg_L_lb = BASOP_Util_Add_Mant32Exp( sum_nrg_L_lb, sum_nrg_L_lb_e, L_temp, L_temp_e, &sum_nrg_L_lb_e ); + + vad_flag_itd = stereo_dft_enc_itd_vad_fx( hItd->E_band_n_fx, &( hItd->vad_frm_cnt ), Spd_L, Spd_L_e, Spd_R, Spd_R_e, &mssnr, &mssnr_e ); + + vad_flag_itd = vad_flag_itd && vad_flag_dtx[0]; + + // if ( sum_nrg_L < EPSILON ) + IF( BASOP_Util_Cmp_Mant32Exp( sum_nrg_L, sum_nrg_L_e, EPSILON_FX_M, EPSILON_FX_E ) < 0 ) + { + sfm_L = 0; + move32(); + sfm_L_e = 0; + move16(); + } + ELSE + { + // sfm_L = expf( log_prod_L / ( NFFT_mid ) ) / ( sum_abs_L / ( NFFT_mid ) ); + L_temp = BASOP_Util_Divide3232_Scale_cadence( log_prod_L, NFFT_mid, &L_temp_e ); + L_temp_e = add( L_temp_e, sub( log_prod_L_e, 31 ) ); + L_temp = BASOP_Util_fPow( 1459366444, 2, L_temp, L_temp_e, &L_temp_e ); + q_temp = norm_l( NFFT_mid ); + L_temp2 = L_shl( NFFT_mid, q_temp ); + L_temp2_e = sub( 31, q_temp ); + L_temp = Mpy_32_32( L_temp, L_temp2 ); + L_temp_e = add( L_temp_e, L_temp2_e ); + sfm_L = BASOP_Util_Divide3232_Scale_cadence( L_temp, sum_abs_L, &sfm_L_e ); + sfm_L_e = add( sfm_L_e, sub( L_temp_e, sum_abs_L_e ) ); + sfm_L = L_shl_sat( sfm_L, sfm_L_e ); // Q31 - should be rechecked for -10dB tests + } + + // if ( sum_nrg_R < EPSILON ) + IF( BASOP_Util_Cmp_Mant32Exp( sum_nrg_R, sum_nrg_R_e, EPSILON_FX_M, EPSILON_FX_E ) < 0 ) + { + sfm_R = 0; + move32(); + sfm_R_e = 0; + move16(); + } + ELSE + { + // sfm_R = expf( log_prod_R / ( NFFT_mid ) ) / ( sum_abs_R / ( NFFT_mid ) ); + L_temp = BASOP_Util_Divide3232_Scale_cadence( log_prod_R, NFFT_mid, &L_temp_e ); + L_temp_e = add( L_temp_e, sub( log_prod_R_e, 31 ) ); + L_temp = BASOP_Util_fPow( 1459366444, 2, L_temp, L_temp_e, &L_temp_e ); + q_temp = norm_l( NFFT_mid ); + L_temp2 = L_shl( NFFT_mid, q_temp ); + L_temp2_e = sub( 31, q_temp ); + L_temp = Mpy_32_32( L_temp, L_temp2 ); + L_temp_e = add( L_temp_e, L_temp2_e ); + sfm_R = BASOP_Util_Divide3232_Scale_cadence( L_temp, sum_abs_R, &sfm_L_e ); + sfm_R_e = add( sfm_L_e, sub( L_temp_e, sum_abs_R_e ) ); + sfm_R = L_shl_r( sfm_R, sfm_R_e ); // Q31 + } + + if ( sfm_R > sfm_L ) + { + sfm_L = sfm_R; + move32(); + } + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + hStereoDft->sfm_fx = sfm_L; + } + + FOR( ; i < NFFT / 2; i++ ) + { + // xcorr[2 * i] = pDFT_L[2 * i] * pDFT_R[2 * i] + pDFT_L[2 * i + 1] * pDFT_R[2 * i + 1]; + xcorr[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_R[2 * i] ), add( DFT_L_e_tmp[2 * i], DFT_R_e_tmp[2 * i] ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_R[2 * i + 1] ), add( DFT_L_e_tmp[2 * i + 1], DFT_R_e_tmp[2 * i + 1] ), &xcorr_e[2 * i] ); + move32(); + // xcorr[2 * i + 1] = pDFT_L[2 * i + 1] * pDFT_R[2 * i] - pDFT_L[2 * i] * pDFT_R[2 * i + 1]; + xcorr[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i + 1], pDFT_R[2 * i] ), add( DFT_L_e_tmp[2 * i + 1], DFT_R_e_tmp[2 * i] ), L_negate( Mpy_32_32( pDFT_L[2 * i], pDFT_R[2 * i + 1] ) ), add( DFT_L_e_tmp[2 * i], DFT_R_e_tmp[2 * i + 1] ), &xcorr_e[2 * i + 1] ); + move32(); + + // pNrgL[i] = pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + pNrgL[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_L[2 * i] ), shl( DFT_L_e_tmp[2 * i], 1 ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_L[2 * i + 1] ), shl( DFT_L_e_tmp[2 * i + 1], 1 ), &pNrgL_e[i] ); + move32(); + // pNrgR[i] = pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + pNrgR[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R[2 * i], pDFT_R[2 * i] ), shl( DFT_R_e_tmp[2 * i], 1 ), Mpy_32_32( pDFT_R[2 * i + 1], pDFT_R[2 * i + 1] ), shl( DFT_R_e_tmp[2 * i + 1], 1 ), &pNrgR_e[i] ); + move32(); + /* Calculate L and R energy power spectrum */ + Spd_L[i] = pNrgL[i]; + move32(); + Spd_L_e[i] = pNrgL_e[i]; + move16(); + Spd_R[i] = pNrgR[i]; + move32(); + Spd_R_e[i] = pNrgR_e[i]; + move16(); + } + + FOR( ; i < STEREO_DFT_N_32k_ENC / 2; i++ ) + { + xcorr[2 * i] = 0; + move32(); + xcorr_e[2 * i] = 0; + move16(); + xcorr[2 * i + 1] = 0; + move32(); + xcorr_e[2 * i + 1] = 0; + move16(); + } + + Word16 xcorr_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC]; + set16_fx( xcorr_smooth_fx_tmp_e, hItd->xcorr_smooth_fx_e, STEREO_DFT_N_32k_ENC ); + hItd->xcorr_smooth_fx[0] = 0; + move32(); + xcorr_smooth_fx_tmp_e[0] = 0; + move16(); + hItd->xcorr_smooth_fx[1] = 0; + move32(); + xcorr_smooth_fx_tmp_e[1] = 0; + move16(); + xcorr[0] = L_shl_sat( sign_fx( hItd->xcorr_smooth_fx[0] ), 31 ); + move32(); + xcorr_e[0] = 0; + move16(); + xcorr[1] = L_shl_sat( sign_fx( hItd->xcorr_smooth_fx[1] ), 31 ); + move32(); + xcorr_e[1] = 0; + move16(); + + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && sub( hItd->td_itd[k_offset], hItd->td_itd[k_offset - 1] ) ) + { + Word16 alphaD, c, s, c1, s1, ctmp; + Word32 vtmp; + Word16 vtmp_e; + // alphaD = -2.f * EVS_PI * ( (float) hItd->td_itd[k_offset] - hItd->td_itd[k_offset - 1] ) / hStereoDft->NFFT; + alphaD = BASOP_Util_Divide1616_Scale( sub( hItd->td_itd[k_offset], hItd->td_itd[sub( k_offset, 1 )] ), hStereoDft->NFFT, &L_temp_e ); + alphaD = mult_r( -EVS_PI_FX, alphaD ); + L_temp_e = add( L_temp_e, 3 ); + alphaD = shl_r( alphaD, L_temp_e - 2 ); // 2Q13 + + // c1 = cosf( alphaD ); + c1 = shl_sat( getCosWord16( alphaD ), 1 ); // Q15 + // s1 = sinf( alphaD ); + s1 = getSinWord16( alphaD ); // Q15 + c = MAX_16; /* cos(0) */ + move16(); + s = 0; /* sin(0) */ + move16(); + + FOR( i = 1; i < NFFT / 2; i++ ) + { + ctmp = c; + c = sub_sat( mult_r( c, c1 ), mult_r( s, s1 ) ); + s = add_sat( mult_r( ctmp, s1 ), mult_r( s, c1 ) ); + vtmp = BASOP_Util_Add_Mant32Exp( Mult_32_16( hItd->xcorr_smooth_fx[2 * i], c ), xcorr_smooth_fx_tmp_e[2 * i], L_negate( Mult_32_16( hItd->xcorr_smooth_fx[2 * i + 1], s ) ), xcorr_smooth_fx_tmp_e[2 * i + 1], &vtmp_e ); + hItd->xcorr_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mult_32_16( hItd->xcorr_smooth_fx[2 * i], s ), xcorr_smooth_fx_tmp_e[2 * i], Mult_32_16( hItd->xcorr_smooth_fx[2 * i + 1], c ), xcorr_smooth_fx_tmp_e[2 * i + 1], &xcorr_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + hItd->xcorr_smooth_fx[2 * i] = vtmp; + move32(); + xcorr_smooth_fx_tmp_e[2 * i] = vtmp_e; + move16(); + } + } + + tmpf3 = 2; + move32(); + tmpf3_e = 31; + move16(); + IF( flag_noisy_speech_snr ) + { + alpha = -1717986918 /*-0.8f*/; + move32(); + } + ELSE + { + alpha = MIN_32; + move32(); + } + + test(); + IF( hCPE->hCoreCoder[0]->Opt_DTX_ON && EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + Word16 xspec_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC]; + set16_fx( xspec_smooth_fx_tmp_e, hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); + Word16 Spd_L_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC / 2], Spd_R_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC / 2]; + set16_fx( Spd_L_smooth_fx_tmp_e, hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + set16_fx( Spd_R_smooth_fx_tmp_e, hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + IF( hCPE->hFrontVad[0] != NULL ) + { + /* Determine if we are in hangover */ + test(); + IF( vad_hover_flag[0] && vad_hover_flag[1] ) + { + /* Determine if we are in the first DTX hangover frame (also triggers for VAD hangover frame) */ + IF( GT_16( hStereoDft->resetFrames, CORR_RESET_FRAMES_MAX ) ) + { + /* Reset cross spectrum when there is hangover */ + set32_fx( hStereoDft->xspec_smooth_fx, 0, STEREO_DFT_N_32k_ENC ); + hStereoDft->resetFrames = 0; + move16(); + hStereoDft->currentNumUpdates = 0; + move16(); + /* Expected minimum number of updates including first SID */ + hStereoDft->expectedNumUpdates = add( 1, s_min( hCPE->hFrontVad[0]->rem_dtx_ho, hCPE->hFrontVad[1]->rem_dtx_ho ) ); + } + ELSE IF( GE_16( hStereoDft->currentNumUpdates, hStereoDft->expectedNumUpdates ) ) + { + hStereoDft->expectedNumUpdates = add( hStereoDft->expectedNumUpdates, add( 1, s_min( hCPE->hFrontVad[0]->rem_dtx_ho, hCPE->hFrontVad[1]->rem_dtx_ho ) ) ); + move16(); + } + // cng_xcorr_filt = max( min( CORR_FILT, 10.0f * CORR_FILT / ( hStereoDft->expectedNumUpdates + hStereoDft->currentNumUpdates ) ), sfm_L ); + + cng_xcorr_filt = BASOP_Util_Divide3232_Scale_cadence( 8 /*10.0f * CORR_FILT*/, add( hStereoDft->expectedNumUpdates, hStereoDft->currentNumUpdates ), &cng_xcorr_filt_e ); + cng_xcorr_filt = L_shl_sat( cng_xcorr_filt, cng_xcorr_filt_e ); // Q31 + cng_xcorr_filt = L_max( L_min( CORR_FILT_Q31, cng_xcorr_filt ), sfm_L ); // Q31 + + hStereoDft->currentNumUpdates = add( hStereoDft->currentNumUpdates, 1 ); + move16(); + FOR( i = 1; i < shr( NFFT, 2 ); i++ ) + { + /* Low pass filter cross L/R power spectrum */ + // hStereoDft->xspec_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; + hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i] ), xspec_smooth_fx_tmp_e[2 * i], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i] ), xcorr_e[2 * i], &xspec_smooth_fx_tmp_e[2 * i] ); + move32(); + // hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i + 1] + cng_xcorr_filt * xcorr[2 * i + 1]; + hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), xspec_smooth_fx_tmp_e[2 * i + 1], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xspec_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + + /* Low pass filter L/R power spectrum */ + /* Calculate coherence as cross spectral density divided by L*R power spectrum */ + // hStereoDft->Spd_L_smooth[i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->Spd_L_smooth[i] + cng_xcorr_filt * Spd_L[i]; + hStereoDft->Spd_L_smooth_fx[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->Spd_L_smooth_fx[i] ), Spd_L_smooth_fx_tmp_e[i], + Mpy_32_32( cng_xcorr_filt, Spd_L[i] ), Spd_L_e[i], &Spd_L_smooth_fx_tmp_e[i] ); + move32(); + hStereoDft->Spd_R_smooth_fx[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->Spd_R_smooth_fx[i] ), Spd_R_smooth_fx_tmp_e[i], + Mpy_32_32( cng_xcorr_filt, Spd_R[i] ), Spd_R_e[i], &Spd_R_smooth_fx_tmp_e[i] ); + move32(); + } + } + ELSE IF( vad_flag_dtx[0] == 0 ) + { + hStereoDft->resetFrames = 0; + move16(); + } + ELSE + { + if ( LT_16( hStereoDft->resetFrames, CORR_RESET_FRAMES_MAX + 1 ) ) + { + hStereoDft->resetFrames = add( hStereoDft->resetFrames, 1 ); + move16(); + } + test(); + if ( !vad_hover_flag[0] && !vad_hover_flag[1] ) + { + hStereoDft->expectedNumUpdates = hStereoDft->currentNumUpdates; + move16(); + } + } + } + IF( ( vad_flag_dtx[0] == 0 ) || ( hCPE->hFrontVad[0] == NULL && ( EQ_32( hCPE->hCoreCoder[0]->last_core_brate, SID_2k40 ) || EQ_32( hCPE->hCoreCoder[0]->last_core_brate, FRAME_NO_DATA ) ) ) || hCPE->hStereoCng->first_SID_after_TD ) + { + IF( vad_flag_dtx[0] == 0 ) + { + /* expectedNumUpdates updated after call to dtx() in SID frames */ + // cng_xcorr_filt = max( min( CORR_FILT, 10.0f * CORR_FILT / ( hStereoDft->expectedNumUpdates + hStereoDft->currentNumUpdates ) ), sfm_L ); + IF( add( hStereoDft->expectedNumUpdates, hStereoDft->currentNumUpdates ) != 0 ) + { + cng_xcorr_filt = BASOP_Util_Divide3232_Scale_cadence( 8 /*10.0f * CORR_FILT*/, add( hStereoDft->expectedNumUpdates, hStereoDft->currentNumUpdates ), &cng_xcorr_filt_e ); + cng_xcorr_filt = L_shl_sat( cng_xcorr_filt, cng_xcorr_filt_e ); // Q31 + cng_xcorr_filt = L_max( L_min( CORR_FILT_Q31, cng_xcorr_filt ), sfm_L ); // Q31 + } + ELSE + { + cng_xcorr_filt = CORR_FILT_Q31; + move32(); + cng_xcorr_filt = L_max( cng_xcorr_filt, sfm_L ); // Q31 + } + hStereoDft->currentNumUpdates = add( hStereoDft->currentNumUpdates, 1 ); + move16(); + hStereoDft->sfm_fx = cng_xcorr_filt; + move32(); + } + ELSE /* use sfm for active frames */ + { + cng_xcorr_filt = sfm_L; // Q31 + move32(); + } + + /* Copy state of xspec_smooth to xcorr_smooth in first CNG frame */ + test(); + IF( hCPE->hStereoCng->cng_counter == 0 && vad_flag_dtx[0] == 0 ) + { + // mvr2r( hStereoDft->xspec_smooth, hItd->xcorr_smooth, NFFT ); + Copy32( hStereoDft->xspec_smooth_fx, hItd->xcorr_smooth_fx, NFFT ); + Copy( xspec_smooth_fx_tmp_e, xcorr_smooth_fx_tmp_e, NFFT ); + } + FOR( i = 1; i < NFFT / 2; i++ ) + { + /* Low pass filter cross L/R power spectrum */ + // hStereoDft->xspec_smooth[2 * i] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i] + XSPEC_ALPHA * xcorr[2 * i]; + hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i] ), xspec_smooth_fx_tmp_e[2 * i], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i] ), xcorr_e[2 * i], &xspec_smooth_fx_tmp_e[2 * i] ); + move32(); + // hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i + 1] + XSPEC_ALPHA * xcorr[2 * i + 1]; + hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), xspec_smooth_fx_tmp_e[2 * i + 1], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xspec_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + // hItd->xcorr_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hItd->xcorr_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; + hItd->xcorr_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hItd->xcorr_smooth_fx[2 * i] ), xcorr_smooth_fx_tmp_e[2 * i], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i] ), xcorr_e[2 * i], &xcorr_smooth_fx_tmp_e[2 * i] ); + move32(); + // hItd->xcorr_smooth[2 * i + 1] = ( 1.f - cng_xcorr_filt ) * hItd->xcorr_smooth[2 * i + 1] + cng_xcorr_filt * xcorr[2 * i + 1]; + hItd->xcorr_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hItd->xcorr_smooth_fx[2 * i + 1] ), xcorr_smooth_fx_tmp_e[2 * i + 1], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xcorr_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + // tmpf1 = sqrtf( hItd->xcorr_smooth[i * 2] * hItd->xcorr_smooth[i * 2] + hItd->xcorr_smooth[i * 2 + 1] * hItd->xcorr_smooth[i * 2 + 1] ); + L_temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hItd->xcorr_smooth_fx[i * 2], hItd->xcorr_smooth_fx[i * 2] ), shl( xcorr_smooth_fx_tmp_e[2 * i], 1 ), + Mpy_32_32( hItd->xcorr_smooth_fx[i * 2 + 1], hItd->xcorr_smooth_fx[i * 2 + 1] ), shl( xcorr_smooth_fx_tmp_e[i * 2 + 1], 1 ), &L_temp_e ); + L_temp = Sqrt32( L_temp, &L_temp_e ); + // tmpf1 += EPSILON; + tmpf1 = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, EPSILON_FX_M, EPSILON_FX_E, &tmpf1_e ); + tmpf2 = tmpf1; + tmpf2_e = tmpf1_e; + // tmpf1 = powf( tmpf1, alpha ); + tmpf1 = BASOP_Util_fPow( tmpf1, tmpf1_e, alpha, 0, &tmpf1_e ); + // tmpf3 += tmpf2 * tmpf1; + tmpf3 = BASOP_Util_Add_Mant32Exp( tmpf3, tmpf3_e, Mpy_32_32( tmpf2, tmpf1 ), add( tmpf2_e, tmpf1_e ), &tmpf3_e ); + // xcorr[2 * i] = hItd->xcorr_smooth[2 * i] * tmpf1; + xcorr[2 * i] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i], tmpf1 ); + move32(); + xcorr_e[2 * i] = add( xcorr_smooth_fx_tmp_e[2 * i], tmpf1_e ); + move16(); + // xcorr[2 * i + 1] = hItd->xcorr_smooth[2 * i + 1] * tmpf1; + xcorr[2 * i + 1] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i + 1], tmpf1 ); + move32(); + xcorr_e[2 * i + 1] = add( xcorr_smooth_fx_tmp_e[2 * i + 1], tmpf1_e ); + move16(); + + /* Low pass filter L/R power spectrum */ + /* Calculate coherence as cross spectral density divided by L*R power spectrum */ + // hStereoDft->Spd_L_smooth[i] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->Spd_L_smooth[i] + XSPEC_ALPHA * Spd_L[i]; + hStereoDft->Spd_L_smooth_fx[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->Spd_L_smooth_fx[i] ), Spd_L_smooth_fx_tmp_e[i], + Mpy_32_32( XSPEC_ALPHA_Q31, Spd_L[i] ), Spd_L_e[i], &Spd_L_smooth_fx_tmp_e[i] ); + move32(); + // hStereoDft->Spd_R_smooth[i] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->Spd_R_smooth[i] + XSPEC_ALPHA * Spd_R[i]; + hStereoDft->Spd_R_smooth_fx[i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->Spd_R_smooth_fx[i] ), Spd_R_smooth_fx_tmp_e[i], + Mpy_32_32( XSPEC_ALPHA_Q31, Spd_R[i] ), Spd_R_e[i], &Spd_R_smooth_fx_tmp_e[i] ); + move32(); + } + } + ELSE + { + FOR( i = 1; i < NFFT / 2; i++ ) + { + // hItd->xcorr_smooth[2 * i] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i] + sfm_L * xcorr[2 * i]; + hItd->xcorr_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm_L ), hItd->xcorr_smooth_fx[2 * i] ), xcorr_smooth_fx_tmp_e[2 * i], + Mpy_32_32( sfm_L, xcorr[2 * i] ), xcorr_e[2 * i], &xcorr_smooth_fx_tmp_e[2 * i] ); + move32(); + // hItd->xcorr_smooth[2 * i + 1] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i + 1] + sfm_L * xcorr[2 * i + 1]; + hItd->xcorr_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm_L ), hItd->xcorr_smooth_fx[2 * i + 1] ), xcorr_smooth_fx_tmp_e[2 * i + 1], + Mpy_32_32( sfm_L, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xcorr_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + // tmpf1 = sqrtf( hItd->xcorr_smooth[i * 2] * hItd->xcorr_smooth[i * 2] + hItd->xcorr_smooth[i * 2 + 1] * hItd->xcorr_smooth[i * 2 + 1] ); + L_temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hItd->xcorr_smooth_fx[i * 2], hItd->xcorr_smooth_fx[i * 2] ), shl( xcorr_smooth_fx_tmp_e[2 * i], 1 ), + Mpy_32_32( hItd->xcorr_smooth_fx[i * 2 + 1], hItd->xcorr_smooth_fx[i * 2 + 1] ), shl( xcorr_smooth_fx_tmp_e[i * 2 + 1], 1 ), &L_temp_e ); + L_temp = Sqrt32( L_temp, &L_temp_e ); + // tmpf1 += EPSILON; + tmpf1 = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, EPSILON_FX_M, EPSILON_FX_E, &tmpf1_e ); + tmpf2 = tmpf1; + tmpf2_e = tmpf1_e; + // tmpf1 = powf( tmpf1, alpha ); + tmpf1 = BASOP_Util_fPow( tmpf1, tmpf1_e, alpha, 0, &tmpf1_e ); + // tmpf3 += tmpf2 * tmpf1; + tmpf3 = BASOP_Util_Add_Mant32Exp( tmpf3, tmpf3_e, Mpy_32_32( tmpf2, tmpf1 ), add( tmpf2_e, tmpf1_e ), &tmpf3_e ); + // xcorr[2 * i] = hItd->xcorr_smooth[2 * i] * tmpf1; + xcorr[2 * i] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i], tmpf1 ); + move32(); + xcorr_e[2 * i] = add( xcorr_smooth_fx_tmp_e[2 * i], tmpf1_e ); + move16(); + // xcorr[2 * i + 1] = hItd->xcorr_smooth[2 * i + 1] * tmpf1; + xcorr[2 * i + 1] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i + 1], tmpf1 ); + move32(); + xcorr_e[2 * i + 1] = add( xcorr_smooth_fx_tmp_e[2 * i + 1], tmpf1_e ); + move16(); + } + } + + /* RESCALING TO COMMON EXP */ + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + max_exp = s_max( max_exp, xspec_smooth_fx_tmp_e[i] ); + } + hStereoDft->xspec_smooth_fx_e = max_exp; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + hStereoDft->xspec_smooth_fx[i] = L_shr_r( hStereoDft->xspec_smooth_fx[i], sub( hStereoDft->xspec_smooth_fx_e, xspec_smooth_fx_tmp_e[i] ) ); + move32(); + } + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 2; i++ ) + { + max_exp = s_max( max_exp, Spd_L_smooth_fx_tmp_e[i] ); + } + hStereoDft->Spd_L_smooth_fx_e = max_exp; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 2; i++ ) + { + hStereoDft->Spd_L_smooth_fx[i] = L_shr_r( hStereoDft->Spd_L_smooth_fx[i], sub( hStereoDft->Spd_L_smooth_fx_e, Spd_L_smooth_fx_tmp_e[i] ) ); + move32(); + } + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 2; i++ ) + { + max_exp = s_max( max_exp, Spd_R_smooth_fx_tmp_e[i] ); + } + hStereoDft->Spd_R_smooth_fx_e = max_exp; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 2; i++ ) + { + hStereoDft->Spd_R_smooth_fx[i] = L_shr_r( hStereoDft->Spd_R_smooth_fx[i], sub( hStereoDft->Spd_R_smooth_fx_e, Spd_R_smooth_fx_tmp_e[i] ) ); + move32(); + } + /* END */ + } + ELSE + { + FOR( i = 1; i < shr( NFFT, 1 ); i++ ) + { + // hItd->xcorr_smooth[2 * i] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i] + sfm_L * xcorr[2 * i]; + hItd->xcorr_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm_L ), hItd->xcorr_smooth_fx[2 * i] ), xcorr_smooth_fx_tmp_e[2 * i], + Mpy_32_32( sfm_L, xcorr[2 * i] ), xcorr_e[2 * i], &xcorr_smooth_fx_tmp_e[2 * i] ); + move32(); + // hItd->xcorr_smooth[2 * i + 1] = ( 1.f - sfm_L ) * hItd->xcorr_smooth[2 * i + 1] + sfm_L * xcorr[2 * i + 1]; + hItd->xcorr_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, sfm_L ), hItd->xcorr_smooth_fx[2 * i + 1] ), xcorr_smooth_fx_tmp_e[2 * i + 1], + Mpy_32_32( sfm_L, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xcorr_smooth_fx_tmp_e[2 * i + 1] ); + move32(); + // tmpf1 = sqrtf( hItd->xcorr_smooth[i * 2] * hItd->xcorr_smooth[i * 2] + hItd->xcorr_smooth[i * 2 + 1] * hItd->xcorr_smooth[i * 2 + 1] ); + L_temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hItd->xcorr_smooth_fx[i * 2], hItd->xcorr_smooth_fx[i * 2] ), shl( xcorr_smooth_fx_tmp_e[2 * i], 1 ), + Mpy_32_32( hItd->xcorr_smooth_fx[i * 2 + 1], hItd->xcorr_smooth_fx[i * 2 + 1] ), shl( xcorr_smooth_fx_tmp_e[i * 2 + 1], 1 ), &L_temp_e ); + L_temp = Sqrt32( L_temp, &L_temp_e ); + // tmpf1 += EPSILON; + tmpf1 = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, EPSILON_FX_M, EPSILON_FX_E, &tmpf1_e ); + tmpf2 = tmpf1; + tmpf2_e = tmpf1_e; + // tmpf1 = powf( tmpf1, alpha ); + tmpf1 = BASOP_Util_fPow( tmpf1, tmpf1_e, alpha, 0, &tmpf1_e ); + // tmpf3 += tmpf2 * tmpf1; + tmpf3 = BASOP_Util_Add_Mant32Exp( tmpf3, tmpf3_e, Mpy_32_32( tmpf2, tmpf1 ), add( tmpf2_e, tmpf1_e ), &tmpf3_e ); + // xcorr[2 * i] = hItd->xcorr_smooth[2 * i] * tmpf1; + xcorr[2 * i] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i], tmpf1 ); + move32(); + xcorr_e[2 * i] = add( xcorr_smooth_fx_tmp_e[2 * i], tmpf1_e ); + move16(); + // xcorr[2 * i + 1] = hItd->xcorr_smooth[2 * i + 1] * tmpf1; + xcorr[2 * i + 1] = Mpy_32_32( hItd->xcorr_smooth_fx[2 * i + 1], tmpf1 ); + move32(); + xcorr_e[2 * i + 1] = add( xcorr_smooth_fx_tmp_e[2 * i + 1], tmpf1_e ); + move16(); + } + } + + // tmpf1 = (float) ( NFFT / 2 + 1 ) / tmpf3; + tmpf1 = BASOP_Util_Divide3232_Scale_cadence( add( shr( NFFT, 1 ), 1 ), tmpf3, &tmpf1_e ); + tmpf1_e = add( tmpf1_e, sub( 31, tmpf3_e ) ); + FOR( i = 0; i < NFFT; i++ ) + { + // xcorr[i] *= tmpf1; + xcorr[i] = Mpy_32_32( xcorr[i], tmpf1 ); + move32(); + xcorr_e[i] = add( xcorr_e[i], tmpf1_e ); + move16(); + } + + /* RESCALING TO COMMON EXP */ + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + max_exp = s_max( max_exp, xcorr_smooth_fx_tmp_e[i] ); + } + hItd->xcorr_smooth_fx_e = max_exp; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + hItd->xcorr_smooth_fx[i] = L_shr_r( hItd->xcorr_smooth_fx[i], sub( hItd->xcorr_smooth_fx_e, xcorr_smooth_fx_tmp_e[i] ) ); + move32(); + } + max_exp = 0; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + max_exp = s_max( max_exp, xcorr_e[i] ); + } + // xcorr_e_final = add( max_exp, 11 /*find_guarded_bits_fx( STEREO_DFT_N_32k_ENC ) */ ); + xcorr_e_final = max_exp; + move16(); + FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + xcorr[i] = L_shr_r( xcorr[i], sub( xcorr_e_final, xcorr_e[i] ) ); // xcorr_e_final + move32(); + } + /* END */ + + /*calculate mean E ratio of main to background signal for cohSNR*/ + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + mEr = calc_mean_E_ratio_fx( hItd, hStereoDft->nbands, hStereoDft->band_limits, sfm_L, pNrgL, pNrgL_e, pNrgR, pNrgR_e, &total_mEr, &total_mEr_e, &mEr_e ); + } + ELSE + { + Word16 nbands; + Word16 band_limits[STEREO_DFT_BAND_MAX + 1]; + + set16_fx( band_limits, 0, STEREO_DFT_BAND_MAX + 1 ); + set_band_limits_fx( &nbands, band_limits, hCPE->hStereoMdct->hDft_ana->NFFT ); + mEr = calc_mean_E_ratio_fx( hItd, nbands, band_limits, sfm_L, pNrgL, pNrgL_e, pNrgR, pNrgR_e, &total_mEr, &total_mEr_e, &mEr_e ); + } + + /*calculate total cohSNR for frame in dB*/ + // THIS PART NEEDS TO BE RECHECKED AGAINST NEW FLOAT CODE + // cohSNR = 20 * log10f( mEr ); + Word16 NAN_flag; + if ( mEr < 0 ) + { + cohSNR = 0; + NAN_flag = 1; + } + else + { + cohSNR = Mpy_32_32( 83886080, BASOP_Util_Log10( mEr, mEr_e ) ); // Q16 + NAN_flag = 0; + } + + /* collect UNCLR classifier parameters */ + { + Word32 es_em, d_prodL_prodR; + Word16 es_em_e, d_prodL_prodR_e; + + IF( BASOP_Util_Cmp_Mant32Exp( total_mEr, total_mEr_e, 1, 31 ) < 0 ) + { + hStereoClassif->unclr_fv_fx[E_cohSNR] = 0; + move32(); + } + ELSE + { + hStereoClassif->unclr_fv_fx[E_cohSNR] = Mpy_32_32( 41943040 /*20 in Q21*/, BASOP_Util_Log10( total_mEr, total_mEr_e ) ); // Q16 + move32(); + } + + // es_em = fabsf( sum_nrg_L - sum_nrg_R ) / ( sum_nrg_L + sum_nrg_R + 1e-5f ); + L_temp = L_abs( BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, L_negate( sum_nrg_R ), sum_nrg_R_e, &L_temp_e ) ); + L_temp2 = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, sum_nrg_R, sum_nrg_R_e, &L_temp2_e ); + L_temp2 = BASOP_Util_Add_Mant32Exp( L_temp2, L_temp2_e, 1407374883, -16, &L_temp2_e ); + es_em = BASOP_Util_Divide3232_Scale_cadence( L_temp, L_temp2, &es_em_e ); + es_em_e = add( es_em_e, sub( L_temp_e, L_temp2_e ) ); + + hStereoClassif->unclr_fv_fx[E_es_em] = L_shr_r( es_em, sub( 16, es_em_e ) ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_es_em] = L_shr_r( es_em, sub( 16, es_em_e ) ); // Q15 + move32(); + + // d_prodL_prodR = logf( max( prod_LL, prod_RR ) / ( min( prod_LL, prod_RR ) + 1e-5f ) + 1.0f ); + IF( BASOP_Util_Cmp_Mant32Exp( prod_LL, prod_LL_e, prod_RR, prod_RR_e ) > 0 ) + { + L_temp = prod_LL; + move32(); + L_temp_e = prod_LL_e; + move16(); + L_temp2 = prod_RR; + move32(); + L_temp2_e = prod_RR_e; + move16(); + } + ELSE + { + L_temp = prod_RR; + move32(); + L_temp_e = prod_RR_e; + move16(); + L_temp2 = prod_LL; + move32(); + L_temp2_e = prod_LL_e; + move16(); + } + L_temp2 = BASOP_Util_Add_Mant32Exp( L_temp2, L_temp2_e, 1407374883, -16, &L_temp2_e ); + d_prodL_prodR = BASOP_Util_Divide3232_Scale_cadence( L_temp, L_temp2, &d_prodL_prodR_e ); + d_prodL_prodR_e = add( d_prodL_prodR_e, sub( L_temp_e, L_temp2_e ) ); + d_prodL_prodR = BASOP_Util_Add_Mant32Exp( d_prodL_prodR, d_prodL_prodR_e, MAX_32, 0, &d_prodL_prodR_e ); + d_prodL_prodR = BASOP_Util_Loge( d_prodL_prodR, d_prodL_prodR_e ); // Q25 + + hStereoClassif->unclr_fv_fx[E_d_prodL_prodR] = L_shr_r( d_prodL_prodR, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_d_prodL_prodR] = L_shr_r( d_prodL_prodR, 10 ); // Q15 + move32(); + + sum_xcorr = 0; + move32(); + sum_xcorr_e = 0; + move16(); + for ( i = 1; i < NFFT_mid; i++ ) + { + // xcorr_abs[i] = logf( xcorr_abs[i] / ( sum_nrg_L + sum_nrg_R + 1e-5f ) + 1e-5f ); + L_temp = BASOP_Util_Add_Mant32Exp( sum_nrg_L, sum_nrg_L_e, sum_nrg_R, sum_nrg_R_e, &L_temp_e ); + L_temp = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, 1407374883, -16, &L_temp_e ); + L_temp2 = BASOP_Util_Divide3232_Scale_cadence( xcorr_abs[i], L_temp, &L_temp2_e ); + L_temp2_e = add( L_temp2_e, sub( xcorr_abs_e[i], L_temp_e ) ); + L_temp2 = BASOP_Util_Add_Mant32Exp( L_temp2, L_temp2_e, 1407374883, -16, &L_temp2_e ); + xcorr_abs[i] = BASOP_Util_Loge( L_temp2, L_temp2_e ); + move32(); + xcorr_abs_e[i] = 6; + move16(); + + // sum_xcorr += xcorr_abs[i]; + sum_xcorr = BASOP_Util_Add_Mant32Exp( sum_xcorr, sum_xcorr_e, xcorr_abs[i], xcorr_abs_e[i], &sum_xcorr_e ); + } + + hStereoClassif->unclr_fv_fx[E_sum_xcorr] = L_shr_r( sum_xcorr, sub( 16, sum_xcorr_e ) ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_sum_xcorr] = L_shr_r( sum_xcorr, sub( 16, sum_xcorr_e ) ); // Q15 + move32(); + } + + /* reset estimates when silence is detected*/ + // if ( ( sum_nrg_L && sum_nrg_R ) < EPSILON ) + IF( ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_L, sum_nrg_L_e, 0, 0 ) == 0 ) && ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_R, sum_nrg_R_e, 0, 0 ) == 0 ) ) + { + resetEstimates_fx( hItd ); + } + + /*smooth cohSNR with time */ + // if ( ( hItd->cohSNR - cohSNR ) < 10.0f ) + IF( LT_32( L_sub( hItd->cohSNR_fx, cohSNR ), 655360 ) && !NAN_flag ) + { + // tmpf1 = max( 0.05f, min( 0.25f, sfm_L * 0.5f ) ); + tmpf1 = L_max( 107374182, L_min( ONE_IN_Q29, L_shr( sfm_L, 1 ) ) ); + // hItd->cohSNR = ( 1.f - tmpf1 ) * hItd->cohSNR + tmpf1 * cohSNR; + hItd->cohSNR_fx = L_add( Mpy_32_32( L_sub( MAX_32, tmpf1 ), hItd->cohSNR_fx ), Mpy_32_32( tmpf1, cohSNR ) ); + move32(); + } + ELSE + { + // hItd->cohSNR = hItd->cohSNR - 0.05f; + hItd->cohSNR_fx = L_sub( hItd->cohSNR_fx, 3277 ); + move32(); + } + + cohSNR = hItd->cohSNR_fx; + move32(); + + // rfft( xcorr, trigo_enc, STEREO_DFT_N_32k_ENC, +1 ); + Scale_sig32( xcorr, STEREO_DFT_N_32k_ENC, negate( find_guarded_bits_fx( STEREO_DFT_N_32k_ENC ) ) ); + rfft_fx( xcorr, trigo_enc, STEREO_DFT_N_32k_ENC, +1 ); + Scale_sig32( xcorr, STEREO_DFT_N_32k_ENC, add( find_guarded_bits_fx( STEREO_DFT_N_32k_ENC ), xcorr_e_final ) ); // Q31 + + itd_td = hItd->td_itd_32k[k_offset]; /* This ITD always operates at 32kHz*/ + move32(); + shift = sub( STEREO_DFT_N_32k_ENC / 2, itd_td ) % STEREO_DFT_N_32k_ENC; + split = sub( STEREO_DFT_N_32k_ENC, shift ); + + Copy32( &xcorr[0], &xcorr_itd[shift], split ); // xcorr_e_final + Copy32( &xcorr[split], &xcorr_itd[0], shift ); // xcorr_e_final + + Copy32( &xcorr_itd[STEREO_DFT_N_32k_ENC / 2 - XTALK_PHAT_LEN], gcc_phat, 2 * XTALK_PHAT_LEN + 1 ); // xcorr_e_final + + + thres = peak_detect_fx( xcorr_itd, &tmpf1, &index, &zero_itd, cohSNR, hCPE->hCoreCoder[0]->vad_flag, &second_max, &second_max_lag, hItd->prev_itd, flag_noisy_speech_snr, hItd->detected_itd_flag, &hItd->prev_max_fx, &hItd->prev_index, &hItd->prev_avg_max_fx, &hItd->prev_avg_max_fx_e, &total_max, &thres_e ); + tmpf1_e = 0; + move16(); + + // hStereoClassif->ave_ener_L = sum_nrg_L / ( NFFT_mid * NFFT_mid ); + hStereoClassif->ave_ener_L_fx = BASOP_Util_Divide3232_Scale_cadence( sum_nrg_L, L_mult0( NFFT_mid, NFFT_mid ), &hStereoClassif->ave_ener_L_fx_e ); + move32(); + hStereoClassif->ave_ener_L_fx_e = add( hStereoClassif->ave_ener_L_fx_e, sub( sum_nrg_L_e, 31 ) ); + move16(); + // hStereoClassif->ave_ener_R = sum_nrg_R / ( NFFT_mid * NFFT_mid ); + hStereoClassif->ave_ener_R_fx = BASOP_Util_Divide3232_Scale_cadence( sum_nrg_R, L_mult0( NFFT_mid, NFFT_mid ), &hStereoClassif->ave_ener_R_fx_e ); + move32(); + hStereoClassif->ave_ener_R_fx_e = add( hStereoClassif->ave_ener_R_fx_e, sub( sum_nrg_R_e, 31 ) ); + move16(); + + IF( EQ_32( hCPE->hCoreCoder[0]->input_Fs, 16000 ) ) + { + // total_max *= 2.0f; + total_max = L_shl_sat( total_max, 1 ); // should be rechecked for -10dB tests + } + // hStereoClassif->unclr_fv[E_xcorr_itd_value] = total_max; + hStereoClassif->unclr_fv_fx[E_xcorr_itd_value] = L_shr_r( total_max, 16 - 0 ); // Q15 + move16(); + // hStereoClassif->xtalk_fv[E_xcorr_itd_value] = total_max; + hStereoClassif->xtalk_fv_fx[E_xcorr_itd_value] = hStereoClassif->unclr_fv_fx[E_xcorr_itd_value]; + move16(); + + + /*for tonal music items increase thresholing by a factor up to 2.*/ + // if ( hCPE->hCoreCoder[0]->sp_aud_decision0 && ( index - STEREO_DFT_ITD_MAX_ANA ) != hItd->prev_itd && !flag_noisy_speech_snr && hCPE->hCoreCoder[0]->vad_flag && tmpf1 < 0.3 ) + test(); + test(); + test(); + test(); + IF( hCPE->hCoreCoder[0]->sp_aud_decision0 && sub( index, STEREO_DFT_ITD_MAX_ANA ) != hItd->prev_itd && !flag_noisy_speech_snr && hCPE->hCoreCoder[0]->vad_flag && LT_32( tmpf1, 644245094 ) ) + { + // thres *= 1.0f + 1.f * min( 1.f, max( 0.f, ( -1.0f * sfm_L + 0.5f ) / ( 0.5f - 0.2f ) ) ); + L_temp = BASOP_Util_Add_Mant32Exp( L_negate( sfm_L ), 0, ONE_IN_Q30, 0, &L_temp_e ); + L_temp2 = BASOP_Util_Divide3232_Scale_cadence( L_temp, 644245094, &L_temp2_e ); + L_temp2_e = add( L_temp2_e, L_temp_e - 0 ); + L_temp2 = L_shl_sat( L_temp2, sub( L_temp2_e, 1 ) ); // Q30 + L_temp2_e = 1; + L_temp2 = L_min( ONE_IN_Q30, L_max( 0, L_temp2 ) ); + L_temp2 = L_add_sat( ONE_IN_Q30, L_temp2 ); // Q30 + thres = Mpy_32_32( thres, L_temp2 ); + thres_e = add( thres_e, L_temp2_e ); + } + thres = L_shl_sat( thres, thres_e ); // Q31 - should be rechecked for -10dB tests + + itd_cal_flag = 0; + move16(); + /*smooth threshold value depending on sfm for music items*/ + // if ( hCPE->hCoreCoder[0]->ini_frame == 0 || hCPE->last_element_mode != IVAS_CPE_DFT || !hCPE->hCoreCoder[0]->sp_aud_decision0 || flag_noisy_speech_snr || cohSNR < 20 ) + test(); + test(); + test(); + test(); + IF( hCPE->hCoreCoder[0]->ini_frame == 0 || hCPE->last_element_mode != IVAS_CPE_DFT || !hCPE->hCoreCoder[0]->sp_aud_decision0 || flag_noisy_speech_snr || BASOP_Util_Cmp_Mant32Exp( cohSNR, 15, 20, 31 ) < 0 ) + { + hItd->itd_thres_fx = thres; + move32(); + } + ELSE + { + // hItd->itd_thres = ( 1.0f - sfm_L ) * hItd->itd_thres + sfm_L * thres; + hItd->itd_thres_fx = L_add( Mpy_32_32( L_sub( MAX_32, sfm_L ), hItd->itd_thres_fx ), Mpy_32_32( sfm_L, thres ) ); + move32(); + } + + // if ( flag_noisy_speech_snr == 0 && hCPE->hCoreCoder[0]->vad_flag == 1 && hItd->detected_itd_flag == 0 && ( hItd->currFlatness < 1.5f || hCPE->hCoreCoder[0]->sp_aud_decision0 == 1 ) ) + test(); + test(); + test(); + test(); + IF( flag_noisy_speech_snr == 0 && hCPE->hCoreCoder[0]->vad_flag == 1 && hItd->detected_itd_flag == 0 && ( BASOP_Util_Cmp_Mant32Exp( hItd->currFlatness_fx, hItd->currFlatness_fx_e, 1610612736, 1 ) < 0 || hCPE->hCoreCoder[0]->sp_aud_decision0 == 1 ) ) + { + // hItd->itd_thres *= 1.5f; + hItd->itd_thres_fx = L_shl_sat( Mpy_32_32( hItd->itd_thres_fx, 1610612736 ), 1 ); /* Saturation added to avoid assertions (this needs to be investigated) */ + move32(); + } + test(); + IF( hCPE->hCoreCoder[0]->vad_flag == 0 || hItd->detected_itd_flag == 0 ) + { + hItd->itd_tracking = 0; + move16(); + } + ELSE IF( GT_16( abs_s( hItd->prev_itd ), 2 ) ) + { + hItd->itd_tracking = 1; + move16(); + } + + // if ( hItd->itd_tracking == 1 && ( second_max > hItd->itd_thres || tmpf1 - second_max < min( tmpf1 * 0.5f, 0.2f ) ) ) + test(); + test(); + if ( EQ_16( hItd->itd_tracking, 1 ) && ( GT_32( second_max, hItd->itd_thres_fx ) || LT_32( L_sub( tmpf1, second_max ), L_min( L_shr( tmpf1, 1 ), 429496730 ) ) ) ) + { + index = second_max_lag; + move16(); + } + + // if ( hItd->itd_tracking == 1 && abs( hItd->prev_itd - ( index - STEREO_DFT_ITD_MAX_ANA ) ) <= max( 2, (int16_t) round_f( abs( hItd->prev_itd ) / 16.f ) ) ) + test(); + if ( hItd->itd_tracking == 1 && abs_s( sub( hItd->prev_itd, sub( index, STEREO_DFT_ITD_MAX_ANA ) ) ) <= s_max( 2, shr_r( abs_s( hItd->prev_itd ), 4 ) ) ) + { + // hItd->itd_thres *= 0.75f; + hItd->itd_thres_fx = Mpy_32_32( hItd->itd_thres_fx, 1610612736 ); + move32(); + } + + // if ( tmpf1 > hItd->itd_thres && !zero_itd ) + test(); + IF( GT_32( tmpf1, hItd->itd_thres_fx ) && !zero_itd ) + { + /* LP filter GCC PHAT peak to follow peak envelope */ + IF( GT_32( tmpf1, hItd->lp_phat_peak_fx ) ) + { + alpha = LP_GCC_PHAT_UP_Q31; + move32(); + } + ELSE + { + alpha = LP_GCC_PHAT_DOWN_Q31; + move32(); + } + // hItd->lp_phat_peak = alpha * tmpf1 + ( 1 - alpha ) * hItd->lp_phat_peak; + hItd->lp_phat_peak_fx = L_add( Mpy_32_32( alpha, tmpf1 ), Mpy_32_32( L_sub( MAX_32, alpha ), hItd->lp_phat_peak_fx ) ); + move32(); + hItd->itd_cnt = add( hItd->itd_cnt, 1 ); + move16(); + test(); + if ( GT_16( hItd->itd_cnt, ITD_CNT_MAX ) || hItd->itd_hangover > 0 ) + { + /* If max count is reached, or if an ITD candidate is found during hangover, + set itd_cnt = ITD_CNT_MAX to ensure hangover is applied */ + hItd->itd_cnt = ITD_CNT_MAX; + move16(); + } + hItd->itd_hangover = 0; + move16(); + + itd = sub( index, STEREO_DFT_ITD_MAX_ANA ); + hItd->itd_nonzero_cnt = 0; /* (1+0+9) <= hItd->itd_nonzero_cnt <= (1+6+3) */ + move16(); + itd_cal_flag = 1; /* Indicates P>T case */ + move16(); + hItd->valid_itd_cnt = hItd->itd_cnt; /* Store last non-zero value (when P>T) before reset */ + move16(); + hItd->detected_itd_flag = 1; + move16(); + } + ELSE + { + /* Set prev_itd hangover period */ + IF( EQ_16( hItd->itd_cnt, ITD_CNT_MAX ) ) + { + // hItd->itd_hangover = max( 0, min( ITD_HO_MAX, (int16_t) ( hItd->lp_phat_peak * ITD_HO_GCC_PHAT_INCL + ITD_HO_GCC_PHAT_OFFS ) ) ); + hItd->itd_hangover = s_max( 0, s_min( ITD_HO_MAX, extract_l( L_shr( L_add( Mpy_32_32( hItd->lp_phat_peak_fx, ITD_HO_GCC_PHAT_INCL_Q26 ), ITD_HO_GCC_PHAT_OFFS_Q26 ), 26 ) ) ) ); + move16(); + } + + IF( hItd->itd_hangover > 0 ) + { + itd = hItd->prev_itd; + move16(); + if ( LT_16( hItd->itd_nonzero_cnt, MAX_ITD_VAD_HANGOVER ) ) + { + hItd->itd_nonzero_cnt = add( hItd->itd_nonzero_cnt, 1 ); + move16(); + } + hItd->itd_hangover = sub( hItd->itd_hangover, 1 ); + move16(); + hItd->detected_itd_flag = 1; + move16(); + } + ELSE + { + itd = 0; + move16(); + hItd->detected_itd_flag = 0; + move16(); + } + + /* Reset */ + hItd->itd_cnt = 0; + move16(); + hItd->lp_phat_peak_fx = 0; + move16(); + } + + { + /* stereo Xtalk classifier */ + xtalk_classifier_dft_fx( hCPE, itd, gcc_phat ); + } + + /*avoid enabling ITD fine control for music*/ + test(); + test(); + IF( !hCPE->hCoreCoder[0]->sp_aud_decision0 || flag_noisy_speech_snr || LT_32( cohSNR, 20 << 16 ) ) + { + /* ITD fine control base on vad and correlation parameters */ + cor_lb_avrg = 0; + move32(); + par_L_avrg = 0; + move32(); + FOR( i = 0; i < XCORR_LB_NUM_BANDS; i++ ) + { + // num_cor = xcorr_lb[i * XCORR_LB_BAND_WIDTH] * hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH]; + num_cor = Mpy_32_32( xcorr_lb[i * XCORR_LB_BAND_WIDTH], hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH] ); + num_cor_e = add( xcorr_lb_e[i * XCORR_LB_BAND_WIDTH], hItd->prev_xcorr_lb_fx_e ); + // den_cor_cur = xcorr_lb[i * XCORR_LB_BAND_WIDTH] * xcorr_lb[i * XCORR_LB_BAND_WIDTH] + 1.0f; + den_cor_cur = BASOP_Util_Add_Mant32Exp( Mpy_32_32( xcorr_lb[i * XCORR_LB_BAND_WIDTH], xcorr_lb[i * XCORR_LB_BAND_WIDTH] ), shl( xcorr_lb_e[i * XCORR_LB_BAND_WIDTH], 1 ), MAX_32, 0, &den_cor_cur_e ); + // den_cor_prev = hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH] * hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH] + 1.0f; + W_temp = W_mult0_32_32( hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH], hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH] ); + W_temp_q = add( shl( sub( 31, hItd->prev_xcorr_lb_fx_e ), 1 ), W_norm( W_temp ) ); + W_temp = W_shl( W_temp, W_norm( W_temp ) ); + L_temp = W_extract_h( W_temp ); + L_temp_e = sub( 63, W_temp_q ); + + den_cor_prev = BASOP_Util_Add_Mant32Exp( L_temp, L_temp_e, MAX_32, 0, &den_cor_prev_e ); + xcorr_max = xcorr_lb[i * XCORR_LB_BAND_WIDTH]; + xcorr_max_e = xcorr_lb_e[i * XCORR_LB_BAND_WIDTH]; + sum_nrg_L_tmp = xcorr_lb[i * XCORR_LB_BAND_WIDTH]; + sum_nrg_L_tmp_e = xcorr_lb_e[i * XCORR_LB_BAND_WIDTH]; + FOR( j = 1; j < XCORR_LB_BAND_WIDTH; j++ ) + { + // num_cor += xcorr_lb[i * XCORR_LB_BAND_WIDTH + j] * hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH + j]; + num_cor = BASOP_Util_Add_Mant32Exp( num_cor, num_cor_e, Mpy_32_32( xcorr_lb[i * XCORR_LB_BAND_WIDTH + j], hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH + j] ), + add( xcorr_lb_e[i * XCORR_LB_BAND_WIDTH + j], hItd->prev_xcorr_lb_fx_e ), &num_cor_e ); + // den_cor_cur += xcorr_lb[i * XCORR_LB_BAND_WIDTH + j] * xcorr_lb[i * XCORR_LB_BAND_WIDTH + j]; + den_cor_cur = BASOP_Util_Add_Mant32Exp( den_cor_cur, den_cor_cur_e, Mpy_32_32( xcorr_lb[i * XCORR_LB_BAND_WIDTH + j], xcorr_lb[i * XCORR_LB_BAND_WIDTH + j] ), + shl( xcorr_lb_e[i * XCORR_LB_BAND_WIDTH + j], 1 ), &den_cor_cur_e ); + // den_cor_prev += hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH + j] * hItd->prev_xcorr_lb[i * XCORR_LB_BAND_WIDTH + j]; + den_cor_prev = BASOP_Util_Add_Mant32Exp( den_cor_prev, den_cor_prev_e, Mpy_32_32( hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH + j], hItd->prev_xcorr_lb_fx[i * XCORR_LB_BAND_WIDTH + j] ), + shl( hItd->prev_xcorr_lb_fx_e, 1 ), &den_cor_prev_e ); + // if ( xcorr_lb[i * XCORR_LB_BAND_WIDTH + j] > xcorr_max ) + IF( BASOP_Util_Cmp_Mant32Exp( xcorr_lb[i * XCORR_LB_BAND_WIDTH + j], xcorr_lb_e[i * XCORR_LB_BAND_WIDTH + j], xcorr_max, xcorr_max_e ) > 0 ) + { + xcorr_max = xcorr_lb[i * XCORR_LB_BAND_WIDTH + j]; + move32(); + xcorr_max_e = xcorr_lb_e[i * XCORR_LB_BAND_WIDTH + j]; + move16(); + } + // sum_nrg_L_tmp += xcorr_lb[i * XCORR_LB_BAND_WIDTH + j]; + sum_nrg_L_tmp = BASOP_Util_Add_Mant32Exp( sum_nrg_L_tmp, sum_nrg_L_tmp_e, xcorr_lb[i * XCORR_LB_BAND_WIDTH + j], xcorr_lb_e[i * XCORR_LB_BAND_WIDTH + j], &sum_nrg_L_tmp_e ); + } + // cor_lb[i] = num_cor / ( sqrtf( den_cor_cur ) * sqrtf( den_cor_prev ) ); + L_temp = Mpy_32_32( den_cor_cur, den_cor_prev ); + L_temp_e = add( den_cor_cur_e, den_cor_prev_e ); + L_temp = Sqrt32( L_temp, &L_temp_e ); + cor_lb[i] = BASOP_Util_Divide3232_Scale_cadence( num_cor, L_temp, &cor_lb_e[i] ); + move32(); + cor_lb_e[i] = add( cor_lb_e[i], sub( num_cor_e, L_temp_e ) ); + move16(); + cor_lb[i] = L_shl_sat( cor_lb[i], cor_lb_e[i] ); // Q31 + move32(); + // cor_lb_avrg += cor_lb[i]; + cor_lb_avrg = L_add( cor_lb_avrg, Mpy_32_32( cor_lb[i], ONE_BY_XCORR_LB_NUM_BANDS_Q31 ) ); + + // par_L[i] = xcorr_max / ( sum_nrg_L_tmp + FLT_MIN ); + IF( xcorr_max ) + { + par_L[i] = BASOP_Util_Divide3232_Scale_cadence( xcorr_max, sum_nrg_L_tmp, &par_L_e[i] ); + move32(); + par_L_e[i] = add( par_L_e[i], sub( xcorr_max_e, sum_nrg_L_tmp_e ) ); + move16(); + } + ELSE + { + par_L[i] = 0; + move32(); + par_L_e[i] = 0; + move16(); + } + par_L[i] = L_shl_sat( par_L[i], par_L_e[i] ); // Q31 + move32(); + // par_L_avrg += par_L[i]; + par_L_avrg = L_add( par_L_avrg, Mpy_32_32( par_L[i], ONE_BY_XCORR_LB_NUM_BANDS_Q31 ) ); + } + // cor_lb_avrg /= XCORR_LB_NUM_BANDS; + // par_L_avrg /= XCORR_LB_NUM_BANDS; + + /*Breakdown of fine-control conditions */ + // fc_condition_1 = abs( hItd->prev_itd ) > 0.2f * abs( itd ); + fc_condition_1 = (Word16) GT_16( abs_s( hItd->prev_itd ), mult( 6554 /*0.2f*/, abs_s( itd ) ) ); + // fc_condition_2 = cor_lb_avrg > 0.85f; + fc_condition_2 = (Word16) GT_32( cor_lb_avrg, 1825361101 /*0.85f*/ ); + // fc_condition_3 = ( cor_lb_avrg > 0.7f && ( cor_lb[0] > 0.9f || cor_lb[1] > 0.9f || cor_lb[2] > 0.9f ) && hItd->prev_sum_nrg_L_lb > 0.5f * sum_nrg_L_lb && hItd->prev_sum_nrg_L_lb < 2.0f * sum_nrg_L_lb ); + test(); + test(); + test(); + test(); + test(); + fc_condition_3 = (Word16) ( GT_32( cor_lb_avrg, 1503238554 /*0.7f*/ ) && ( GT_32( cor_lb[0], 1932735283 /*0.9f*/ ) || GT_32( cor_lb[1], 1932735283 /*0.9f*/ ) || GT_32( cor_lb[2], 1932735283 /*0.9f*/ ) ) && + BASOP_Util_Cmp_Mant32Exp( hItd->prev_sum_nrg_L_lb_fx, hItd->prev_sum_nrg_L_lb_fx_e, sum_nrg_L_lb, sub( sum_nrg_L_lb_e, 1 ) ) > 0 && BASOP_Util_Cmp_Mant32Exp( hItd->prev_sum_nrg_L_lb_fx, hItd->prev_sum_nrg_L_lb_fx_e, sum_nrg_L_lb, add( sum_nrg_L_lb_e, 1 ) ) < 0 ); + // fc_condition_4 = par_L_avrg > 0.6f; + fc_condition_4 = (Word16) GT_32( par_L_avrg, 1288490189 /*0.6f*/ ); + fc_condition_5 = hItd->prev_itd != 0; + fc_condition_6_a = L_mult0( itd, hItd->prev_itd ) < 0; /* ITD sign change */ + fc_condition_6_b = L_mult0( itd, hItd->prev_itd ) == 0; /* ITD jump to zero */ + // fc_condition_6_c = abs( itd - hItd->prev_itd ) > 0.5f * ( ( abs( itd ) > abs( hItd->prev_itd ) ) ? abs( itd ) : abs( hItd->prev_itd ) ); /* Magnitude of the ITD jump */ + fc_condition_6_c = (Word16) GT_16( abs_s( sub( itd, hItd->prev_itd ) ), shr( ( ( abs_s( itd ) > abs_s( hItd->prev_itd ) ) ? abs_s( itd ) : abs_s( hItd->prev_itd ) ), 1 ) ); /* Magnitude of the ITD jump */ + + /* Combining conditions 1,2,3,4 */ + test(); + test(); + test(); + fc_condition_1234 = fc_condition_1 && ( fc_condition_2 || fc_condition_3 || fc_condition_4 ); + + test(); + test(); + test(); + test(); + test(); + IF( ( fc_condition_1234 && ( ( fc_condition_5 && fc_condition_6_b ) || fc_condition_6_c ) ) || ( fc_condition_1234 && fc_condition_6_a ) ) + { + itd = hItd->prev_itd; + move16(); + + if ( LT_16( hItd->itd_nonzero_cnt, MAX_ITD_VAD_HANGOVER ) ) + { + hItd->itd_nonzero_cnt = add( hItd->itd_nonzero_cnt, 1 ); + move16(); + } + hItd->detected_itd_flag = 1; + move16(); + } + + /* stop the fine control when inactive or very high mssnr is detected*/ + // if ( mssnr < 6e-7f * HIGHT_SNR_VOICE_TH || mssnr > 200 * HIGHT_SNR_VOICE_TH ) + test(); + if ( BASOP_Util_Cmp_Mant32Exp( mssnr, mssnr_e, 12884902 /*6e-7f * HIGHT_SNR_VOICE_TH */, 0 ) < 0 || BASOP_Util_Cmp_Mant32Exp( mssnr, mssnr_e, 200 * HIGHT_SNR_VOICE_TH_FX, 31 ) > 0 ) + { + hItd->itd_nonzero_cnt = MAX_ITD_VAD_HANGOVER; + move16(); + } + + IF( vad_flag_itd ) + { + /* Fine-control for hangover if set HR period = 0 or if HR period expires */ + /* However fine-control shouldn't be used when HR is disabled because itd_cnt < 2 - hence the extra last condition */ + test(); + test(); + test(); + test(); + test(); + test(); + IF( hItd->itd_hangover == 0 && hItd->prev_itd != 0 && itd == 0 && NE_16( itd_cal_flag, 1 ) && LT_16( hItd->itd_nonzero_cnt, MAX_ITD_VAD_HANGOVER ) && EQ_16( hItd->valid_itd_cnt, ITD_CNT_MAX ) && EQ_16( hItd->pre_vad, 1 ) ) + { + itd = hItd->prev_itd; + move16(); + hItd->itd_nonzero_cnt = add( hItd->itd_nonzero_cnt, 1 ); + move16(); + hItd->detected_itd_flag = 1; + move16(); + } + hItd->pre_vad = 1; + move16(); + } + ELSE + { + hItd->pre_vad = 0; + move16(); + } + + test(); + if ( itd == 0 && NE_16( itd_cal_flag, 1 ) ) + { + hItd->itd_nonzero_cnt = 0; + move16(); + } + + hItd->prev_sum_nrg_L_lb_fx = sum_nrg_L_lb; + move32(); + hItd->prev_sum_nrg_L_lb_fx_e = sum_nrg_L_lb_e; + move16(); + // mvr2r( xcorr_lb, hItd->prev_xcorr_lb, STEREO_DFT_XCORR_LB_MAX ); + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_XCORR_LB_MAX; i++ ) + { + max_exp = s_max( max_exp, xcorr_lb_e[i] ); + } + FOR( i = 0; i < STEREO_DFT_XCORR_LB_MAX; i++ ) + { + hItd->prev_xcorr_lb_fx[i] = L_shr_r( xcorr_lb[i], sub( max_exp, xcorr_lb_e[i] ) ); + move32(); + } + hItd->prev_xcorr_lb_fx_e = max_exp; + move16(); + } + /*save previous flag*/ + prev_itd_max = hItd->hybrid_itd_max; + move16(); + /* enable hybrid ITD handling for very large ITDs*/ + hItd->hybrid_itd_max = ( abs( itd ) > STEREO_DFT_ITD_MAX && abs( itd ) < STEREO_DFT_ITD_MAX_ANA && !hCPE->hCoreCoder[0]->sp_aud_decision0 && hCPE->element_brate < IVAS_32k ); + move16(); + /* Update memory */ + hItd->prev_itd = itd; + move16(); + + itd = check_bounds_s_fx( itd, -STEREO_DFT_ITD_MAX, STEREO_DFT_ITD_MAX ); + + /*Inverse the time diff*/ + // hItd->itd[k_offset] = -1.f * itd; + hItd->itd_fx[k_offset] = L_deposit_h( imult1616( -1, itd ) ); // Q16 + move32(); + + /* collect UNCLR classifier parameters */ + hStereoClassif->unclr_fv_fx[E_ITD] = L_shr( hItd->itd_fx[k_offset], 1 ); // Q15 + move32(); + + + /* limit ITD range for MDCT stereo even more */ + test(); + if ( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && GT_32( L_abs( hItd->itd_fx[k_offset] ), ( ITD_MAX_MDCT << 16 ) ) ) + { + itd = 0; + move16(); + } + + stereo_dft_quantize_itd_fx( -1 * itd, hItd->itd_fx + k_offset, input_frame * FRAMES_PER_SEC, hItd->itd_index + k_offset ); + + // hItd->deltaItd[k_offset] = hItd->itd[k_offset] - hItd->td_itd[k_offset]; + hItd->deltaItd_fx[k_offset] = L_sub( hItd->itd_fx[k_offset], L_deposit_h( hItd->td_itd[k_offset] ) ); + move32(); + + IF( hItd->hybrid_itd_max ) + { + /*check if there is an ITD flip*/ + // itd_max_flip = ( hItd->itd[k_offset] * hItd->itd[k_offset - 1] < 0 ); + itd_max_flip = ( W_mult0_32_32( hItd->itd_fx[k_offset], hItd->itd_fx[k_offset - 1] ) < 0 ); + + test(); + IF( hItd->deltaItd_fx[k_offset - 1] != 0 && itd_max_flip == 0 ) + { + // int16_t tmp_itd2 = (int16_t) floorf( ( ( hItd->prev_itd ) * ( (float) input_frame / 640 ) ) + 0.5f ); + Word16 tmp_itd = extract_l( Mpy_32_32_r( L_mult0( hItd->prev_itd, input_frame ), 3355443 ) ); + // hItd->deltaItd[k_offset] = -1.0f * tmp_itd - hItd->td_itd[k_offset]; + hItd->deltaItd_fx[k_offset] = L_deposit_h( sub( imult1616( -1, tmp_itd ), hItd->td_itd[k_offset] ) ); + move32(); + } + } + /*signal change for next frame*/ + test(); + if ( EQ_16( prev_itd_max, 1 ) && hItd->hybrid_itd_max == 0 ) + { + hItd->hybrid_itd_max = -1; + move16(); + } + + + return; +} +#endif void stereo_dft_enc_compute_itd( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float *DFT_L, diff --git a/lib_enc/ivas_stereo_dft_td_itd.c b/lib_enc/ivas_stereo_dft_td_itd.c index 068883104da67c7fa22862f903798b17edc52d02..c3673647fab720a8e2caa61bba5fb46f6a0249f3 100644 --- a/lib_enc/ivas_stereo_dft_td_itd.c +++ b/lib_enc/ivas_stereo_dft_td_itd.c @@ -42,6 +42,8 @@ #include "ivas_stat_enc.h" #include "ivas_cnst.h" #include "wmc_auto.h" +#include "ivas_prot_fx.h" +#include "prot_fx.h" /*-------------------------------------------------------------------* @@ -50,8 +52,37 @@ #define STEREO_DFT_CHANNEL_EXTR_LPC_ORDER 10 #define STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT 320 - - +#ifdef IVAS_FLOAT_FIXED +#define FLR_FX 16384 // Q15 +#define ONE_HALF 24576 // Q14 +#endif +const Word16 wac_swb_h_fx[LPC_SHB_ORDER + 1] = { + 32767, + 32758, + 32731, + 32686, + 32622, + 32541, + 32442, + 32325, + 32191, + 32039, + 31870 +}; + +const Word16 wac_swb_l_fx[LPC_SHB_ORDER + 1] = { + 32767, + 29696, + 20864, + 7872, + 25856, + 12800, + 5952, + 10560, + 256, + 15040, + 30336 +}; /*--------------------------------------------------------------- * stereo_td_get_td_itd() * @@ -84,6 +115,45 @@ static void stereo_td_get_td_itd( return; } +#ifdef IVAS_FLOAT_FIXED +static void stereo_td_get_td_itd_fx( + Word16 *td_itd, /* o : td_itd in samples at sampling frequency */ + Word16 *td_itd_32, /* o : td_itd in samples at 32kHz */ + const Word32 itd, /* i : itd in samples at sampling frequency */ + Word16 q_itd, + const Word32 input_Fs /* i : sampling frequency */ +) +{ + /* *td_itd is the closest integer to itd that transforms into an integer value * + * under the transform x -> (32000/fs) x. */ + Word16 d, d_e; + + IF( EQ_32( input_Fs, 32000 ) ) + { + *td_itd_32 = *td_itd = extract_l( L_shr_r( itd, q_itd ) ); + move16(); + move16(); + } + ELSE + { + assert( ( input_Fs % 16000 ) == 0 && "sampling frequency should be divisible by 16000" ); + Word16 temp_div, temp_e, temp_add; + d = BASOP_Util_Divide3232_Scale( input_Fs, 16000, &d_e ); + temp_div = BASOP_Util_Divide3232_Scale( itd, L_deposit_h( d ), &temp_e ); + temp_e = add( temp_e, sub( sub( 31, q_itd ), d_e ) ); // e+(e1-e2)// + temp_add = add_sat( temp_div, shr( FLR_FX, temp_e ) ); + + *td_itd_32 = shl( shr( temp_add, sub( 15, temp_e ) ), 1 ); + move16(); + + *td_itd = i_mult( shr( *td_itd_32, 1 ), shr( d, sub( 15, d_e ) ) ); + move16(); + } + + return; +} +#endif + /*--------------------------------------------------------------- * stereo_td_channel_extrapolate() * @@ -218,6 +288,196 @@ static void stereo_td_channel_extrapolate( return; } +#ifdef IVAS_FLOAT_FIXED +static void stereo_td_channel_extrapolate_fx( + Encoder_State **sts, + const Word16 dft_ovl, + const Word16 shift_mem[], + Word16 q_shift, + Word16 shift_input[], + const Word16 input_frame, + const Word16 itd_shift, + const Word16 lagging_channel, + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem, + Word16 *q_new_shift ) +{ + Word16 leading_channel, i, size_ovl, pred_ovlp; + Word16 g, nsr, g_lpc; + Word32 dot_lead_lag_1, dot_lead_lead_1, dot_lag_lag_1; + Word64 dot_lead_lag, dot_lead_lead, dot_lag_lag; + Word16 q_dot_lead_lag, q_dot_lead_lead, q_dot_lag_lag; + Word16 window[STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT], mem_zero[STEREO_DFT_CHANNEL_EXTR_LPC_ORDER]; + Word16 residual[STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT + ( STEREO_DFT_ITD_MAX * L_FRAME48k ) / L_FRAME32k]; + Word16 r_h[STEREO_DFT_CHANNEL_EXTR_LPC_ORDER + 1]; + Word16 r_l[STEREO_DFT_CHANNEL_EXTR_LPC_ORDER + 1]; + Word16 Q_r; + Word16 A[STEREO_DFT_CHANNEL_EXTR_LPC_ORDER + 1]; + Word16 shift_combined[L_FRAME48k + L_FRAME48k]; + // Word16 q_shift_combined; + Word16 flag; + Word16 pitch_lag; + Word16 res_shift; + Word16 pitch0; + Word32 L_tmp; + // shift_mem and shift_input are of same Q q_shift// + set16_fx( shift_combined, 0, add( L_FRAME48k, L_FRAME48k ) ); + set16_fx( residual, 0, STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT + ( STEREO_DFT_ITD_MAX * input_frame ) / L_FRAME32k ); + + leading_channel = add( lagging_channel, 1 ) & 1; + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + size_ovl = dft_ovl; + pitch0 = sts[0]->pitch[0]; + } + ELSE + { + size_ovl = input_frame; + pitch0 = sts[lagging_channel]->pitch[0]; + } + + pred_ovlp = idiv1616( input_frame, 10 ); + + /*get pitch lag from previous frame */ + pitch_lag = (int16_t) ( pitch0 * ( (float) input_frame / L_FRAME ) ); + + /* compute the parameters g, nsr and g_lpc */ + dot_lead_lag = EPSILON_FX; + dot_lead_lead = EPSILON_FX; + dot_lag_lag = EPSILON_FX; + dot_lead_lag_1 = EPSILON_FX; + dot_lead_lead_1 = EPSILON_FX; + dot_lag_lag_1 = EPSILON_FX; + FOR( i = 0; i < size_ovl; i++ ) + { + shift_combined[i] = shift_mem[i]; // q_shift + // q_shift_combined = q_shift; + dot_lead_lag = W_mac0_16_16( dot_lead_lag, input_mem[leading_channel][i], shift_mem[i] ); + dot_lead_lead = W_mac0_16_16( dot_lead_lead, input_mem[leading_channel][i], input_mem[leading_channel][i] ); + dot_lag_lag = W_mac0_16_16( dot_lag_lag, shift_mem[i], shift_mem[i] ); + } + FOR( i = 0; i < input_frame - itd_shift; i++ ) + { + shift_combined[add( i, size_ovl )] = shift_input[i]; // q_shift + dot_lead_lag = W_mac0_16_16( dot_lead_lag, sts[leading_channel]->input_fx[i], shift_input[i] ); + dot_lead_lead = W_mac0_16_16( dot_lead_lead, sts[leading_channel]->input_fx[i], sts[leading_channel]->input_fx[i] ); + dot_lag_lag = W_mac0_16_16( dot_lag_lag, shift_input[i], shift_input[i] ); + } + q_dot_lead_lag = q_shift + q_input_mem[leading_channel]; // q_input_mem = q_input + q_dot_lead_lead = q_input_mem[leading_channel] + q_input_mem[leading_channel]; + q_dot_lag_lag = q_shift + q_shift; + + + q_dot_lead_lag = q_dot_lead_lag + W_norm( dot_lead_lag ) - 32; + q_dot_lead_lead = q_dot_lead_lead + W_norm( dot_lead_lead ) - 32; + q_dot_lag_lag = q_dot_lag_lag + W_norm( dot_lag_lag ) - 32; + dot_lead_lag_1 = W_extract_h( W_shl( dot_lead_lag, W_norm( dot_lead_lag ) ) ); + dot_lead_lead_1 = W_extract_h( W_shl( dot_lead_lead, W_norm( dot_lead_lead ) ) ); + dot_lag_lag_1 = W_extract_h( W_shl( dot_lag_lag, W_norm( dot_lag_lag ) ) ); + + + Word16 g_e, f, f_e, g_lpc_e, nsr_e; + g = BASOP_Util_Divide3232_Scale( dot_lead_lag_1, dot_lead_lead_1, &g_e ); + g_e = g_e + ( q_dot_lead_lead - q_dot_lead_lag ); + + f = BASOP_Util_Divide3232_Scale( dot_lead_lag_1, dot_lag_lag_1, &f_e ); + f_e = f_e + ( q_dot_lag_lag - q_dot_lead_lag ); + + nsr = mult( g, f ); + nsr_e = BASOP_Util_Add_MantExp( ONE_IN_Q14, 1, negate( nsr ), g_e + f_e, &nsr ); + IF( LE_16( g_e, 0 ) ) + g = g; + ELSE + g = check_bounds_s( g, negate( shl( 1, 15 - g_e ) ), shl( ONE_HALF, ( 1 - g_e ) ) ); + IF( LE_16( nsr_e, 0 ) ) + nsr = nsr; + ELSE + nsr = check_bounds_s( nsr, 0, shl( 1, 15 - ( nsr_e ) ) ); + g = shl( g, g_e - 1 ); // q14 + nsr = shl( nsr, nsr_e ); // Q15 + g_lpc_e = 0; + g_lpc = Sqrt16( nsr, &g_lpc_e ); + g_lpc = shl( g_lpc, g_lpc_e - 1 ); // Q14 + /* rectangular window */ + set16_fx( window, 32767, STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT ); + set16_zero_fx( mem_zero, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER ); + + /* get the LPC filter */ + autocorr_fx( shift_combined + input_frame + size_ovl - itd_shift - STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER, r_h, r_l, &Q_r, STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT, window, 0, 0 ); + /* Ensure R[0] isn't zero when entering Levinson-Durbin */ + r_l[0] = s_max( r_l[0], 1 ); + FOR( i = 0; i <= STEREO_DFT_CHANNEL_EXTR_LPC_ORDER; i++ ) + { + L_tmp = Mpy_32( r_h[i], r_l[i], wac_swb_h_fx[i], wac_swb_l_fx[i] ); + L_Extract( L_tmp, &r_h[i], &r_l[i] ); + } + r_l[0] = s_max( r_l[0], 1 ); + + flag = E_LPC_lev_dur( r_h, r_l, A, NULL, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER, NULL ); + Copy_Scale_sig( A, A, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER + 1, sub( norm_s( A[0] ), 2 ) ); + IF( EQ_16( flag, 1 ) ) + { + g_lpc = 0; + } + ELSE + { + /* get the residual */ + fir_fx( shift_combined + input_frame + size_ovl - itd_shift - STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT, A, residual, mem_zero, STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER, 0, 3 ); + + /* extend the residual */ + /* to prevent out of bound reading */ + res_shift = ( pitch_lag < PIT_MAX ? pitch_lag : itd_shift ); + + FOR( i = STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT; i < STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT + itd_shift; i++ ) + { + residual[i] = residual[i - res_shift]; + } + + /* perform sythesis */ + E_UTIL_synthesis( 0, A, residual, shift_combined + input_frame + size_ovl - STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT - itd_shift, STEREO_DFT_CHANNEL_EXTR_LPC_VEC_LIMIT + itd_shift, mem_zero, 0, STEREO_DFT_CHANNEL_EXTR_LPC_ORDER ); + } + + Copy( shift_combined + size_ovl, shift_input, input_frame ); // q_shift + + FOR( i = input_frame - itd_shift; i < input_frame; i++ ) + { + shift_input[i] = add( mult( g_lpc, shift_input[i] ), mult( g, sts[leading_channel]->input_fx[i] ) ); + } + Word16 q_temp = 14 + q_shift - 15; + + /* smooth transition (currently done by blending over linearly, could be replaced by something more elaborate.) */ + Word16 e_shift = 0, q_pre_ovl[1280]; + q_temp = q_shift - 1; + FOR( i = input_frame - itd_shift - pred_ovlp; i < input_frame - itd_shift; i++ ) + { + Word32 temp1 = L_mult0( ( i - input_frame + itd_shift + pred_ovlp ), add( mult( g_lpc, shift_input[i] ), mult( g, sts[leading_channel]->input_fx[i] ) ) ); // 14 + q_shift - 15; + Word32 temp2 = L_mult0( ( input_frame - itd_shift - i ), shift_input[i] ); // q_shift + temp2 = L_shr( temp2, 1 ); // q_shift-1 + temp1 = L_add( temp1, temp2 ); // Q_shift-1 + shift_input[i] = BASOP_Util_Divide3232_Scale( temp1, pred_ovlp, &e_shift ); + q_pre_ovl[i] = 15 - e_shift + q_shift - 1; + q_temp = s_min( q_pre_ovl[i], q_temp ); + } + + // scaling whole buffer to q_temp// + FOR( i = 0; i < input_frame - itd_shift - pred_ovlp; i++ ) + { + shift_input[i] = shr( shift_input[i], q_shift - q_temp ); + } + + FOR( i = input_frame - itd_shift; i < input_frame; i++ ) + { + shift_input[i] = shr( shift_input[i], q_shift - 1 - q_temp ); + } + + FOR( i = input_frame - itd_shift - pred_ovlp; i < input_frame - itd_shift; i++ ) + { + shift_input[i] = shr( shift_input[i], q_pre_ovl[i] - q_temp ); + } + *q_new_shift = q_temp; + return; +} +#endif /*--------------------------------------------------------------- * stereo_td_itd() @@ -349,6 +609,175 @@ void stereo_td_itd( return; } +#ifdef IVAS_FLOAT_FIXED +void stereo_td_itd_fx( + ITD_DATA *hITD, /* i/o: ITD data structure */ + Word16 input_mem_itd[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ + Word16 *q_input_mem_itd, + const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ + const Word16 dft_ovl, /* i : size of DFT overlap */ + Encoder_State **sts, /* i/o: Encoder state structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ) +{ + Word16 i, ch, n; + Word16 size_ovl, k_offset; + Word16 shift[2]; + Word16 itd, itd_max; + Word16 shift_input[L_FRAME48k]; + Word16 shift_mem[L_FRAME48k]; + Word16 *mdct_mem[CPE_CHANNELS]; + // Word16 q_mdct_mem[CPE_CHANNELS]; + Word16 q_shift, q_new_shift; + + k_offset = STEREO_DFT_OFFSET; + move16(); + set16_fx( shift_input, 0, input_frame ); + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + Scale_sig( &input_mem[n][0], dft_ovl, sts[n]->q_inp - q_input_mem[n] ); + // Scale_sig(&sts[n]->old_input_signal_fx, 1965, sts[n]->q_inp - sts[n]->q_old_inp); + // sts[n]->q_old_inp = sts[n]->q_inp; + q_input_mem[n] = sts[n]->q_inp; + move16(); + } // check this block once + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_MDCT ) ) + { + /*FOR(n = 0; n < CPE_CHANNELS; n++) + { + Scale_sig(sts[n]->old_input_signal_fx, 1965, sts[n]->q_inp - sts[n]->q_old_inp); + sts[n]->q_old_inp = sts[n]->q_inp; + }*/ + // check this block onc + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + mdct_mem[n] = sts[n]->old_input_signal_fx; + // q_mdct_mem[n] = sts[n]->q_old_inp; + } + } + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + /* Update the parameters */ + FOR( i = 0; i < k_offset; i++ ) + { + hITD->deltaItd_fx[i] = hITD->deltaItd_fx[i + 1]; + move32(); + hITD->td_itd[i] = hITD->td_itd[i + 1]; + move16(); + hITD->td_itd_32k[i] = hITD->td_itd_32k[i + 1]; + move16(); + } + } + /*reset TD ITDs in case of hybrid itd_max change - turn hybrid ITD off*/ + test(); + IF( EQ_16( hITD->hybrid_itd_max, -1 ) && EQ_16( hybrid_itd_flag, 0 ) ) + { + hITD->td_itd[k_offset] = 0; + move16(); + hITD->td_itd_32k[k_offset] = 0; + move16(); + } + IF( EQ_16( hybrid_itd_flag, 0 ) ) + { + return; + } + stereo_td_get_td_itd_fx( &( hITD->td_itd[k_offset] ), &( hITD->td_itd_32k[k_offset] ), hITD->itd_fx[k_offset], Q16, sts[0]->input_Fs ); + + /* initializations*/ + { + size_ovl = dft_ovl; + move16(); + + itd_max = shr( input_frame, 2 ); + Word16 comp_flag1 = (Word16) LE_16( extract_l( L_shr( hITD->itd_fx[k_offset], Q16 ) ), itd_max ); + Word16 comp_flag2 = (Word16) LE_16( extract_l( L_shr( hITD->itd_fx[sub( k_offset, 1 )], Q16 ) ), itd_max ); + assert( ( comp_flag1 ) && "ITD value is too high!" ); + assert( ( comp_flag2 ) && "ITD value is too high!" ); + + itd = hITD->td_itd[k_offset]; + + /*Time shift with current ITD*/ + IF( LT_16( itd, 0 ) ) + { + shift[1] = 0; + move16(); + shift[0] = negate( itd ); + move16(); + ch = 0; + move16(); + } + ELSE + { + shift[1] = itd; + move16(); + shift[0] = 0; + move16(); + ch = 1; + move16(); + } + + /* extrapolate lagging channel */ + IF( GT_16( shift[ch], 0 ) ) + { + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + /* store last part of signal before extrapolation */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + Copy( sts[n]->input_fx + input_frame - dft_ovl, input_mem_itd[n], dft_ovl ); + q_input_mem_itd[n] = sts[n]->q_inp; + move16(); + } + + /*shift past part*/ + Copy( input_mem[ch] + shift[ch], shift_mem, size_ovl - shift[ch] ); + Copy( sts[ch]->input_fx, shift_mem + size_ovl - shift[ch], shift[ch] ); + } + ELSE + { + /*shift past part*/ + Copy( mdct_mem[ch] + shift[ch], shift_mem, input_frame - shift[ch] ); + Copy( sts[ch]->input_fx, shift_mem + input_frame - shift[ch], shift[ch] ); + } + /*shift current part*/ + Copy( sts[ch]->input_fx + shift[ch], shift_input, input_frame - shift[ch] ); + + q_shift = sts[ch]->q_inp; + move16(); + // q_shift is shift for both shift_mem and shift_inp// + // both channels input maintain same q// + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + /*Extrapolate current frame*/ + stereo_td_channel_extrapolate_fx( sts, dft_ovl, shift_mem, q_shift, shift_input, input_frame, shift[ch], ch, input_mem, q_input_mem, &q_new_shift ); + } + ELSE + { + /*Extrapolate current frame*/ + stereo_td_channel_extrapolate_fx( sts, 0, shift_mem, q_shift, shift_input, input_frame, shift[ch], ch, mdct_mem, q_input_mem, &q_new_shift ); + } + + /* write back the extrapolated signal into sts[ch]->input */ + Copy( shift_input, sts[ch]->input_fx, input_frame ); + sts[ch]->q_inp = q_new_shift; + move16(); + IF( EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + // here shift_mem has same as input_mem, no need to update q // + Copy( shift_mem, input_mem[ch], size_ovl ); + } + ELSE + { + Copy( shift_mem, mdct_mem[ch], input_frame ); + } + } + } + + return; +} +#endif /*--------------------------------------------------------------- * stereo_td_itd_mdct_stereo() diff --git a/lib_enc/ivas_stereo_td_analysis.c b/lib_enc/ivas_stereo_td_analysis.c index 73b03eb183aa3bc3dd031fd570d50bf29c007289..299f5e837c201808fd33f357f026becf95ecf524 100644 --- a/lib_enc/ivas_stereo_td_analysis.c +++ b/lib_enc/ivas_stereo_td_analysis.c @@ -56,13 +56,15 @@ #define RMS_MIN_FX_Q20 ( 1572864000 ) /* 1500 in Q20 */ /* Minimum energy for ratio index*/ #define RMS_MIN2_FX_Q21 ( 2097152000 ) /* 1000 in Q21 */ /* Minimum energy for LR encoding*/ #define CORR_THRES_FX_Q15 ( 31130 ) /* 0.95f in Q15 */ /* Maximal open loop correlation */ -#define DT_ENER_THR_FX_Q23 ( 1677721600 ) /* 200 in Q24 */ /* Energy variation threshold */ +#define DT_ENER_THR_FX_Q16 ( 13107200 ) /* 200 in Q16 */ /* Energy variation threshold */ #endif -#define RMS_MIN 1500 /* Minimum energy for ratio index*/ -#define RMS_MIN2 1000 /* Minimum energy for LR encoding*/ -#define CORR_THRES 0.95f /* Maximal open loop correlation */ -#define DT_ENER_THR 200 /* Energy variation threshold */ +#define RMS_MIN 1500 /* Minimum energy for ratio index*/ +#define RMS_MIN2 1000 /* Minimum energy for LR encoding*/ +#define CORR_THRES 0.95f /* Maximal open loop correlation */ +#ifndef IVAS_FLOAT_FIXED +#define DT_ENER_THR 200 /* Energy variation threshold */ +#endif #ifdef IVAS_FLOAT_FIXED #define ALP_REF_FX_Q31 ( 1717986918 ) /* 0.8f in Q31 */ /* smoothing factor */ @@ -73,35 +75,35 @@ #define ALP2_FX_Q31 ( 429496729 ) /* 0.2f in Q31 */ /* smoothing factor in case of correlation are going in different directions in SM mode*/ #define BET2_FX_Q31 ( ONE_IN_Q31 - ALP2_FX_Q31 ) /* increase the update rate in SM mode*/ -#endif - +#else #define ALP_REF 0.8f /* smoothing factor */ #define BET_REF ( 1.0f - ALP_REF ) #define ALP1 0.5f /* smoothing factor in case of correlation are going in different directions */ #define BET1 ( 1.0f - ALP1 ) /* increase the update rate */ -#define ALP2 0.2f /* smoothing factor in case of correlation are going in different directions in SM mode*/ -#define BET2 ( 1.0f - ALP2 ) /* increase the update rate in SM mode*/ -#define RATIO_MAX 1.5f /* Maximum correlation ratio */ +#define ALP2 0.2f /* smoothing factor in case of correlation are going in different directions in SM mode*/ +#define BET2 ( 1.0f - ALP2 ) /* increase the update rate in SM mode*/ +#endif + +#define RATIO_MAX 1.5f /* Maximum correlation ratio */ #ifdef IVAS_FLOAT_FIXED -#define RATIO_MAX_FX_Q30 ( 1610612736 ) /* 0.15f in Q30 */ /* Maximum correlation ratio */ -#define RATIO_MAX_FX_Q24 ( 2516582 ) /* 0.15f in Q24 */ /* Maximum correlation ratio */ -#define RATIO_MAX_FX_Q23 ( 1258291 ) /* 0.15f in Q23 */ /* Maximum correlation ratio */ +#define RATIO_MAX_FX_Q30 ( 1610612736 ) /* 1.5f in Q30 */ /* Maximum correlation ratio */ +#define RATIO_MAX_FX_Q24 ( 2516582 ) /* 1.5f in Q24 */ /* Maximum correlation ratio */ +#define RATIO_MAX_FX_Q23 ( 1258291 ) /* 1.5f in Q23 */ /* Maximum correlation ratio */ #endif +#ifdef IVAS_FLOAT_FIXED +#define LIMIT_ADAP_FAC_FX_Q16 ( 9830 ) /* 0.15f in Q16 */ +#define MIN_ADAP_FAC_FX_Q16 ( 6554 ) /*0.1f in Q16*/ +#define M_ADAP_FX_Q31 ( 1932735 ) /* 0.0009f in Q31 */ +#define B_ADAP_FX_Q16 ( 10486 ) /* 0.16f in Q16 */ +#else #define LIMIT_ADAP_FAC 0.15f #define MIN_ADAP_FAC 0.1f #define M_ADAP 0.0009f #define B_ADAP 0.16f - -#ifdef IVAS_FLOAT_FIXED -#define LIMIT_ADAP_FAC_FX_Q24 ( 2516582 ) /* 0.15f in Q24 */ -#define MIN_ADAP_FAC_FX_Q24 ( 1677722 ) /*0.1f in Q24*/ -#define M_ADAP_FX_Q31 ( 1932735 ) /* 0.0009f in Q31 */ -#define B_ADAP_FX_Q24 ( 2684355 ) /* 0.16f in Q24 */ -// #define B_ADAP_FX_Q31 ( 343597384 ) /* 0.16f in Q31 */ #endif #define PC_LIMIT 64 @@ -122,7 +124,7 @@ // #define ONE_BY_100_Q15 ( 328 ) #define ONE_BY_100_Q31 ( 21474896 ) #define TEN_IN_Q27 ( 1342177280 ) /* 10.0f in Q27 */ -#define TEN_IN_Q24 ( 167772160 ) /* 10.0f in Q24 */ +#define TEN_IN_Q16 ( 655360 ) /* 10.0f in Q16 */ #endif /*-------------------------------------------------------------------* @@ -133,44 +135,39 @@ static Word16 stereo_tdm_ener_analysis_SM_fx( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const Word16 input_frame, Word16 *tdm_SM_flag ); static void Get_corr_n_fx( const Word16 L[], const Word16 R[], Word32 *ic_Lm, Word16 *q_ic_Lm, Word32 *ic_Rm, Word16 *q_ic_Rm, const Word16 len, Word32 *es_em, const Word16 tdm_SM_calc_flag ); -#else -static int16_t stereo_tdm_ener_analysis_SM( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const int16_t input_frame, int16_t *tdm_SM_flag ); - -#endif -static void Get_corr_n( const float L[], const float R[], float *ic_Lm, float *ic_Rm, const int16_t len, float *es_em, const int16_t tdm_SM_calc_flag ); - -#ifdef IVAS_FLOAT_FIXED static Word16 stereo_smooth_LR_transition_fx( Word16 *tdm_prev_stable_idx, Word16 *tdm_ratio_transition_mov_flag, Word16 tdm_last_ratio_idx, Word16 *tdm_prev_desired_idx, Word16 *tdm_ratio_transition_cnt, const Word16 tdm_SM_flag, Word16 desired_idx ); static Word16 limit_idx_Dwnmix_fx( const Word16 idx_in, const Word16 unclr_decision, const Word16 inst_idx, const Word16 previous_idx, const Word16 tdm_last_LRTD_PriCh_cnt, const Word16 tdm_last_LRTD_frame_cnt ); + +static Word16 limit_idx_NoDwnmix_fx( const Word16 idx_in, const Word16 side_can_change, const Word32 d_lt_corr_raw, const Word16 q_d_lt_corr_raw ); + +static void Get_LR_rms_fx( const Word16 *Left_in, const Word16 *Right_in, const Word16 input_frame, Word32 *rms_L, Word16 *q_rms_L, Word32 *rms_R, Word16 *q_rms_R ); + +static Word16 Get_dt_lt_ener_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word16 input_frame, const Word16 tdm_last_SM_flag, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word32 *tdm_lt_rms_L, Word32 *tdm_lt_rms_R, Word32 *tdm_last_ener_lt_L, Word32 *tdm_last_ener_lt_R, Word32 *tdm_LT_es_em, Word16 *tdm_hyst_cnt, Word16 *tdm_NOOP_SM_flag_loc, Word32 *ener_R_dt, Word32 *ener_L_dt, Word32 *corr_LM, Word16 *q_corr_LM, Word32 *corr_RM, Word16 *q_corr_RM ); + +static void NOOP_decision_fx( CPE_ENC_HANDLE hCPE, const Word16 tdm_NOOP_flag_loc, const Word16 tmp_SM_flag, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word16 *tdm_SM_flag_loc ); + +static Word32 Comp_diff_lt_corr_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, const Word32 ener_L_dt, const Word32 ener_R_dt, Word32 corr_LM, Word16 q_corr_LM, Word32 corr_RM, Word16 q_corr_RM, const Word32 tdm_lt_rms_L, const Word32 tdm_lt_rms_R, Word32 *tdm_lt_corr_LM, Word32 *tdm_lt_corr_RM, Word32 *tdm_last_diff_lt_corr, Word16 *q_tdm_last_diff_lt_corr, Word32 *inst_ratio_L_out, Word32 *diff_lt_corr, Word16 *q_d_lt_corr_raw ); #else +static int16_t stereo_tdm_ener_analysis_SM( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const int16_t input_frame, int16_t *tdm_SM_flag ); + +static void Get_corr_n( const float L[], const float R[], float *ic_Lm, float *ic_Rm, const int16_t len, float *es_em, const int16_t tdm_SM_calc_flag ); + static int16_t stereo_smooth_LR_transition( int16_t *tdm_prev_stable_idx, int16_t *tdm_ratio_transition_mov_flag, int16_t tdm_last_ratio_idx, int16_t *tdm_prev_desired_idx, int16_t *tdm_ratio_transition_cnt, const int16_t tdm_SM_flag, int16_t desired_idx ); static int16_t limit_idx_Dwnmix( const int16_t idx_in, const int16_t unclr_decision, const int16_t inst_idx, const int16_t previous_idx, const int16_t tdm_last_LRTD_PriCh_cnt, const int16_t tdm_last_LRTD_frame_cnt ); -#endif static int16_t limit_idx_NoDwnmix( const int16_t idx_in, const int16_t side_can_change, const float d_lt_corr_raw ); -#ifdef IVAS_FLOAT_FIXED -static void Get_LR_rms_fx( const Word16 *Left_in, const Word16 *Right_in, const Word16 input_frame, Word32 *rms_L, Word16 *q_rms_L, Word32 *rms_R, Word16 *q_rms_R ); -#else -#endif static void Get_LR_rms( const float *Left_in, const float *Right_in, const int16_t input_frame, float *rms_L, float *rms_R ); -#ifdef IVAS_FLOAT_FIXED -static Word16 Get_dt_lt_ener_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word16 input_frame, const Word16 tdm_last_SM_flag, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word32 *tdm_lt_rms_L, Word32 *tdm_lt_rms_R, Word32 *tdm_last_ener_lt_L, Word32 *tdm_last_ener_lt_R, Word32 *tdm_LT_es_em, Word16 *tdm_hyst_cnt, Word16 *tdm_NOOP_SM_flag_loc, Word32 *ener_R_dt, Word32 *ener_L_dt, Word32 *corr_LM, Word16 *q_corr_LM, Word32 *corr_RM, Word16 *q_corr_RM ); -#else -#endif static int16_t Get_dt_lt_ener( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, const int16_t input_frame, const int16_t tdm_last_SM_flag, const float rms_L, const float rms_R, float *tdm_lt_rms_L, float *tdm_lt_rms_R, float *tdm_last_ener_lt_L, float *tdm_last_ener_lt_R, float *tdm_LT_es_em, int16_t *tdm_hyst_cnt, int16_t *tdm_NOOP_SM_flag_loc, float *ener_R_dt, float *ener_L_dt, float *corr_LM, float *corr_RM ); static void NOOP_decision( CPE_ENC_HANDLE hCPE, const int16_t tdm_NOOP_flag_loc, const int16_t tmp_SM_flag, const float rms_L, const float rms_R, int16_t *tdm_SM_flag_loc ); -#ifdef IVAS_FLOAT_FIXED -static Word32 Comp_diff_lt_corr_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, const Word32 ener_L_dt, const Word32 ener_R_dt, Word32 corr_LM, Word16 q_corr_LM, Word32 corr_RM, Word16 q_corr_RM, const Word32 tdm_lt_rms_L, const Word32 tdm_lt_rms_R, Word32 *tdm_lt_corr_LM, Word32 *tdm_lt_corr_RM, Word32 *tdm_last_diff_lt_corr, Word16 *q_tdm_last_diff_lt_corr, Word32 *inst_ratio_L_out, Word32 *diff_lt_corr, Word16 *q_d_lt_corr_raw ); -#else -#endif static float Comp_diff_lt_corr( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, const float rms_L, const float rms_R, const float ener_L_dt, const float ener_R_dt, float corr_LM, float corr_RM, const float tdm_lt_rms_L, const float tdm_lt_rms_R, float *tdm_lt_corr_LM, float *tdm_lt_corr_RM, float *tdm_last_diff_lt_corr, float *inst_ratio_L_out, float *diff_lt_corr ); +#endif /*-------------------------------------------------------------------* @@ -187,33 +184,93 @@ int16_t stereo_tdm_ener_analysis( ) { float rms_R, rms_L; +#ifdef IVAS_FLOAT_FIXED + float diff_lt_corr = 0, ratio_L, dist; +#else float corr_RM, corr_LM, diff_lt_corr = 0, ratio_L, dist; +#endif +#ifdef IVAS_FLOAT_FIXED + Word32 diff_lt_corr_fx; +#endif int16_t i, side_can_change; int16_t idx, tdm_SM_flag_loc; int16_t tmp_SM_flag; +#ifndef IVAS_FLOAT_FIXED float ener_R_dt, ener_L_dt; +#endif int16_t desired_idx; float rms_thd; int16_t tdm_NOOP_flag_loc, tdm_NOOP_flag; STEREO_TD_ENC_DATA_HANDLE hStereoTD; Encoder_State **sts; +#ifndef IVAS_FLOAT_FIXED const float *Left_in, *Right_in; +#endif float d_lt_corr_raw; float inst_ratio_L = 0; +#ifdef IVAS_FLOAT_FIXED + Word32 d_lt_corr_raw_fx; + Word16 q_d_lt_corr_raw; + Word32 inst_ratio_L_fx; +#endif int16_t tdm_LRTD_pri_side; +#ifdef IVAS_FLOAT_FIXED + Word32 rms_L_fx, rms_R_fx; + Word16 q_rms_L, q_rms_R; + Word32 corr_RM_fx, corr_LM_fx; + Word16 q_corr_LM, q_corr_RM; + Word32 ener_R_dt_fx, ener_L_dt_fx; +#if 0 + Word16 Left_in_fx[L_FRAME48k], Right_in_fx[L_FRAME48k]; + Word16 q_Left_in, q_Right_in; +#endif +#endif hStereoTD = hCPE->hStereoTD; sts = hCPE->hCoreCoder; +#ifndef IVAS_FLOAT_FIXED Left_in = sts[0]->input; /* Left channel */ Right_in = sts[1]->input; /* Right channel */ +#endif desired_idx = 0; +#ifdef IVAS_FLOAT_FIXED + inst_ratio_L_fx = 0; + move32(); + diff_lt_corr_fx = 0; + move32(); +#endif /*----------------------------------------------------------------* * Compute L and R energy and Long term RMS of each channel *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + floatToFixed_arr16( sts[0]->input, sts[0]->input_fx, 0, input_frame ); + floatToFixed_arr16( sts[1]->input, sts[1]->input_fx, 0, input_frame ); +#endif + +#ifdef IVAS_FLOAT_FIXED +#if 1 + Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R ); +#else + /* This part has f2f conversions as sts[0]->input_fx and sts[1]->input_fx are in Q0. Precision loss is observed in later functions.*/ + q_Left_in = Q_factor_arr( sts[0]->input, input_frame ); + q_Right_in = Q_factor_arr( sts[1]->input, input_frame ); + q_Left_in = s_min( q_Left_in, q_Right_in ); + q_Left_in = sub( q_Left_in, Q1 ); + floatToFixed_arr16( sts[0]->input, Left_in_fx, q_Left_in, input_frame ); + floatToFixed_arr16( sts[1]->input, Right_in_fx, q_Left_in, input_frame ); + Get_LR_rms_fx( Left_in_fx, Right_in_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R ); +#endif +#else Get_LR_rms( Left_in, Right_in, input_frame, &rms_L, &rms_R ); +#endif + +#ifdef IVAS_FLOAT_FIXED + rms_L = fixedToFloat_32( rms_L_fx, q_rms_L ); + rms_R = fixedToFloat_32( rms_R_fx, q_rms_R ); +#endif /*----------------------------------------------------------------* * Compute the 1st order energy difference difference @@ -226,8 +283,39 @@ int16_t stereo_tdm_ener_analysis( tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag; +#ifdef IVAS_FLOAT_FIXED + hStereoTD->tdm_lt_rms_L_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_L, Q16 ); + hStereoTD->tdm_lt_rms_R_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_R, Q16 ); + hStereoTD->tdm_last_ener_lt_L_fx = floatToFixed_32( hStereoTD->tdm_last_ener_lt_L, Q16 ); + hStereoTD->tdm_last_ener_lt_R_fx = floatToFixed_32( hStereoTD->tdm_last_ener_lt_R, Q16 ); + hStereoTD->tdm_LT_es_em_fx = floatToFixed_32( hStereoTD->tdm_LT_es_em, Q21 ); + sts[0]->hNoiseEst->Etot_last_fx = float_to_fix16( sts[0]->hNoiseEst->Etot_last, Q8 ); + sts[1]->hNoiseEst->Etot_last_fx = float_to_fix16( sts[1]->hNoiseEst->Etot_last, Q8 ); + sts[0]->old_corr_fx = float_to_fix16( sts[0]->old_corr, Q15 ); + sts[1]->old_corr_fx = float_to_fix16( sts[1]->old_corr, Q15 ); +#endif + +#ifdef IVAS_FLOAT_FIXED + tmp_SM_flag = Get_dt_lt_ener_fx( hCPE, 0, input_frame, hStereoTD->tdm_last_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, + &hStereoTD->tdm_lt_rms_L_fx, &hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_last_ener_lt_L_fx, &hStereoTD->tdm_last_ener_lt_R_fx, + &hStereoTD->tdm_LT_es_em_fx, &hStereoTD->tdm_hyst_cnt, &tdm_NOOP_flag_loc, + &ener_R_dt_fx, &ener_L_dt_fx, &corr_LM_fx, &q_corr_LM, &corr_RM_fx, &q_corr_RM ); +#else tmp_SM_flag = Get_dt_lt_ener( hCPE, 0, input_frame, hStereoTD->tdm_last_SM_flag, rms_L, rms_R, &hStereoTD->tdm_lt_rms_L, &hStereoTD->tdm_lt_rms_R, &hStereoTD->tdm_last_ener_lt_L, &hStereoTD->tdm_last_ener_lt_R, &hStereoTD->tdm_LT_es_em, &hStereoTD->tdm_hyst_cnt, &tdm_NOOP_flag_loc, &ener_R_dt, &ener_L_dt, &corr_LM, &corr_RM ); +#endif + +#ifdef IVAS_FLOAT_FIXED + hStereoTD->tdm_lt_rms_L = fixedToFloat_32( hStereoTD->tdm_lt_rms_L_fx, Q16 ); + hStereoTD->tdm_lt_rms_R = fixedToFloat_32( hStereoTD->tdm_lt_rms_R_fx, Q16 ); + hStereoTD->tdm_last_ener_lt_L = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_L_fx, Q16 ); + hStereoTD->tdm_last_ener_lt_R = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_R_fx, Q16 ); + hStereoTD->tdm_LT_es_em = fixedToFloat_32( hStereoTD->tdm_LT_es_em_fx, Q21 ); + sts[0]->hNoiseEst->Etot_last = fix16_to_float( sts[0]->hNoiseEst->Etot_last_fx, Q8 ); + sts[1]->hNoiseEst->Etot_last = fix16_to_float( sts[1]->hNoiseEst->Etot_last_fx, Q8 ); + hCPE->hStereoClassif->xtalk_fv[E_diff_corrLM_corrRM] = fixedToFloat( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM], Q21 ); + hCPE->hStereoClassif->xtalk_fv[E_tdm_LT_es_em] = fixedToFloat( hCPE->hStereoClassif->xtalk_fv_fx[E_tdm_LT_es_em], Q21 ); +#endif hStereoTD->tdm_SM_reset_flag = 0; @@ -236,7 +324,17 @@ int16_t stereo_tdm_ener_analysis( * and trigger side/mono configuration if needed *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + sts[0]->ee_old_fx = floatToFixed( sts[0]->ee_old, Q6 ); + sts[1]->ee_old_fx = floatToFixed( sts[1]->ee_old, Q6 ); + hStereoTD->tdm_last_ratio_fx = floatToFixed( hStereoTD->tdm_last_ratio, Q31 ); +#endif + +#ifdef IVAS_FLOAT_FIXED + NOOP_decision_fx( hCPE, tdm_NOOP_flag_loc, tmp_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, &tdm_SM_flag_loc ); +#else NOOP_decision( hCPE, tdm_NOOP_flag_loc, tmp_SM_flag, rms_L, rms_R, &tdm_SM_flag_loc ); +#endif /*----------------------------------------------------------------* * Adjust stereo downmixing adaptation rate factor @@ -245,8 +343,29 @@ int16_t stereo_tdm_ener_analysis( * move on speech offset *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + hStereoTD->tdm_lt_corr_LM_fx = floatToFixed_32( hStereoTD->tdm_lt_corr_LM, Q24 ); + hStereoTD->tdm_lt_corr_RM_fx = floatToFixed_32( hStereoTD->tdm_lt_corr_RM, Q24 ); + hStereoTD->q_tdm_last_diff_lt_corr = Q31; + hStereoTD->tdm_last_diff_lt_corr_fx = floatToFixed_32( hStereoTD->tdm_last_diff_lt_corr, hStereoTD->q_tdm_last_diff_lt_corr ); +#endif + +#ifdef IVAS_FLOAT_FIXED + d_lt_corr_raw_fx = Comp_diff_lt_corr_fx( hCPE, 0, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, ener_L_dt_fx, ener_R_dt_fx, corr_LM_fx, q_corr_LM, corr_RM_fx, q_corr_RM, hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_lt_corr_LM_fx, + &hStereoTD->tdm_lt_corr_RM_fx, &hStereoTD->tdm_last_diff_lt_corr_fx, &hStereoTD->q_tdm_last_diff_lt_corr, &inst_ratio_L_fx, &diff_lt_corr_fx, &q_d_lt_corr_raw ); +#else d_lt_corr_raw = Comp_diff_lt_corr( hCPE, 0, rms_L, rms_R, ener_L_dt, ener_R_dt, corr_LM, corr_RM, hStereoTD->tdm_lt_rms_L, hStereoTD->tdm_lt_rms_R, &hStereoTD->tdm_lt_corr_LM, &hStereoTD->tdm_lt_corr_RM, &hStereoTD->tdm_last_diff_lt_corr, &inst_ratio_L, &diff_lt_corr ); +#endif + +#ifdef IVAS_FLOAT_FIXED + hStereoTD->tdm_lt_corr_LM = fixedToFloat_32( hStereoTD->tdm_lt_corr_LM_fx, Q24 ); + hStereoTD->tdm_lt_corr_RM = fixedToFloat_32( hStereoTD->tdm_lt_corr_RM_fx, Q24 ); + hStereoTD->tdm_last_diff_lt_corr = fixedToFloat_32( hStereoTD->tdm_last_diff_lt_corr_fx, hStereoTD->q_tdm_last_diff_lt_corr ); + diff_lt_corr = fixedToFloat_32( diff_lt_corr_fx, Q24 ); + d_lt_corr_raw = fixedToFloat_32( d_lt_corr_raw_fx, q_d_lt_corr_raw ); + inst_ratio_L = fixedToFloat_32( inst_ratio_L_fx, Q24 ); +#endif /*----------------------------------------------------------------* * UNCLR classifier (detection of uncorrelated L and R channels) @@ -520,7 +639,13 @@ int16_t stereo_tdm_ener_analysis( } else if ( hStereoTD->tdm_LRTD_flag == 1 ) { +#ifdef IVAS_FLOAT_FIXED + q_d_lt_corr_raw = L_get_q1( d_lt_corr_raw ); + d_lt_corr_raw_fx = floatToFixed( d_lt_corr_raw, q_d_lt_corr_raw ); + idx = limit_idx_NoDwnmix_fx( idx, side_can_change, d_lt_corr_raw_fx, q_d_lt_corr_raw ); +#else idx = limit_idx_NoDwnmix( idx, side_can_change, d_lt_corr_raw ); +#endif hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM; tdm_LRTD_pri_side = 0; /* right channel */ if ( idx != LRTD_STEREO_RIGHT_IS_PRIM ) @@ -596,15 +721,25 @@ int16_t stereo_tdm_ener_analysis( } #ifdef IVAS_FLOAT_FIXED - hStereoTD->tdm_lt_rms_L_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_L_SM, Q24 ); - hStereoTD->tdm_lt_rms_R_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_R_SM, Q24 ); + floatToFixed_arr16( sts[0]->input, sts[0]->input_fx, 0, input_frame ); + floatToFixed_arr16( sts[1]->input, sts[1]->input_fx, 0, input_frame ); + + hStereoTD->tdm_lt_rms_L_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_L_SM, Q16 ); + hStereoTD->tdm_lt_rms_R_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_rms_R_SM, Q16 ); + hStereoTD->tdm_last_ener_lt_L_SM_fx = floatToFixed_32( hStereoTD->tdm_last_ener_lt_L_SM, Q16 ); + hStereoTD->tdm_last_ener_lt_R_SM_fx = floatToFixed_32( hStereoTD->tdm_last_ener_lt_R_SM, Q16 ); hStereoTD->tdm_LT_es_em_SM_fx = floatToFixed_32( hStereoTD->tdm_LT_es_em_SM, Q21 ); sts[0]->hNoiseEst->Etot_last_fx = float_to_fix16( sts[0]->hNoiseEst->Etot_last, Q8 ); sts[1]->hNoiseEst->Etot_last_fx = float_to_fix16( sts[1]->hNoiseEst->Etot_last, Q8 ); sts[0]->old_corr_fx = float_to_fix16( sts[0]->old_corr, Q15 ); sts[1]->old_corr_fx = float_to_fix16( sts[1]->old_corr, Q15 ); + + hStereoTD->tdm_lt_corr_LM_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_corr_LM_SM, Q24 ); + hStereoTD->tdm_lt_corr_RM_SM_fx = floatToFixed_32( hStereoTD->tdm_lt_corr_RM_SM, Q24 ); hStereoTD->q_tdm_last_diff_lt_corr_SM = Q31; hStereoTD->tdm_last_diff_lt_corr_SM_fx = floatToFixed_32( hStereoTD->tdm_last_diff_lt_corr_SM, hStereoTD->q_tdm_last_diff_lt_corr_SM ); + + hStereoTD->tdm_last_ratio_SM_fx = floatToFixed_32( hStereoTD->tdm_last_ratio_SM, Q31 ); #endif #ifdef IVAS_FLOAT_FIXED @@ -614,10 +749,10 @@ int16_t stereo_tdm_ener_analysis( #endif #ifdef IVAS_FLOAT_FIXED - hStereoTD->tdm_lt_rms_L_SM = fixedToFloat_32( hStereoTD->tdm_lt_rms_L_SM_fx, Q24 ); - hStereoTD->tdm_lt_rms_R_SM = fixedToFloat_32( hStereoTD->tdm_lt_rms_R_SM_fx, Q24 ); - hStereoTD->tdm_last_ener_lt_L_SM = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_L_SM_fx, Q24 ); - hStereoTD->tdm_last_ener_lt_R_SM = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_R_SM_fx, Q24 ); + hStereoTD->tdm_lt_rms_L_SM = fixedToFloat_32( hStereoTD->tdm_lt_rms_L_SM_fx, Q16 ); + hStereoTD->tdm_lt_rms_R_SM = fixedToFloat_32( hStereoTD->tdm_lt_rms_R_SM_fx, Q16 ); + hStereoTD->tdm_last_ener_lt_L_SM = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_L_SM_fx, Q16 ); + hStereoTD->tdm_last_ener_lt_R_SM = fixedToFloat_32( hStereoTD->tdm_last_ener_lt_R_SM_fx, Q16 ); hStereoTD->tdm_LT_es_em_SM = fixedToFloat_32( hStereoTD->tdm_LT_es_em_SM_fx, Q21 ); sts[0]->hNoiseEst->Etot_last = fix16_to_float( sts[0]->hNoiseEst->Etot_last_fx, Q8 ); sts[1]->hNoiseEst->Etot_last = fix16_to_float( sts[1]->hNoiseEst->Etot_last_fx, Q8 ); @@ -651,6 +786,7 @@ int16_t stereo_tdm_ener_analysis( return ( idx ); } + #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * Function Get_LR_rms_fx() @@ -759,9 +895,7 @@ static void Get_LR_rms_fx( return; } -#endif - - +#else /*-------------------------------------------------------------------* * Function Get_LR_rms() * @@ -791,6 +925,7 @@ static void Get_LR_rms( return; } +#endif #ifdef IVAS_FLOAT_FIXED @@ -828,8 +963,12 @@ static Word16 Get_dt_lt_ener_fx( Word16 *q_corr_RM ) { Encoder_State **sts; +#if 0 + Word16 *Left_in_fx, *Right_in_fx; +#else Word16 Left_in_fx[L_FRAME48k], Right_in_fx[L_FRAME48k]; Word16 q_Left_in, q_Right_in; +#endif Word32 es_em_fx; Word16 tmp_SM_flag, tdm_SM_flag_loc; Word32 L_tmp, L_tmp1; @@ -840,7 +979,8 @@ static Word16 Get_dt_lt_ener_fx( Left_in_fx = sts[0]->input_fx; /* Left channel */ Right_in_fx = sts[1]->input_fx; /* Right channel */ #else - /* This part has f2f conversions as sts[0]->input_fx and sts[1]->input_fx are in Q0. Precision loss is observed in later functions.*/ + /* This part has f2f conversions as sts[0]->input_fx and sts[1]->input_fx are in Q0. + Precision loss is observed in Get_corr_n_fx() function. */ q_Left_in = Q_factor_arr( sts[0]->input, input_frame ); q_Right_in = Q_factor_arr( sts[1]->input, input_frame ); q_Left_in = s_min( q_Left_in, q_Right_in ); @@ -855,9 +995,9 @@ static Word16 Get_dt_lt_ener_fx( test(); IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) && IsSideMono == 0 ) /* last coding mode not TD and normal mono/side case, quick update of lt energy */ { - *tdm_lt_rms_L = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_L ), sub( Q24, q_rms_L ) ); // (Q31, q_rms_L) -> q_rms_L -> Q24 + *tdm_lt_rms_L = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ); // (Q31, q_rms_L) -> q_rms_L -> Q16 move32(); - *tdm_lt_rms_R = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_R ), sub( Q24, q_rms_R ) ); // (Q31, q_rms_R) -> q_rms_R -> Q24 + *tdm_lt_rms_R = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ); // (Q31, q_rms_R) -> q_rms_R -> Q16 move32(); L_tmp = Mpy_32_16_1( 1932735282 /* 0.9f in Q31 */, sts[0]->hNoiseEst->Etot_last_fx ); //(Q31, Q8) -> Q24 sts[1]->hNoiseEst->Etot_last_fx = extract_h( L_tmp ); // (Q24 >> Q16) -> Q8 @@ -866,17 +1006,17 @@ static Word16 Get_dt_lt_ener_fx( } ELSE { - L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_L ); // Q24 + L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_L ); // Q16 L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_L ); // q_rms_L - *tdm_lt_rms_L = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_rms_L ), &exp_diff ); //(Q31 - exp_diff) + *tdm_lt_rms_L = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_L ), &exp_diff ); //(Q31 - exp_diff) move32(); - *tdm_lt_rms_L = L_shl( *tdm_lt_rms_L, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24 + *tdm_lt_rms_L = L_shl( *tdm_lt_rms_L, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16 move32(); - L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_R ); // Q24 + L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_R ); // Q16 L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_R ); // q_rms_L - *tdm_lt_rms_R = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_rms_R ), &exp_diff ); //(Q31 - exp_diff) + *tdm_lt_rms_R = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_R ), &exp_diff ); //(Q31 - exp_diff) move32(); - *tdm_lt_rms_R = L_shl( *tdm_lt_rms_R, sub( Q24, sub( Q31, exp_diff ) ) ); // Q24 + *tdm_lt_rms_R = L_shl( *tdm_lt_rms_R, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16 move32(); } @@ -884,14 +1024,14 @@ static Word16 Get_dt_lt_ener_fx( * Compute the 1st order energy difference difference *----------------------------------------------------------------*/ - *ener_R_dt = L_sub( *tdm_lt_rms_R, *tdm_last_ener_lt_R ); // Q24 + *ener_R_dt = L_sub( *tdm_lt_rms_R, *tdm_last_ener_lt_R ); // Q16 move32(); - *tdm_last_ener_lt_R = *tdm_lt_rms_R; // Q24 + *tdm_last_ener_lt_R = *tdm_lt_rms_R; // Q16 move32(); - *ener_L_dt = L_sub( *tdm_lt_rms_L, *tdm_last_ener_lt_L ); // Q24 + *ener_L_dt = L_sub( *tdm_lt_rms_L, *tdm_last_ener_lt_L ); // Q16 move32(); - *tdm_last_ener_lt_L = *tdm_lt_rms_L; // Q24 + *tdm_last_ener_lt_L = *tdm_lt_rms_L; // Q16 move32(); /*----------------------------------------------------------------* @@ -965,9 +1105,7 @@ static Word16 Get_dt_lt_ener_fx( return tmp_SM_flag; } -#endif - - +#else /*-------------------------------------------------------------------* * Function Get_dt_lt_ener() * @@ -1086,8 +1224,151 @@ static int16_t Get_dt_lt_ener( return tmp_SM_flag; } +#endif +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * Function NOOP_decision_fx() + * + * Set Near Out Of Phase decision + *-------------------------------------------------------------------*/ + +static void NOOP_decision_fx( + CPE_ENC_HANDLE hCPE, + const Word16 tdm_NOOP_flag_loc, + const Word16 tmp_SM_flag, + const Word32 rms_L, + const Word16 q_rms_L, + const Word32 rms_R, + const Word16 q_rms_R, + Word16 *tdm_SM_flag_loc ) +{ + Word16 tdm_NOOP_switch_flag; + STEREO_TD_ENC_DATA_HANDLE hStereoTD; + Encoder_State **sts; + + hStereoTD = hCPE->hStereoTD; + sts = hCPE->hCoreCoder; + + tdm_NOOP_switch_flag = 0; + move16(); + hStereoTD->tdm_NOOP_cnt = add( hStereoTD->tdm_NOOP_cnt, 1 ); + move16(); + IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 ) + { + IF( ( ( GT_16( hStereoTD->tdm_SM_last2_clas[0], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[0], VOICED_TRANSITION ) ) ) || + ( GT_16( hStereoTD->tdm_SM_last2_clas[1], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[1], VOICED_TRANSITION ) ) ) ) && + ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) ) ) + { + tdm_NOOP_switch_flag = 1; + move16(); + hStereoTD->tdm_NOOP_cnt = 0; + move16(); + } + ELSE IF( ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS ) && + ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) ) && ( LT_32( L_shr( rms_L, q_rms_L ), 400 ) && LT_32( L_shr( rms_R, q_rms_R ), 400 ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) ) + { + tdm_NOOP_switch_flag = 1; + move16(); + hStereoTD->tdm_NOOP_cnt = 0; + move16(); + } + } + ELSE + { + if ( LT_32( sts[0]->ee_old_fx, 160000 /* 5000.f in Q6 */ ) && LT_32( sts[1]->ee_old_fx, 160000 /* 5000.f in Q6 */ ) ) + { + tdm_NOOP_switch_flag = 1; + move16(); + } + } + + IF( NE_16( *tdm_SM_flag_loc, tdm_NOOP_flag_loc ) ) + { + hStereoTD->tdm_SM_flag = 1; + move16(); + IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 ) + { + IF( EQ_16( tdm_NOOP_switch_flag, 1 ) ) + { + *tdm_SM_flag_loc = tdm_NOOP_flag_loc; + move16(); + if ( *tdm_SM_flag_loc ) + { + hStereoTD->tdm_SM_reset_flag = 1; + move16(); + } + hStereoTD->tdm_SM_flag = 0; + move16(); + } + } + ELSE + { + IF( EQ_16( tdm_NOOP_switch_flag, 1 ) ) + { + *tdm_SM_flag_loc = tdm_NOOP_flag_loc; + move16(); + if ( *tdm_SM_flag_loc ) + { + hStereoTD->tdm_SM_reset_flag = 1; + move16(); + } + hStereoTD->tdm_SM_flag = 0; + move16(); + } + } + + IF( EQ_16( tdm_NOOP_flag_loc, 1 ) ) + { + hStereoTD->tdm_hyst_cnt = 2; + move16(); + } + ELSE + { + hStereoTD->tdm_hyst_cnt = 20; + move16(); + } + } + + IF( GT_16( hStereoTD->tdm_SM_flag, 0 ) && EQ_16( tdm_NOOP_switch_flag, 1 ) && NE_16( *tdm_SM_flag_loc, tmp_SM_flag ) ) + { + *tdm_SM_flag_loc = !( *tdm_SM_flag_loc ); + move16(); + hStereoTD->tdm_SM_flag = 0; + move16(); + if ( *tdm_SM_flag_loc ) + { + hStereoTD->tdm_SM_reset_flag = 1; + move16(); + } + } + + IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) ) + { + *tdm_SM_flag_loc = 1; + move16(); + hStereoTD->tdm_SM_modi_flag = 0; + move16(); + hStereoTD->tdm_SM_reset_flag = 1; + move16(); + } + ELSE + { + IF( EQ_16( *tdm_SM_flag_loc, 1 ) && EQ_16( hStereoTD->tdm_SM_reset_flag, 1 ) && LT_32( hStereoTD->tdm_last_ratio_fx, 1073741824 /* 0.5 in Q31 */ ) ) + { + hStereoTD->tdm_SM_reset_flag = 0; + move16(); + *tdm_SM_flag_loc = 0; + move16(); + hStereoTD->tdm_SM_modi_flag = 1; + move16(); + } + } + + return; +} +#else /*-------------------------------------------------------------------* * Function NOOP_decision() * @@ -1201,6 +1482,7 @@ static void NOOP_decision( return; } +#endif #ifdef IVAS_FLOAT_FIXED @@ -1239,7 +1521,7 @@ static Word32 Comp_diff_lt_corr_fx( Word32 adaprate_tmp_fx; Word32 madaprate_fx; Word32 d_lt_corr_raw_fx; - Word32 L_tmp, L_tmp1; + Word32 L_tmp, L_tmp1, L_tmp2; Word16 q_tmp, q_tmp1; Word16 exp_diff; Word32 inst_ratio_L_fx; @@ -1261,16 +1543,16 @@ static Word32 Comp_diff_lt_corr_fx( * move on speech offset *----------------------------------------------------------------*/ - IF( IsSideMono == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( GT_32( tdm_lt_rms_R, L_shl( tdm_lt_rms_L, Q1 ) ) || GT_32( tdm_lt_rms_L, L_shl( tdm_lt_rms_R, Q1 ) ) ) ) + IF( IsSideMono == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( GT_32( L_shr( tdm_lt_rms_R, Q1 ), tdm_lt_rms_L ) || GT_32( L_shr( tdm_lt_rms_L, Q1 ), tdm_lt_rms_R ) ) ) { - adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_max( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q24 ); // Q24 + adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_max( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16 } ELSE { - adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_min( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q24 ); // Q24 + adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_min( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16 } - adaprate_fx = check_bounds_l( adaprate_fx, MIN_ADAP_FAC_FX_Q24, ONE_IN_Q24 ); // Q24 + adaprate_fx = check_bounds_l( adaprate_fx, MIN_ADAP_FAC_FX_Q16, ONE_IN_Q16 ); // Q16 /*----------------------------------------------------------------* * In case of unvoiced content (expect when it is part of an onset), @@ -1281,57 +1563,57 @@ static Word32 Comp_diff_lt_corr_fx( ( ( LE_16( sts[0]->last_clas, VOICED_TRANSITION ) && sts[0]->hVAD->hangover_cnt == 0 ) || ( LE_16( sts[1]->last_clas, VOICED_TRANSITION ) && sts[1]->hVAD->hangover_cnt == 0 ) ) ) { - adaprate_fx = L_min( adaprate_fx, LIMIT_ADAP_FAC_FX_Q24 ); + adaprate_fx = L_min( adaprate_fx, LIMIT_ADAP_FAC_FX_Q16 ); // Q16 } d_lt_corr_raw_fx = 0; move32(); IF( IsSideMono == 0 ) { - if ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || ( ( LT_32( tdm_lt_rms_R, ONE_IN_Q24 ) || LT_32( tdm_lt_rms_L, ONE_IN_Q24 ) ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && LT_32( L_max( tdm_lt_rms_R, tdm_lt_rms_L ), TEN_IN_Q24 ) ) ) + if ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || ( ( LT_32( tdm_lt_rms_R, ONE_IN_Q16 ) || LT_32( tdm_lt_rms_L, ONE_IN_Q16 ) ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && LT_32( L_max( tdm_lt_rms_R, tdm_lt_rms_L ), TEN_IN_Q16 ) ) ) { - adaprate_fx = 16441672; /* 0.98f in Q24 */ /* speed up the adaptation of the long term values to the current values after coming from DFT */ + adaprate_fx = 64225; /* 0.98f in Q16 */ /* speed up the adaptation of the long term values to the current values after coming from DFT */ move32(); } - adaprate_tmp_fx = L_max( adaprate_fx, 13421773 /* 0.8f in Q24 */ ); // Q24 - madaprate_fx = L_sub( ONE_IN_Q24, adaprate_tmp_fx ); /* madaprate has temporary value, will updated few lines below */ // Q24 + adaprate_tmp_fx = L_max( adaprate_fx, 52429 /* 0.8f in Q16 */ ); // Q16 + madaprate_fx = L_sub( ONE_IN_Q16, adaprate_tmp_fx ); /* madaprate has temporary value, will updated few lines below */ // Q16 - L_tmp = Mpy_32_32( adaprate_tmp_fx, corr_LM ); // (Q24, q_corr_LM) -> q_corr_LM - Q7 - L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ); // (Q24, Q24) -> Q17 - L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, sub( q_corr_LM, Q7 ) ), L_tmp1, Q31 - Q17, &exp_diff ); // Q31 - exp_diff + L_tmp = Mpy_32_32( adaprate_tmp_fx, corr_LM ); // (Q16, q_corr_LM) -> q_corr_LM - Q15 + L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ); // (Q16, Q24) -> Q9 + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, sub( q_corr_LM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff q_tmp = sub( Q31, exp_diff ); - L_tmp = Mpy_32_32( adaprate_tmp_fx, corr_RM ); // (Q24, q_corr_RM) -> q_corr_RM - Q7 - L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ); // (Q24, Q24) -> Q17 - L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, sub( q_corr_RM, Q7 ) ), L_tmp1, Q31 - Q17, &exp_diff ); // Q31 - exp_diff + L_tmp2 = Mpy_32_32( adaprate_tmp_fx, corr_RM ); // (Q16, q_corr_RM) -> q_corr_RM - Q15 + L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ); // (Q16, Q24) -> Q9 + L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp2, sub( Q31, sub( q_corr_RM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff q_tmp1 = sub( Q31, exp_diff ); - d_lt_corr_raw_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_tmp ), L_tmp1, sub( Q31, q_tmp1 ), &exp_diff ); // Q31 - exp_diff + d_lt_corr_raw_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_tmp ), L_negate( L_tmp1 ), sub( Q31, q_tmp1 ), &exp_diff ); // Q31 - exp_diff *q_d_lt_corr_raw = sub( Q31, exp_diff ); move16(); - q_com = s_min( *q_d_lt_corr_raw, Q30 ); + q_com = s_min( *q_d_lt_corr_raw, Q29 ); inst_ratio_L_fx = 0; move32(); inst_ratio_L_fx = L_max( L_shl( d_lt_corr_raw_fx, sub( q_com, *q_d_lt_corr_raw ) ), L_negate( L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) ) ); // q_com inst_ratio_L_fx = L_min( inst_ratio_L_fx, L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) ); // q_com inst_ratio_L_fx = L_add( Mpy_32_32( 1432371593 /* 0.667f in Q31 */, inst_ratio_L_fx ), L_shl( 1, q_com ) ); // q_com - angle = extract_l( L_shl( Mpy_32_16_1( inst_ratio_L_fx, EVS_PI_FX ), sub( Q13, sub( q_com, Q2 ) ) ) ); // (q_com, Q13) -> q_com - Q2 >> Q1 -> q_com - Q3 -> Q13 + angle = extract_l( L_shl( Mpy_32_16_1( inst_ratio_L_fx, EVS_PI_FX ), sub( sub( Q13, sub( q_com, Q2 ) ), Q1 ) ) ); // (q_com, Q13) -> q_com - Q2 -> Q13 >> Q1 *inst_ratio_L_out = L_shl( L_shr( L_sub( ONE_IN_Q14, L_deposit_l( getCosWord16( angle ) ) ), Q1 ), Q24 - Q14 ); // Q14 << Q10 -> Q24 } - madaprate_fx = L_sub( ONE_IN_Q24, adaprate_fx ); // Q24 - corr_RM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_RM ), sub( Q31, sub( q_corr_RM, Q7 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ), Q31 - Q17, &exp_diff ); // Q31 - exp_diff + madaprate_fx = L_sub( ONE_IN_Q16, adaprate_fx ); // Q16 + corr_RM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_RM ), sub( Q31, sub( q_corr_RM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff q_corr_RM = sub( Q31, exp_diff ); - corr_LM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_LM ), sub( Q31, sub( q_corr_LM, Q7 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ), Q31 - Q17, &exp_diff ); // Q31 - exp_diff + corr_LM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_LM ), sub( Q31, sub( q_corr_LM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff q_corr_LM = sub( Q31, exp_diff ); L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_LM ); // Q24 L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_LM ); // q_corr_LM - diff_lt_corr_LM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_corr_LM ), L_tmp1, Q31 - Q24, &exp_diff ); + diff_lt_corr_LM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); q_diff_lt_corr_LM_tmp = sub( Q31, exp_diff ); L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_RM ); // Q24 L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_RM ); // q_corr_RM - diff_lt_corr_RM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_corr_RM ), L_tmp1, Q31 - Q24, &exp_diff ); + diff_lt_corr_RM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); q_diff_lt_corr_RM_tmp = sub( Q31, exp_diff ); diff_lt_corr_tmp_fx = BASOP_Util_Add_Mant32Exp( diff_lt_corr_LM_tmp_fx, sub( Q31, q_diff_lt_corr_LM_tmp ), L_negate( diff_lt_corr_RM_tmp_fx ), sub( Q31, q_diff_lt_corr_RM_tmp ), &exp_diff ); // (Q31 - exp_diff) q_diff_lt_corr_tmp = sub( Q31, exp_diff ); @@ -1362,8 +1644,8 @@ static Word32 Comp_diff_lt_corr_fx( IF( EQ_16( IsSideMono, 1 ) && ( ( LT_32( L_shl( rms_L, sub( Q21, q_rms_L ) ), RMS_MIN2_FX_Q21 ) && LT_32( L_shl( rms_R, sub( Q21, q_rms_R ) ), RMS_MIN2_FX_Q21 ) ) && - ( LT_32( tdm_lt_rms_L, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_L ), sub( Q24, q_rms_L ) ) ) && - LT_32( tdm_lt_rms_R, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_R ), sub( Q24, q_rms_R ) ) ) ) && + ( LT_32( tdm_lt_rms_L, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ) ) && + LT_32( tdm_lt_rms_R, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ) ) ) && ( GT_32( tdm_lt_rms_L, L_shl( tdm_lt_rms_R, Q1 ) ) || LT_32( tdm_lt_rms_L, L_shr( tdm_lt_rms_R, Q1 ) ) ) ) ) { @@ -1383,10 +1665,10 @@ static Word32 Comp_diff_lt_corr_fx( *tdm_lt_corr_RM = L_shl( Mpy_32_32( *tdm_lt_corr_RM, 1342177280 /* 2.5f in Q29 */ ), Q24 - Q22 ); // ((Q24, Q29) -> Q22 << 2) -> Q24 move32(); } - ELSE IF( ( !( ( GT_32( L_shr( ener_R_dt, Q1 ), DT_ENER_THR_FX_Q23 ) && LT_32( L_shr( ener_L_dt, Q1 ), DT_ENER_THR_FX_Q23 ) ) || - ( LT_32( L_shr( ener_R_dt, Q1 ), DT_ENER_THR_FX_Q23 ) && GT_32( L_shr( ener_L_dt, Q1 ), DT_ENER_THR_FX_Q23 ) ) ) /* Energy are going in the same direction */ - && ( LT_32( L_abs( L_shl( d_lt_corr_fx, d_lt_corr_shift ) ), L_shl( 665719931 /* 0.31f in Q31 */, shift ) ) /* small difference regarding the difference gain evolution */ - || GT_32( L_shr( tdm_lt_rms_L, Q24 - Q20 ), RMS_MIN2_FX_Q21 ) || GT_32( L_shr( tdm_lt_rms_R, Q24 - Q20 ), RMS_MIN2_FX_Q21 ) ) ) /* Energy of at least one of the channel is not low */ + ELSE IF( ( !( ( GT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && LT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) || + ( LT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && GT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) ) /* Energy are going in the same direction */ + && ( LT_32( L_abs( L_shl( d_lt_corr_fx, d_lt_corr_shift ) ), L_shl( 665719931 /* 0.31f in Q31 */, shift ) ) /* small difference regarding the difference gain evolution */ + || GT_32( tdm_lt_rms_L, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) || GT_32( tdm_lt_rms_R, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) ) ) /* Energy of at least one of the channel is not low */ ) { /* Use estimated results */ @@ -1414,9 +1696,7 @@ static Word32 Comp_diff_lt_corr_fx( return d_lt_corr_raw_fx; } -#endif - - +#else /*-------------------------------------------------------------------* * Function Comp_diff_lt_corr() * @@ -1538,6 +1818,7 @@ static float Comp_diff_lt_corr( return d_lt_corr_raw; } +#endif #ifdef IVAS_FLOAT_FIXED @@ -1652,6 +1933,50 @@ static int16_t limit_idx_Dwnmix( #endif +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * Function limit_idx_NoDwnmix_fx() + * + *-------------------------------------------------------------------*/ + +static Word16 limit_idx_NoDwnmix_fx( + const Word16 idx_in, /* i : Index */ + const Word16 side_can_change, /* i : Primary and secondary channel allowed to change ? */ + const Word32 d_lt_corr_raw, /* i : Raw corrrelation differences */ + const Word16 q_d_lt_corr_raw /* i : Q-factor of Raw corrrelation differences */ +) +{ + Word16 idx; + + idx = idx_in; + move16(); + IF( side_can_change == 0 && GT_16( idx_in, 10 ) && LT_16( idx_in, 20 ) ) + { + idx = 30; + move16(); + if ( LT_32( d_lt_corr_raw, L_negate( L_shl( 214748365 /* 0.1f in Q31 */, sub( q_d_lt_corr_raw, Q31 ) ) ) ) ) + { + idx = 0; + move16(); + } + } + ELSE + { + IF( LE_16( idx, 15 ) ) + { + idx = 0; + move16(); + } + ELSE + { + idx = 30; + move16(); + } + } + + return idx; +} +#else /*-------------------------------------------------------------------* * Function limit_idx_NoDwnmix() * @@ -1688,6 +2013,7 @@ static int16_t limit_idx_NoDwnmix( return idx; } +#endif #ifdef IVAS_FLOAT_FIXED @@ -1704,6 +2030,10 @@ static Word16 stereo_tdm_ener_analysis_SM_fx( Word16 *tdm_SM_flag /* i/o: channel combination scheme flag */ ) { +#if 0 + Word16 Left_in_fx[L_FRAME48k], Right_in_fx[L_FRAME48k]; + Word16 q_Left_in, q_Right_in; +#endif Word32 rms_R_fx, rms_L_fx; Word16 q_rms_R, q_rms_L; Word32 corr_RM_fx, corr_LM_fx; @@ -1737,7 +2067,18 @@ static Word16 stereo_tdm_ener_analysis_SM_fx( * Compute L and R energy and Long term RMS of each channel *----------------------------------------------------------------*/ +#if 1 Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R ); +#else + /* This part has f2f conversions as sts[0]->input_fx and sts[1]->input_fx are in Q0. Precision loss is observed in later functions.*/ + q_Left_in = Q_factor_arr( sts[0]->input, input_frame ); + q_Right_in = Q_factor_arr( sts[1]->input, input_frame ); + q_Left_in = s_min( q_Left_in, q_Right_in ); + q_Left_in = sub( q_Left_in, Q1 ); + floatToFixed_arr16( sts[0]->input, Left_in_fx, q_Left_in, input_frame ); + floatToFixed_arr16( sts[1]->input, Right_in_fx, q_Left_in, input_frame ); + Get_LR_rms_fx( Left_in_fx, Right_in_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R ); +#endif /*----------------------------------------------------------------* * Compute the 1st order energy difference difference @@ -1848,10 +2189,9 @@ static Word16 stereo_tdm_ener_analysis_SM_fx( ratio_L_fx = tdm_ratio_tabl_fx_Q24[idx]; move32(); } - else + ELSE { - ratio_L_fx = hStereoTD->tdm_last_ratio_SM_fx; - move32(); + ratio_L_fx = L_shl( hStereoTD->tdm_last_ratio_SM_fx, Q24 - Q31 ); // Q31 -> Q24 idx = hStereoTD->tdm_last_ratio_idx_SM; move16(); } @@ -2306,45 +2646,59 @@ static void Get_corr_n_fx( #endif } - *ic_Lm = BASOP_Util_Divide3232_Scale_cadence( corrL, ener, &exp_diff ); // (Q31 - exp_diff) - move32(); - IF( *ic_Lm == 0 ) + IF( ener == 0 ) { + *ic_Lm = 0; + move32(); *q_ic_Lm = Q31; move16(); - } - ELSE - { - *q_ic_Lm = sub( Q31, exp_diff ); - move16(); - } - *ic_Rm = BASOP_Util_Divide3232_Scale_cadence( corrR, ener, &exp_diff ); // (Q31 - exp_diff) - move16(); - IF( *ic_Rm == 0 ) - { + *ic_Rm = 0; + move32(); *q_ic_Rm = Q31; move16(); + *es_em = 0; + move32(); } ELSE { - *q_ic_Rm = sub( Q31, exp_diff ); + *ic_Lm = BASOP_Util_Divide3232_Scale_cadence( corrL, ener, &exp_diff ); // (Q31 - exp_diff) + move32(); + IF( *ic_Lm == 0 ) + { + *q_ic_Lm = Q31; + move16(); + } + ELSE + { + *q_ic_Lm = sub( Q31, exp_diff ); + move16(); + } + *ic_Rm = BASOP_Util_Divide3232_Scale_cadence( corrR, ener, &exp_diff ); // (Q31 - exp_diff) move16(); - } + IF( *ic_Rm == 0 ) + { + *q_ic_Rm = Q31; + move16(); + } + ELSE + { + *q_ic_Rm = sub( Q31, exp_diff ); + move16(); + } - /* *es_em = 10 * ( log10f( sqrtf( ener_side / len ) ) - log10f( sqrtf( ener / len ) ) ); - is simplified to - *es_em = 10 * ( log10f( sqrtf( ener_side / ener ) ) ); */ - L_tmp = BASOP_Util_Divide3232_Scale_cadence( ener_side, ener, &exp_diff ); // (Q31 - exp_diff) - L_tmp = Sqrt32( L_tmp, &exp_diff ); - L_tmp = BASOP_Util_Log2( L_tmp ); - *es_em = Mpy_32_32( Mpy_32_32( L_add( L_tmp, L_shl( exp_diff, Q25 ) ), LOG10_2_Q31 ), TEN_IN_Q27 ); // (Q25, Q27) -> Q21 - move32(); + /* *es_em = 10 * ( log10f( sqrtf( ener_side / len ) ) - log10f( sqrtf( ener / len ) ) ); + is simplified to + *es_em = 10 * ( log10f( sqrtf( ener_side / ener ) ) ); */ + L_tmp = BASOP_Util_Divide3232_Scale_cadence( ener_side, ener, &exp_diff ); // (Q31 - exp_diff) + L_tmp = Sqrt32( L_tmp, &exp_diff ); + L_tmp = BASOP_Util_Log2( L_tmp ); + *es_em = Mpy_32_32( Mpy_32_32( L_add( L_tmp, L_shl( exp_diff, Q25 ) ), LOG10_2_Q31 ), TEN_IN_Q27 ); // (Q25, Q27) -> Q21 + move32(); + } return; } -#endif - - +#else /*-------------------------------------------------------------------* * Function Get_corr_n() * @@ -2406,6 +2760,7 @@ static void Get_corr_n( return; } +#endif #ifdef IVAS_FLOAT_FIXED diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c index 8df503bd1bbb93e2d4353a585b9e066c8e9e85d1..7d605217ae59c2235f6c5139117c9ab18fb495ab 100644 --- a/lib_enc/speech_music_classif.c +++ b/lib_enc/speech_music_classif.c @@ -1781,6 +1781,7 @@ int16_t ivas_smc_gmm( /* calculate weighted decision */ hSpMusClas->wdlp_0_95_sp = wght * hSpMusClas->wdlp_0_95_sp + ( 1 - wght ) * dlp; + // printf( "\n%f ", hSpMusClas->wdlp_0_95_sp ); /* xtalk classifier: apply long hysteresis to prevent LRTD on music */ hSpMusClas->wdlp_xtalk = 0.995f * hSpMusClas->wdlp_xtalk + 0.005f * dlp; diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 9b95d11439a7634d8564681f78fce0730a139408..bff4b9b430755c565454d094964b690043b03632 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1963,7 +1963,9 @@ typedef struct enc_core_structure Word32 *input_buff32_fx; Word16 *input_fx; Word32 *input32_fx; + Word16 q_inp; Word16 *old_input_signal_fx; + // Word16 q_old_inp; Word16 Q_old_wtda; SIGNAL_BUFFERS_ENC_HANDLE hSignalBuf; @@ -2022,12 +2024,12 @@ typedef struct enc_core_structure float bckr_tilt_lt_flt; float lp_speech; - float lp_noise; /* CNG and DTX - LP filtered total noise estimation */ - Word16 lp_speech_fx; + float lp_noise; /* CNG and DTX - LP filtered total noise estimation */ + Word16 lp_speech_fx; // Q8 Word16 Opt_HE_SAD_ON_fx; Word16 nb_active_frames_HE_SAD_fx; Word16 voicing_old_fx; - Word16 lp_noise_fx; /* CNG and DTX - LP filtered total noise estimation */ + Word16 lp_noise_fx; /* CNG and DTX - LP filtered total noise estimation Q8 */ Word16 var_SID_rate_flag_fx; /* CNG and DTX - flag for variable SID rate */ Word16 interval_SID_fx; Word32 bckr_tilt_lt; diff --git a/lib_enc/swb_bwe_enc.c b/lib_enc/swb_bwe_enc.c index 78808fa51f8ab5db19e0ebac8a2aa845e8085265..569374756f43c9e2e8acba7ddadcbf800e449281 100644 --- a/lib_enc/swb_bwe_enc.c +++ b/lib_enc/swb_bwe_enc.c @@ -54,7 +54,9 @@ static void MSVQ_Interpol_Tran( float *SWB_env_energy, int16_t *indice ); static void calculate_tonality( const float *org, const float *gen, float *SFM_org, float *SFM_gen, const int16_t length ); static int16_t WB_BWE_encoding( Encoder_State *st, const float *yos, float *WB_fenv ); static void energy_control( Encoder_State *st, const int16_t core, const int16_t mode, const int16_t coder_type, const float *org, const int16_t offset, float *energy_factor ); +#ifndef IVAS_FLOAT_FIXED static int16_t decision_hq_generic_class( const float *coefs, const int16_t hq_generic_offset ); +#endif /*-------------------------------------------------------------------* @@ -1038,7 +1040,7 @@ static void msvq_interpol( return; } - +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * msvq_interpol_2() * @@ -1145,7 +1147,7 @@ static void msvq_interpol_2( return; } - +#endif /*-------------------------------------------------------------------* * calculate_tonality() * @@ -1593,7 +1595,7 @@ static int16_t SWB_BWE_encoding( return mode; } - +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * decision_hq_generic_class() * @@ -1839,7 +1841,7 @@ void hq_generic_hf_encoding( return; } - +#endif /*-------------------------------------------------------------------* * fd_bwe_enc_init() * diff --git a/lib_enc/swb_bwe_enc_fx.c b/lib_enc/swb_bwe_enc_fx.c index 9cd165b8db21f58a9572f39abbd1b453ad002e4f..1167ad1afcbf48c6f7539e48a46a6cbb5a5d2b55 100644 --- a/lib_enc/swb_bwe_enc_fx.c +++ b/lib_enc/swb_bwe_enc_fx.c @@ -4,8 +4,9 @@ #include #include "options.h" - -//#include "prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot.h" +#endif #include "cnst.h" #include "rom_com_fx.h" #include "rom_com.h" @@ -907,13 +908,13 @@ static void freq_weights_fx( move16(); FOR( i = 1; i < Nbands; i++ ) { - IF( LT_16( Band_Ener[i], min_b ) ) + if ( LT_16( Band_Ener[i], min_b ) ) { min_b = Band_Ener[i]; move16(); /*Q8 */ } - IF( GT_16( Band_Ener[i], max_b ) ) + if ( GT_16( Band_Ener[i], max_b ) ) { max_b = Band_Ener[i]; move16(); /*Q8 */ @@ -945,6 +946,7 @@ static void freq_weights_fx( L_tmp = L_add( L_tmp, 16777216 ); /*Q24 */ L_tmp = L_shl( L_tmp, 5 ); /*Q29 */ w1[i] = round_fx( L_tmp ); /*Q13 */ + move16(); w2[i] = f_weighting[i]; move16(); /*Q15 */ /*1~0.75*/ w_env[i] = mult_r( w1[i], w2[i] ); @@ -976,6 +978,7 @@ static void vqWithCand_w_fx( Word32 L_dist, L_tmp; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif IF( flag ) { @@ -1017,7 +1020,7 @@ static void vqWithCand_w_fx( { IF( LT_32( L_dist, dist_min[k] ) ) { - FOR( l = surv - 1; l > k; l-- ) + FOR( l = sub( surv, 1 ); l > k; l-- ) { dist_min[l] = dist_min[l - 1]; move32(); @@ -1067,7 +1070,7 @@ static void vqWithCand_w_fx( { IF( LT_32( L_dist, dist_min[k] ) ) { - FOR( l = surv - 1; l > k; l-- ) + FOR( l = sub( surv, 1 ); l > k; l-- ) { dist_min[l] = dist_min[l - 1]; move32(); @@ -1169,7 +1172,7 @@ static Word16 vqSimple_w_fx( /* Reading the selected vector */ - Copy( &cb[index * dim], y, dim ); + Copy( &cb[i_mult( index, dim )], y, dim ); return ( index ); } @@ -1288,6 +1291,7 @@ static void msvq_interpol_fx( Word16 synth_energy[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif /* Extract target vector */ @@ -1429,6 +1433,7 @@ static void msvq_interpol_2_fx( Word16 synth_energy[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif /* Extract target vector */ FOR( n_band = 0; n_band < DIM11 - 1; n_band++ ) @@ -1471,7 +1476,9 @@ static void msvq_interpol_2_fx( } ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); + move16(); ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); + move16(); /* Extract vector for odd position */ FOR( n_band = 0; n_band < DIM11; n_band++ ) @@ -1497,7 +1504,9 @@ static void msvq_interpol_2_fx( } ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); + move16(); ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk3rd_fx, w_env12 + DIM3RD, DIM3RD, N_CB3RD, 1 ); + move16(); FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) { @@ -2388,7 +2397,7 @@ static void get_normalize_spec_fx_32( Word32 L_tmp; Word32 envelope_fx[L_FRAME32k]; - set32_fx( SWB_signal_fx, 0, HQ_GENERIC_HIGH0 + offset ); + set32_fx( SWB_signal_fx, 0, add( HQ_GENERIC_HIGH0, offset ) ); calc_normal_length_fx_32( core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm ); test(); IF( EQ_16( extl, SWB_BWE ) || EQ_16( extl, FB_BWE ) ) @@ -2404,7 +2413,7 @@ static void get_normalize_spec_fx_32( Copy32( &org_fx[112], &SWB_signal_fx[add( 368, offset )], 128 ); Copy32( &org_fx[176], &SWB_signal_fx[add( 496, offset )], 64 ); } - frq_end = 560 + offset; + frq_end = add( 560, offset ); move16(); } ELSE IF( EQ_16( extl, WB_BWE ) ) @@ -2446,11 +2455,12 @@ static void get_normalize_spec_fx_32( tmp = div_s( 16384, tmp ); /*15 + 14 - (12 + exp1 - 16) */ L_tmp = Mult_32_16( L_shl( SWB_signal_fx[n_freq], exp2 ), tmp ); /*exp2 + 12 + (15 + 14 - (12 + exp1 - 16)) - 15 */ SWB_signal_fx[n_freq] = L_shr( L_tmp, sub( 10, sub( exp1, exp2 ) ) ); /*20 */ + move32(); } ELSE { SWB_signal_fx[n_freq] = 0; - move16(); /*20 */ + move32(); /*20 */ } } @@ -2483,8 +2493,9 @@ static void calculate_tonality_fx_32( FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) { org_spec_fx[n_coeff] = L_abs( org_fx[n_coeff] ); + move32(); - IF( LT_32( max_fx, org_spec_fx[n_coeff] ) ) + if ( LT_32( max_fx, org_spec_fx[n_coeff] ) ) { max_fx = org_spec_fx[n_coeff]; move16(); @@ -2495,7 +2506,8 @@ static void calculate_tonality_fx_32( FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) { gen_spec_fx[n_coeff] = L_abs( gen_fx[n_coeff] ); - IF( LT_32( max_fx, gen_spec_fx[n_coeff] ) ) + move32(); + if ( LT_32( max_fx, gen_spec_fx[n_coeff] ) ) { max_fx = gen_spec_fx[n_coeff]; move16(); @@ -2563,6 +2575,7 @@ static void calculate_tonality_fx_32( L_tmp = L_sub( L_tmp1, L_tmp2 ); /*14 */ *SFM_org = L_max( 0, L_min( L_tmp, 98189 ) ); + move32(); IF( am_gen_fx != 0 ) { @@ -2586,6 +2599,7 @@ static void calculate_tonality_fx_32( L_tmp = L_sub( L_tmp1, L_tmp2 ); /*14 */ *SFM_gen = L_max( 0, L_min( L_tmp, 98189 ) ); + move32(); return; } @@ -2606,7 +2620,7 @@ static void energy_control_fx_32( { Word16 n_band; Word16 core_type; - Word16 max_band = SWB_FENV, band_step = 1; + Word16 max_band, band_step; Word32 SWB_signal_fx[L_FRAME32k]; Word32 SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; Word32 L_temp1, L_temp2; @@ -2614,6 +2628,11 @@ static void energy_control_fx_32( Word16 gamma_fx; FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + max_band = SWB_FENV; + move16(); + band_step = 1; + move16(); + IF( core == ACELP_CORE ) { gamma_fx = 11468; @@ -2646,7 +2665,7 @@ static void energy_control_fx_32( move16(); get_normalize_spec_fx_32( core, -1, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset ); - IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) + if ( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) { max_band = 12; move16(); @@ -2656,11 +2675,11 @@ static void energy_control_fx_32( FOR( n_band = 0; n_band < max_band; n_band += band_step ) { calculate_tonality_fx_32( &org_fx[add( swb_bwe_subband[n_band], offset )], &SWB_signal_fx[add( swb_bwe_subband[n_band], offset )], - &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[add( n_band, band_step )] - swb_bwe_subband[n_band] ); + &SFM_org_fx[n_band], &SFM_gen_fx[n_band], sub( swb_bwe_subband[add( n_band, band_step )], swb_bwe_subband[n_band] ) ); L_temp1 = L_shl( SFM_gen_fx[n_band], 2 ); L_temp2 = L_add( SFM_org_fx[n_band], L_shl( SFM_org_fx[n_band], 1 ) ); - IF( L_temp1 < L_temp2 ) + IF( LT_32( L_temp1, L_temp2 ) ) { exp1 = sub( norm_l( SFM_gen_fx[n_band] ), 1 ); exp2 = norm_l( SFM_org_fx[n_band] ); @@ -2668,8 +2687,9 @@ static void energy_control_fx_32( tmp2 = extract_h( L_shl( SFM_org_fx[n_band], exp2 ) ); tmp = div_s( tmp1, tmp2 ); /*15 + (14 + exp1 ) - (14 + exp2) */ energy_factor_fx[n_band] = shl( tmp, sub( exp2, exp1 ) ); /*15 */ + move16(); - IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + if ( LT_16( energy_factor_fx[n_band], gamma_fx ) ) { energy_factor_fx[n_band] = gamma_fx; move16(); @@ -3029,3 +3049,230 @@ void fd_bwe_enc_init_fx( return; } + +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * hq_generic_encoding_fx() + * + *-------------------------------------------------------------------*/ +void hq_generic_hf_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original : Q12 */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope : Q1 */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy : Q0 */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas, /* o : bwe excitation class : Q0 */ + Word16 length ) +{ + Word16 n_coeff, n_band; + Word16 indice[HQ_GENERIC_NVQIDX]; + Word16 nenv; + + Word16 energy_factor_fx[SWB_FENV]; + Word16 cs, exp, tmp, tmp2; + Word32 energy_fx; + Word32 L_tmp, max_coefs_fx; + Word16 w_env_fx[SWB_FENV]; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + set16_fx( energy_factor_fx, 0, SWB_FENV ); + + IF( LE_16( hq_generic_offset, HQ_GENERIC_FOFFSET_24K4 ) ) + { + nenv = SWB_FENV; + move16(); + } + ELSE + { + nenv = SWB_FENV - 2; + move16(); + } + + + energy_control_fx_32( st_fx, HQ_CORE, -1, -1, coefs_fx, hq_generic_offset, energy_factor_fx ); + + IF( EQ_16( hHQ_core->hq_generic_speech_class, 1 ) ) + { + push_indice( hBstr, IND_HQ_SWB_EXC_SP_CLAS, 1, 1 ); + *hq_generic_exc_clas = HQ_GENERIC_SP_EXC; + move16(); + } + ELSE + { + *hq_generic_exc_clas = decision_hq_generic_class_fx_32( coefs_fx, hq_generic_offset ); + move16(); + push_indice( hBstr, IND_HQ_SWB_EXC_SP_CLAS, 0, 1 ); + push_indice( hBstr, IND_HQ_SWB_EXC_CLAS, *hq_generic_exc_clas, 1 ); + } + + FOR( n_band = 0; n_band < nenv; n_band++ ) + { + energy_fx = L_deposit_l( 0 ); + max_coefs_fx = L_deposit_l( 0 ); + tmp2 = add( swb_bwe_subband[n_band + 1], hq_generic_offset ); + FOR( n_coeff = add( swb_bwe_subband[n_band], hq_generic_offset ); n_coeff < tmp2; n_coeff++ ) + { + IF( LT_32( max_coefs_fx, L_abs( coefs_fx[n_coeff] ) ) ) + { + max_coefs_fx = L_abs( coefs_fx[n_coeff] ); + } + } + cs = norm_l( max_coefs_fx ); + tmp2 = add( swb_bwe_subband[n_band + 1], hq_generic_offset ); + FOR( n_coeff = add( swb_bwe_subband[n_band], hq_generic_offset ); n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h( L_shl( coefs_fx[n_coeff], cs ) ); /*12 + cs - 16 */ + L_tmp = L_mult0( tmp, tmp ); /*2*cs - 8 */ + energy_fx = L_add( energy_fx, L_shr( L_tmp, 5 ) ); + } + + IF( energy_fx != 0 ) + { + L_tmp = Mult_32_16( energy_fx, energy_factor_fx[n_band] ); /*2*cs - 13 */ + L_tmp = Mult_32_16( L_tmp, swb_inv_bwe_subband_width_fx[n_band] ); /*2*cs - 13 + 15 - 15 */ + + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + exp = sub( 30, add( exp, sub( shl( cs, 1 ), 13 ) ) ); + + L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[n_band] = round_fx( L_shl( L_tmp, 10 ) ); /*Q8 */ + } + ELSE + { + hq_generic_fenv_fx[n_band] = -24576; + move16(); + } + } + + IF( EQ_16( length, L_SPEC48k ) ) + { + FOR( n_band = 0; n_band < DIM_FB; n_band++ ) + { + energy_fx = L_deposit_l( 0 ); + max_coefs_fx = L_deposit_l( 0 ); + tmp2 = fb_bwe_subband[n_band + 1]; + FOR( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + IF( LT_32( max_coefs_fx, L_abs( coefs_fx[n_coeff] ) ) ) + { + max_coefs_fx = L_abs( coefs_fx[n_coeff] ); + } + } + cs = norm_l( max_coefs_fx ); + tmp2 = fb_bwe_subband[n_band + 1]; + FOR( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h( L_shl( coefs_fx[n_coeff], cs ) ); /*12 + cs - 16 */ + L_tmp = L_mult0( tmp, tmp ); /*2*cs - 8 */ + energy_fx = L_add( energy_fx, L_shr( L_tmp, 5 ) ); + } + + IF( energy_fx != 0 ) + { + L_tmp = Mult_32_16( energy_fx, fb_inv_bwe_subband_width_fx[n_band] ); /*2*cs - 13 + 18 - 15 */ + + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + exp = sub( 30, add( exp, sub( shl( cs, 1 ), 13 ) ) ); + + L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[add( n_band, nenv )] = round_fx( L_shl( L_tmp, 10 ) ); /*Q8 */ + move16(); + } + ELSE + { + hq_generic_fenv_fx[add( n_band, nenv )] = -24576; + move16(); + } + } + } + + freq_weights_fx( hq_generic_fenv_fx, w_NOR_fx, w_env_fx, nenv ); + + FOR( n_band = 0; n_band < nenv; n_band++ ) + { + hq_generic_fenv_fx[n_band] = sub( hq_generic_fenv_fx[n_band], Mean_env_fx[n_band] ); + move16(); + } + + IF( EQ_16( length, L_SPEC48k ) ) + { + FOR( n_band = 0; n_band < DIM_FB; n_band++ ) + { + hq_generic_fenv_fx[add( n_band, nenv )] = sub( shr( hq_generic_fenv_fx[add( n_band, nenv )], 1 ), Mean_env_fb_fx[n_band] ); + move16(); + } + } + + + /* Energy VQ */ + IF( LE_16( hq_generic_offset, HQ_GENERIC_FOFFSET_24K4 ) ) + { + msvq_interpol_fx( hq_generic_fenv_fx, w_env_fx, indice ); + } + ELSE + { + msvq_interpol_2_fx( hq_generic_fenv_fx, w_env_fx, indice, nenv ); + } + + IF( EQ_16( length, L_SPEC48k ) ) + { + indice[5] = vqSimple_w_fx( hq_generic_fenv_fx + nenv, hq_generic_fenv_fx + nenv, EnvCdbkFB_fx, NULL, DIM_FB, N_CB_FB, 0 ); + move16(); + } + + push_indice( hBstr, IND_SWB_FENV_HQ, indice[0], 5 ); + push_indice( hBstr, IND_SWB_FENV_HQ, indice[1], 7 ); + push_indice( hBstr, IND_SWB_FENV_HQ, indice[2], 6 ); + push_indice( hBstr, IND_SWB_FENV_HQ, indice[3], 5 ); + + IF( LE_16( hq_generic_offset, HQ_GENERIC_FOFFSET_24K4 ) ) + { + push_indice( hBstr, IND_SWB_FENV_HQ, indice[4], 6 ); + } + ELSE + { + push_indice( hBstr, IND_SWB_FENV_HQ, indice[4], 5 ); + } + + IF( EQ_16( length, L_SPEC48k ) ) + { + push_indice( hBstr, IND_FB_FENV_HQ, indice[5], 5 ); + } + + FOR( n_band = 0; n_band < nenv; n_band++ ) + { + tmp = add( hq_generic_fenv_fx[n_band], Mean_env_fx[n_band] ); /*8 */ + L_tmp = L_mult( tmp, 21771 ); /*26 */ + L_tmp = L_shr( L_tmp, 10 ); /*16 */ + L_Extract( L_tmp, &exp, &tmp ); /* */ + tmp = extract_l( Pow2( 13, tmp ) ); + exp = sub( exp, 13 ); +#ifdef BASOP_NOGLOB + hq_generic_fenv_fx[n_band] = shl_sat( tmp, add( exp, 1 ) ); /*1 */ +#else + hq_generic_fenv_fx[n_band] = shl( tmp, add( exp, 1 ) ); /*1 */ +#endif + move16(); + } + + + IF( EQ_16( length, L_SPEC48k ) ) + { + FOR( n_band = 0; n_band < DIM_FB; n_band++ ) + { + tmp = add( hq_generic_fenv_fx[add( n_band, nenv )], Mean_env_fb_fx[n_band] ); /*7 */ + L_tmp = L_mult( tmp, 21771 ); /*25 */ + L_tmp = L_shr( L_tmp, 9 ); /*16 */ + L_Extract( L_tmp, &exp, &tmp ); + tmp = extract_l( Pow2( 13, tmp ) ); + exp = sub( exp, 13 ); + hq_generic_fenv_fx[add( n_band, nenv )] = shl( tmp, add( exp, 1 ) ); /*1 */ + move16(); + } + } + + return; +} +#endif