diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c index e8d44551c4b0a908dc458c4af415c491392201da..7d892f8c813f92e41bfc492d3e1f2edec31d6ff7 100644 --- a/lib_com/bitstream.c +++ b/lib_com/bitstream.c @@ -2170,6 +2170,7 @@ uint16_t get_indice_1( * Reset the buffer of encoder indices *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void reset_indices_enc( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 max_num_indices /* i : max number of indices */ @@ -2187,6 +2188,28 @@ void reset_indices_enc( return; } +#else +void reset_indices_enc( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 max_num_indices /* i : max number of indices */ +) +{ + Word16 i; + + hBstr->nb_bits_tot = 0; + move16(); + hBstr->nb_ind_tot = 0; + move16(); + + FOR( i = 0; i < max_num_indices; i++ ) + { + hBstr->ind_list[i].nb_bits = -1; + move16(); + } + + return; +} +#endif /*-------------------------------------------------------------------* * reset_indices_dec() diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index 6bbd3e152e6766e617c55d2d142a2d89c4574878..c015e5738d730286664ff79239531369517fce28 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -1950,7 +1950,9 @@ void analysisCldfbEncoder_ivas( void analysisCldfbEncoder_ivas_fx( Encoder_State *st, /* i/o: encoder state structure */ - const Word16 *timeIn, + Word32 *timeIn, /*q11*/ + Word16 timeInq, + Word16 samplesToProcess, Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], @@ -1965,7 +1967,11 @@ void analysisCldfbEncoder_ivas_fx( Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX]; Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX]; Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX]; - Word32 workBuffer[256]; + Word32 l_timeIn[L_FRAME48k]; + Word16 norm_timeIn = L_norm_arr( timeIn, samplesToProcess ); + Word16 guard_bits = find_guarded_bits_fx( shl( samplesToProcess, 1 ) ); + Word16 shift = 0; + move16(); FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ ) { @@ -1974,13 +1980,24 @@ void analysisCldfbEncoder_ivas_fx( ppBuf_Real16[i] = &realBuffer16[i][0]; ppBuf_Imag16[i] = &imagBuffer16[i][0]; } + IF( GT_16( guard_bits, norm_timeIn ) ) + { + shift = sub( guard_bits, norm_timeIn ); + v_shr_32( timeIn, l_timeIn, samplesToProcess, shift ); + } + ELSE + { + Copy32( timeIn, l_timeIn, samplesToProcess ); + } - cldfbAnalysisFiltering( st->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, scale, timeIn, 0, CLDFB_NO_COL_MAX, workBuffer ); + cldfbAnalysis_ivas_fx( l_timeIn, ppBuf_Real, ppBuf_Imag, samplesToProcess, st->cldfbAnaEnc ); + scale->lb_scale = sub( 16 + 5, sub( timeInq, shift ) ); enerScale.lb_scale = negate( scale->lb_scale ); enerScale.lb_scale16 = negate( scale->lb_scale ); move16(); move16(); + move16(); AnalysisPostSpectrumScaling_Fx( st->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, ppBuf_Real16, ppBuf_Imag16, &enerScale.lb_scale16 ); @@ -2793,7 +2810,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17036; hs->scale = cldfb_scale_2_5ms[0]; - hs->p_filter = cldfb_protoFilter_2_5ms[0]; + hs->p_filter = CLDFB80_10_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -2808,7 +2825,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; - hs->p_filter = cldfb_protoFilter_5_0ms[0]; + hs->p_filter = LDQMF_10_fx; hs->scale = cldfb_scale_5_0ms[0]; #endif } @@ -2843,7 +2860,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17051; - hs->p_filter = cldfb_protoFilter_2_5ms[1]; + hs->p_filter = CLDFB80_16_fx; hs->scale = cldfb_scale_2_5ms[1]; #endif } @@ -2859,7 +2876,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; - hs->p_filter = cldfb_protoFilter_5_0ms[1]; + hs->p_filter = LDQMF_16_fx; hs->scale = cldfb_scale_5_0ms[1]; #endif } @@ -2900,7 +2917,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17050; - hs->p_filter = cldfb_protoFilter_2_5ms[2]; + hs->p_filter = CLDFB80_20_fx; hs->scale = cldfb_scale_2_5ms[2]; #endif } @@ -2916,7 +2933,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15390; - hs->p_filter = cldfb_protoFilter_5_0ms[2]; + hs->p_filter = LDQMF_20_fx; hs->scale = cldfb_scale_5_0ms[2]; #endif } @@ -2958,7 +2975,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17051; hs->scale = cldfb_scale_2_5ms[6]; - hs->p_filter = cldfb_protoFilter_2_5ms[6]; + hs->p_filter = CLDFB80_30_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -2974,7 +2991,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; hs->scale = cldfb_scale_5_0ms[6]; - hs->p_filter = cldfb_protoFilter_5_0ms[6]; + hs->p_filter = LDQMF_30_fx; #endif } break; @@ -3008,7 +3025,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17050; - hs->p_filter = cldfb_protoFilter_2_5ms[3]; + hs->p_filter = CLDFB80_32_fx; hs->scale = cldfb_scale_2_5ms[3]; #endif } @@ -3025,7 +3042,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15392; hs->scale = cldfb_scale_5_0ms[3]; - hs->p_filter = cldfb_protoFilter_5_0ms[3]; + hs->p_filter = LDQMF_32_fx; #endif } break; @@ -3067,7 +3084,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->p_filter_sf = (Word16) 17051; hs->q_scale = norm_s( (Word16) CLDFB80_40_SCALE ); hs->scale = cldfb_scale_2_5ms[4]; - hs->p_filter = cldfb_protoFilter_2_5ms[4]; + hs->p_filter = CLDFB80_40_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -3086,7 +3103,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_syn_delay_im_fx = rot_vec_delay_im_LDQMF_fx; hs->p_filter_sf = (Word16) 15391; - hs->p_filter = cldfb_protoFilter_5_0ms[4]; + hs->p_filter = LDQMF_40_fx; hs->scale = cldfb_scale_5_0ms[4]; #endif } @@ -3131,7 +3148,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = NULL; hs->rot_vec_syn_delay_im_fx = NULL; hs->p_filter_sf = (Word16) 17051; - hs->p_filter = cldfb_protoFilter_2_5ms[5]; + hs->p_filter = CLDFB80_60_fx; hs->scale = cldfb_scale_2_5ms[5]; #endif } @@ -3151,7 +3168,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_syn_delay_im_fx = rot_vec_delay_im_LDQMF_fx; hs->p_filter_sf = (Word16) 15391; - hs->p_filter = cldfb_protoFilter_5_0ms[5]; + hs->p_filter = LDQMF_60_fx; hs->scale = cldfb_scale_5_0ms[5]; #endif } diff --git a/lib_com/cnst.h b/lib_com/cnst.h index bbedf69d6b3e9d3b0843e58a72e33b81c079604b..feece3ae908957fa0bffcc4f51cb4e4161073386 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -209,6 +209,15 @@ enum{ #define L_FRAME8k 160 /* Frame size in samples at 8kHz */ #define L_FRAME4k 80 /* Frame size in samples at 4kHz */ +#define ONE_BY_L_FRAME48k_Q31 2236962 +#define ONE_BY_L_FRAME32k_Q31 3355443 +#define ONE_BY_L_FRAME25_6k_Q31 4194304 +#define ONE_BY_L_FRAME16k_Q31 6710886 +#define ONE_BY_L_FRAME_Q31 8388608 +#define ONE_BY_240_Q31 8947849 +#define ONE_BY_L_FRAME8k_Q31 13421772 +#define ONE_BY_L_FRAME4k_Q31 26843546 + #define L_SPEC48k 800 /* HQ spectrum length at 48kHz */ #define L_SPEC32k 640 /* HQ spectrum length at 32kHz */ #define L_SPEC16k 320 /* HQ spectrum length at 16kHz */ @@ -238,6 +247,7 @@ enum{ #define INV_LOG_2_FX 23637 /*Q14*//* 1/log(2) */ #endif // IVAS_FLOAT_FIXED #define INV_SQRT_2 0.70710676908493f /* 1/sqrt(2) */ +#define INV_SQRT_2_Q30 759250112 /* 1/sqrt(2) in Q30*/ #define INV_SQRT_2_Q15 23170 /* 1/sqrt(2) in Q15 */ #define INV_SQRT_2_Q31 (Word32)1.51850022e+09 /* 1/sqrt(2) in Q31 */ @@ -736,11 +746,14 @@ enum #define PIT_UP_SAMP6 6 #define PIT_L_INTERPOL6_2 17 #define PIT_FIR_SIZE6_2 ( PIT_UP_SAMP6 * PIT_L_INTERPOL6_2 + 1 ) +#define E_MIN_Q11_FX 7 /* minimum allowable energy in Q11*/ #define E_MIN 0.0035f /* minimum allowable energy */ +#define E_MIN_Q11_FX 7 /* minimum allowable energy in Q11*/ #define STEP_DELTA 0.0625f /* quantization step for tilt compensation of gaussian cb. excitation */ #define GAMMA_EV 0.92f /* weighting factor for core synthesis error weighting */ #define FORMANT_SHARPENING_NOISE_THRESHOLD 21.0f /* lp_noise level above which formant sharpening is deactivated */ #define E_MIN_FX 1 /* QSCALE (Q7)*/ +#define E_MIN_IVAS_FX 1835 /* (Q19) (E12) */ #define STEP_DELTA_FX 11 #define FORMANT_SHARPENING_NOISE_THRESHOLD_FX 5376 /* 21 (!8)lp_noise level above which formant sharpening is deactivated - at this level most of 20 dB SNR office noisy speech still uses sharpening */ @@ -772,6 +785,7 @@ enum #define CLDFB_OVRLP_MIN_SLOTS 3 /* CLDFB resampling - minimize processing to minimum required for transition frame ACELP->TCX/HQ */ #define INV_CLDFB_BANDWIDTH ( 1.f / 800.f ) #define INV_CLDFB_BANDWIDTH_Q31 ( 2684355l ) +#define INV_CLDFB_BANDWIDTH_MDFT_FAC_Q31 ( 10737418 ) #define CLDFB_BANDWIDTH 800 #define L_FILT_2OVER3 12 @@ -1000,6 +1014,7 @@ typedef enum #define BWD_COUNT_MAX 100 /* maximum value of BWD counter */ #define BWD_N_BINS_MAX 13 /* maximum number of BWD bins */ #define BWS_TRAN_PERIOD 5 /* BWS - number of frames for transition period */ +#define ONE_BY_BWS_TRAN_PERIOD_Q15 6554 #define PREEMPH_FAC_FLT 0.68f /* preemphasis factor at 12.8kHz */ #define PREEMPH_FAC_16k_FLT 0.72f @@ -1425,6 +1440,7 @@ enum #define NB_LEADER 36 #define NB_LDQ4 27 #define FAC_LOG2 3.321928095f +#define FAC_LOG2_BY10_Q16 21771 #define NSV_MAX 34 /* maximal number of sub-vectors used by the AVQ */ @@ -1549,6 +1565,7 @@ enum #define SHB_GAIN_QDELTA_1k75 0.08f /* SHB gain scalar quantizer stepsize */ #define SHB_GAIN_QLOW_1k75_FX 0 /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QDELTA_1k75_FX 10486 /* SHB gain scalar quantizer stepsize Q17 */ +#define SHB_GAIN_QDELTA_1k75_FX_15 2622 /* SHB gain scalar quantizer stepsize */ #define SHB_GAIN_QLOW_FX -262144 /* Q18*/ /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QLOW_FX_16 -65536 /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QDELTA_FX_15 4915 /* SHB gain scalar quantizer step size */ @@ -1941,10 +1958,15 @@ typedef enum _DCTTYPE #define ATT_NSEG 32 /* strong attack detection - number of time blocks */ #define TOD_NSPEC 80 /* number of spectral bins of the tonal detector */ +#define TOD_NSPEC_INV_Q31 26843546 /* inverse of number of spectral bins of the tonal detector */ #define TOD_THR_MASS 0.86f /* initial value for the adaptive threshold of the tonal detector */ +#define TOD_THR_MASS_FX_Q22 3607101 /* initial value for the adaptive threshold of the tonal detector */ #define P2A_FACT 0.9f /* long-term averaging factor for peak-to-average ratio */ +#define P2A_FACT_FX_Q15 29491 /* long-term averaging factor for peak-to-average ratio */ #define THR_P2A_HIGH 95.0f /* higher threshold to detect strongly peaky signals at low bitrates*/ #define THR_P2A 80.0f /* lower threshold to detect strongly peaky signals at higher bitrates */ +#define THR_P2A_HIGH_FX 95 /* Q0, higher threshold to detect strongly peaky signals at low bitrates*/ +#define THR_P2A_FX 80 /* Q0, lower threshold to detect strongly peaky signals at higher bitrates */ /*----------------------------------------------------------------------------------* * LD music post-filter constants @@ -2750,6 +2772,7 @@ enum #define Fs_2_16k 20480 /* lsf max value (Use in reorder_fx.c) */ #define LG10 24660 /* 10*log10(2) in Q13 */ +#define TEN_MULT_LOG10_2_IN_Q29 1616142464 /* (10 * log10(2)) = 3.0103 (in Q29) */ #define LG10_s3_0 16440 /* 10*log10(2)/1.55 = 1.00343331 in Q14 */ #define LOG2_10 27213 /* log base 2 of 10 in Q12 */ #define LOG2_10_Q29 1783446566 /* log base 2 of 10 in Q12 */ @@ -3022,7 +3045,7 @@ enum #define EVS_2PI_FX 51472 /* 2 * pi in Q13 */ #define EVS_PI_FX_Q27 421657428 /* pi in Q28 */ #define EVS_2PI_FX_Q27 843314856 /* 2 * pi in Q28 */ -#define EVS_PI_BY_2_FX (Word16)(0x3244) +#define EVS_PI_BY_2_FX (Word16)(0x3244) // Q13 //#define EVS_PI_FX (Word16)(0x6488) #define LG10 24660 /* 10*log10(2) in Q13 */ diff --git a/lib_com/count.c b/lib_com/count.c index b93414d8a4cbd123e05fd700533d1da6ad012d58..eaf6f04f422786a7f67642b6e3bfca292eb2afde 100644 --- a/lib_com/count.c +++ b/lib_com/count.c @@ -1082,7 +1082,7 @@ void WMOPS_destroy( void ) { if ( NULL != objectName[i] ) { - free_( objectName[i] ); + free( objectName[i] ); objectName[i] = NULL; } } diff --git a/lib_com/edct_fx.c b/lib_com/edct_fx.c index bd27d2137a5234757c747e4b90270f0c69c67bbf..c3506838f6c0118e087a034043510fd2250b9b56 100644 --- a/lib_com/edct_fx.c +++ b/lib_com/edct_fx.c @@ -746,7 +746,7 @@ void edxt_fx( move32(); } - y[sub( Nm1, imult1616( Nm1, shl( kernelType, 1 ) ) )] = L_shr( re[0], 1 ); + y[sub( Nm1, imult1616( Nm1, shr( kernelType, 1 ) ) )] = L_shr( re[0], 1 ); move32(); } ELSE /* inverse II = III */ diff --git a/lib_com/fd_cng_com_fx.c b/lib_com/fd_cng_com_fx.c index 825d13cbbc441fc4b24ba501b7b87a8843acf750..8f55280149576e393514336613c8ecab6cf37edc 100644 --- a/lib_com/fd_cng_com_fx.c +++ b/lib_com/fd_cng_com_fx.c @@ -10,6 +10,7 @@ #include "rom_basop_util.h" #include "rom_com.h" #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot_fx.h" #define DELTA_SHIFT 2 @@ -2471,6 +2472,147 @@ void AnalysisSTFT_fx( } #endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------- + * SynthesisSTFT_enc_ivas_fx() + * + * STFT synthesis filterbank + *-------------------------------------------------------------------*/ + +void SynthesisSTFT_enc_ivas_fx( + Word32 *fftBuffer, /* i : pointer to FFT bins */ + Word16 fftBufferExp, /* i : exponent of FFT bins */ + Word16 *timeDomainOutput, /* o : pointer to time domain signal */ + Word16 *olapBuffer, /* i/o : pointer to overlap buffer */ + const PWord16 *olapWin, /* i : pointer to overlap window */ + Word16 tcx_transition, + HANDLE_FD_CNG_COM hFdCngCom, /* i/o : pointer to FD_CNG structure containing all buffers and variables */ + Word16 gen_exc, + Word16 *Q_new, /* i : Q of generated exc_cng */ + const Word16 element_mode, /* i : element mode */ + const Word16 nchan_out /* i : number of output channels */ +) +{ + Word16 i, len, scale, tmp; + Word16 len2, len3, len4; + Word16 buf[M + 1 + L_FRAME16k]; + + + /* Perform IFFT */ + scale = 0; + move16(); + BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 ); + fftBufferExp = add( fftBufferExp, scale ); + hFdCngCom->fftBuffer_exp = fftBufferExp; + move16(); + + fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift ); + + /* Perform overlap-add */ + /* Handle overlap in P/S domain for stereo */ + test(); + test(); + IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) ) + { + Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 ); + set16_fx( olapBuffer, 0, hFdCngCom->fftlen ); + } + ELSE + { + Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize ); + set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); + } + len2 = shr( hFdCngCom->fftlen, 2 ); + len4 = shr( hFdCngCom->fftlen, 3 ); + len3 = add( len2, len4 ); + len = add( hFdCngCom->frameSize, len4 ); + IF( tcx_transition ) + { + FOR( i = 0; i < len; i++ ) + { + olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); + move16(); + } + } + ELSE + { + FOR( i = 0; i < len4; i++ ) + { + olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 1 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.im ) ); + move16(); + olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 2 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.re ) ); + move16(); + } + FOR( i = len3; i < len; i++ ) + { + olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); + move16(); + } + } + + FOR( i = 0; i < len4; i++ ) + { + olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.re ); + move16(); + olapBuffer[i + 6 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 6 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.im ); + move16(); + } + + len = add( len, len2 ); + FOR( i = len; i < hFdCngCom->fftlen; i++ ) + { + olapBuffer[i] = 0; + move16(); + } + + /* Get time-domain signal */ + FOR( i = 0; i < hFdCngCom->frameSize; i++ ) + { + timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac ); + move16(); + } + /* Generate excitation */ + test(); + test(); + IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) ) + { + FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ ) + { + buf[i + ( M + 1 )] = add( buf[i + ( M + 1 )], olapBuffer[i + hFdCngCom->frameSize / 4] ); + move16(); + } + + FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ ) + { + buf[i] = mult_r( buf[i], hFdCngCom->fftlenFac ); + move16(); + } + } + ELSE + { + FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ ) + { + buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac ); + move16(); + } + tmp = buf[0]; + move16(); + } + IF( EQ_16( gen_exc, 1 ) ) + { + + E_UTIL_f_preemph2( sub( *Q_new, 1 ), buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp ); + Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 ); + } + IF( EQ_16( gen_exc, 2 ) ) + { + *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp, 1 ); + move16(); + Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 ); + } +} +#endif + /*------------------------------------------------------------------- * SynthesisSTFT() * diff --git a/lib_com/float_to_fix_ops.c b/lib_com/float_to_fix_ops.c index 7a081f35137dabf9796d96f7fcb8f07e9e3b1018..432bc2d2e2b168fcee1d4a5e45a0830cda7d5c6e 100644 --- a/lib_com/float_to_fix_ops.c +++ b/lib_com/float_to_fix_ops.c @@ -78,6 +78,13 @@ void floatToFixed_arr32( float *f, Word32 *i, Word16 Q, Word16 l ) } } +float fixedToFloat_16( Word16 i, Word16 Q ) +{ + if ( Q < 0 ) + return ( i * (float) ( ( (unsigned) 1 ) << ( -Q ) ) ); + else + return (float) ( i ) / (float) ( (unsigned int) 1 << Q ); +} float fixedToFloat_32( Word32 number, Word16 Q ) { float val = 0.0f; diff --git a/lib_com/hq_tools_fx.c b/lib_com/hq_tools_fx.c index f83d20ccdcf983ef13640c7c5453a4f4fb63304c..5ce39824715e87b581e27a607693d7a4f8da1d4e 100644 --- a/lib_com/hq_tools_fx.c +++ b/lib_com/hq_tools_fx.c @@ -431,7 +431,7 @@ void apply_noisefill_HQ_fx( { cb_buff[i] = CodeBook_mod[cb_pos++]; move16(); - L_E_cb_vec = L_mac0( L_E_cb_vec, cb_buff[i], cb_buff[i] ); /*Q24 (12+12) */ + L_E_cb_vec = L_mac0_sat( L_E_cb_vec, cb_buff[i], cb_buff[i] ); /*Q24 (12+12) */ if ( GE_16( cb_pos, cb_size ) ) { @@ -446,7 +446,7 @@ void apply_noisefill_HQ_fx( { cb_buff[i] = CodeBook[cb_pos++]; move16(); - L_E_cb_vec = L_mac0( L_E_cb_vec, cb_buff[i], cb_buff[i] ); /*Q24 (12+12) */ + L_E_cb_vec = L_mac0_sat( L_E_cb_vec, cb_buff[i], cb_buff[i] ); /*Q24 (12+12) */ if ( GE_16( cb_pos, cb_size ) ) { diff --git a/lib_com/igf_base_fx.c b/lib_com/igf_base_fx.c index 6b7b31be7a61c8951f0d930a4b337f353c7cf99a..b087695b580c010b2939c9fffc6fd928f3d7c8a2 100644 --- a/lib_com/igf_base_fx.c +++ b/lib_com/igf_base_fx.c @@ -893,7 +893,7 @@ static void IGF_gridSetUp_ivas_fx( Word16 bitRateIndex, /* i : IGF bitrate index */ const Word32 sampleRate, /* i : sample rate */ Word16 frameLength, /* i : frame length */ - const Word16 transFac, /* i : transFac */ + const Word16 transFac, /* i : transFac, Q14 */ const Word16 igfMinFq /* i : IGF minimum frequency indicating lower start frequency for copy up */ ) { diff --git a/lib_com/int_lsp.c b/lib_com/int_lsp.c index b6528030e17949b4ff1af298ed0996668d5d87ae..522f62fe0568f9c1a16c907938055edd0a7e15b9 100644 --- a/lib_com/int_lsp.c +++ b/lib_com/int_lsp.c @@ -314,3 +314,82 @@ void int_lsp4_fx( return; } + +void int_lsp4_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +) +{ + Word16 lsp[M16k]; + Word16 i, j, k; + Word32 L_tmp; + const Word16 *pt_int_coeffs; + + IF( EQ_16( L_frame, L_FRAME ) ) + { + IF( EQ_16( relax_prev_lsf_interp, 1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_12k8_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, 2 ) ) + { + pt_int_coeffs = interpol_frac_mid_FEC_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_12k8_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -2 ) ) + { + pt_int_coeffs = interpol_frac2_mid_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_fx; + } + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( EQ_16( relax_prev_lsf_interp, 1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_16k_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, 2 ) ) + { + pt_int_coeffs = interpol_frac_mid_16k_FEC_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_16k_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_16k_fx; + } + } + k = sub( shr( L_frame, 6 ), 1 ); + FOR( j = 0; j < k; j++ ) + { + FOR( i = 0; i < m; i++ ) + { + L_tmp = L_mult( lsp_old[i], *pt_int_coeffs ); /*Q31 */ + L_tmp = L_mac( L_tmp, lsp_mid[i], *( pt_int_coeffs + 1 ) ); /*Q31 */ + lsp[i] = mac_r( L_tmp, lsp_new[i], *( pt_int_coeffs + 2 ) ); + move16(); + } + pt_int_coeffs += 3; + + E_LPC_f_lsp_a_conversion( lsp, Aq, m ); + Aq += add( m, 1 ); + } + + /* Last subframe */ + E_LPC_f_lsp_a_conversion( lsp_new, Aq, m ); + + return; +} diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index d6ac3843e45313d174d6e075ae7321b4095c700b..7c23752cfb36b045ff2234961ef0997b89c16d0d 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -644,7 +644,9 @@ typedef enum #define STEREO_DFT_RES_GAINS_BITS 3 #define STEREO_DFT_RES_COD_SNR_MIN 10 +#define STEREO_DFT_RES_COD_SNR_MIN_Q25 335544320 #define STEREO_DFT_RES_COD_SNR_MAX 40 +#define STEREO_DFT_RES_COD_SNR_MAX_Q25 1342177280 #define STEREO_DFT_L_SUBFR_8k 32 #define STEREO_DFT_NBPSF_PIT_MAX_8k NBPSF_PIT_MAX / 2 @@ -727,6 +729,7 @@ enum #define ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO 127 /* indicates that all values in the vector are zero */ #define ECLVQ_GLOBAL_GAIN_FACTOR ( 20.0f * 127.0f / 90.0f ) +#define ECLVQ_GLOBAL_GAIN_FACTOR_Q26 1893961218 #define ECLVQ_INV_GLOBAL_GAIN_FACTOR ( 1.0f / ( 20.0f * 127.0f / 90.0f ) ) #define ECLVQ_INV_GLOBAL_GAIN_FACTOR_Q24 594468 @@ -821,7 +824,13 @@ enum fea_names #define STEREO_BITS_TCA_CORRSTATS 5 /* target corrStats */ #define STEREO_BITS_TCA_GD 5 /* target gain */ #define STEREO_TCA_GDMIN -1.0f +#define STEREO_TCA_GDMIN_FX -32768 #define STEREO_TCA_GDSTEP 0.05f +#define STEREO_TCA_GDSTEP_FX 819 +#ifdef IVAS_FLOAT_FIXED +#define STEREO_TCA_GDMIN_FX_Q14 (-16384) +#define STEREO_TCA_GDSTEP_FX_Q13 (410) +#endif #define STEREO_BITS_TCA ( STEREO_BITS_TCA_CHAN + STEREO_BITS_TCA_CORRSTATS + STEREO_BITS_TCA_GD ) #define STEREO_ICBWE_MSFLAG_BITS 1 /* BWE Multi Source flag */ @@ -837,6 +846,7 @@ enum fea_names #define MAX_DELAYREGLEN 12 /* max regression length */ #define INV_MAX_DELAYREGLEN 0.083333333333333f /* (1/MAX_DELAYREGLEN) */ +#define INV_MAX_DELAYREGLEN_FX_Q15 2731 /* (1/MAX_DELAYREGLEN) */ #define MAX_INTERPOLATE 11 #define ADDED_MEM_DS 40 @@ -1276,6 +1286,9 @@ enum #define MASA_COHERENCE_TOLERANCE 0.1f #define MASA_COHERENCE_THRESHOLD 0.1f +#ifdef IVAS_FLOAT_FIXED +#define MASA_COHERENCE_THRESHOLD_FX 214748365 // 0.1 in Q31 +#endif #define MASA_RATIO_TOLERANCE 0.1f #define MASA_RATIO_THRESHOLD 0.1f #define MASA_ANGLE_TOLERANCE 0.5f diff --git a/lib_com/ivas_fb_mixer.c b/lib_com/ivas_fb_mixer.c index b84a8b772421828ece91537939e4a693cb332c66..1c6a82a99ff789726a253103bc76250c86f96ac6 100644 --- a/lib_com/ivas_fb_mixer.c +++ b/lib_com/ivas_fb_mixer.c @@ -359,6 +359,18 @@ ivas_error ivas_FB_mixer_open( { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } + +#ifdef IVAS_FLOAT_FIXED + if ( ( hFbMixer->ppFilterbank_inFR_re_fx[j] = (Word32 *) malloc( sizeof( Word32 ) * frame_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + + if ( ( hFbMixer->ppFilterbank_inFR_im_fx[j] = (Word32 *) malloc( sizeof( Word32 ) * frame_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } +#endif } } @@ -378,8 +390,26 @@ ivas_error ivas_FB_mixer_open( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } set_f( hFbMixer->ppFilterbank_prior_input[i], 0, fb_cfg->prior_input_length ); +#ifdef IVAS_FLOAT_FIXED + IF( ( hFbMixer->ppFilterbank_prior_input_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * fb_cfg->prior_input_length ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + set32_fx( hFbMixer->ppFilterbank_prior_input_fx[i], 0, fb_cfg->prior_input_length ); +#endif } +#ifdef IVAS_FLOAT_FIXED + FOR( i = 0; i < num_chs_alloc; i++ ) + { + IF( ( hFbMixer->ppFilterbank_prior_input_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * fb_cfg->prior_input_length ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + set32_fx( hFbMixer->ppFilterbank_prior_input_fx[i], 0, fb_cfg->prior_input_length ); + } +#endif + if ( ( fb_cfg->active_w_mixing != -1 ) && ( fb_cfg->num_out_chans > 0 ) ) { float *pTemp_mem; @@ -560,6 +590,27 @@ ivas_error ivas_FB_mixer_open_fx( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } } +#if 1 // TODO: To be removed later + if ( fb_cfg->num_out_chans == 0 ) + { + hFbMixer->ppFilterbank_inFR_re[i] = NULL; + hFbMixer->ppFilterbank_inFR_im[i] = NULL; + } + else + { + j = fb_cfg->remix_order[i]; + + if ( ( hFbMixer->ppFilterbank_inFR_re[j] = (float *) malloc( sizeof( float ) * frame_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + + if ( ( hFbMixer->ppFilterbank_inFR_im[j] = (float *) malloc( sizeof( float ) * frame_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + } +#endif } IF( EQ_16( fb_cfg->active_w_mixing, -1 ) ) @@ -579,6 +630,13 @@ ivas_error ivas_FB_mixer_open_fx( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); } set32_fx( hFbMixer->ppFilterbank_prior_input_fx[i], 0, fb_cfg->prior_input_length ); +#if 1 // TODO: To be removed later + if ( ( hFbMixer->ppFilterbank_prior_input[i] = (float *) malloc( sizeof( float ) * fb_cfg->prior_input_length ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + set_f( hFbMixer->ppFilterbank_prior_input[i], 0, fb_cfg->prior_input_length ); +#endif } test(); @@ -598,6 +656,22 @@ ivas_error ivas_FB_mixer_open_fx( set32_fx( hFbMixer->prior_mixer_fx[i][j], 0, IVAS_MAX_NUM_BANDS ); } } +#if 1 // TODO: To be removed later + float *pTemp_mem; + if ( ( pTemp_mem = (float *) malloc( sizeof( float ) * fb_cfg->num_out_chans * max( fb_cfg->num_in_chans, fb_cfg->nchan_fb_in ) * IVAS_MAX_NUM_BANDS ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer" ); + } + for ( i = 0; i < fb_cfg->num_out_chans; i++ ) + { + for ( j = 0; j < fb_cfg->num_in_chans; j++ ) + { + hFbMixer->prior_mixer[i][j] = pTemp_mem; + pTemp_mem += IVAS_MAX_NUM_BANDS; + set_f( hFbMixer->prior_mixer[i][j], 0, IVAS_MAX_NUM_BANDS ); + } + } +#endif } IF( !spar_reconfig_flag ) @@ -618,6 +692,12 @@ ivas_error ivas_FB_mixer_open_fx( { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder fixed" ); } +#if 1 // TODO: To be removed later + if ( ( hFbMixer->pFb->fb_bin_to_band.pFb_bin_to_band[i] = (float *) malloc( sizeof( float ) * pActive_bins_per_band_abs[i] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } +#endif } } @@ -634,6 +714,17 @@ ivas_error ivas_FB_mixer_open_fx( FOR( j = start_diff_band_non48k; j < num_bands; j++ ) { +#if 1 // TODO: To be removed later + if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[0][j] = (float *) malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } + + if ( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k[1][j] = (float *) malloc( sizeof( float ) * pActive_bins_per_band[j] ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); + } +#endif IF( ( hFbMixer->pFb->fb_consts.ppFilterbank_FRs_non48k_fx[0][j] = (Word32 *) malloc( sizeof( Word32 ) * pActive_bins_per_band[j] ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FB mixer encoder" ); @@ -666,6 +757,12 @@ ivas_error ivas_FB_mixer_open_fx( { return error; } +#if 1 // TODO: To be removed later + if ( ( error = ivas_filterbank_setup( hFbMixer, sampling_rate ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif } *hFbMixer_out = hFbMixer; @@ -721,6 +818,13 @@ void ivas_FB_mixer_close( free( hFbMixer->ppFilterbank_inFR_im[j] ); hFbMixer->ppFilterbank_inFR_im[j] = NULL; +#ifdef IVAS_FLOAT_FIXED + free( hFbMixer->ppFilterbank_inFR_re_fx[j] ); + hFbMixer->ppFilterbank_inFR_re_fx[j] = NULL; + + free( hFbMixer->ppFilterbank_inFR_im_fx[j] ); + hFbMixer->ppFilterbank_inFR_im_fx[j] = NULL; +#endif } } @@ -738,7 +842,13 @@ void ivas_FB_mixer_close( free( hFbMixer->ppFilterbank_prior_input[i] ); hFbMixer->ppFilterbank_prior_input[i] = NULL; } - +#ifdef IVAS_FLOAT_FIXED + for ( i = 0; i < num_chs_alloc; i++ ) + { + free( hFbMixer->ppFilterbank_prior_input_fx[i] ); + hFbMixer->ppFilterbank_prior_input_fx[i] = NULL; + } +#endif if ( ( fb_cfg->active_w_mixing != -1 ) && ( fb_cfg->num_out_chans > 0 ) ) { free( hFbMixer->prior_mixer[0][0] ); @@ -976,7 +1086,77 @@ void ivas_fb_mixer_pcm_ingest( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_fb_mixer_pcm_ingest_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in[], /* i : input audio channels Qq_data_fix[] */ + Word32 **ppOut_pcm, /* o : output audio channels Qq_ppOut_pcm[] */ + const Word16 frame_len, /* i : frame length */ + const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH], + Word16 q_data_fix[MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS], + Word16 *q_ppOut_pcm ) +{ + Word16 i; + Word16 num_chs_ingest; + IVAS_FB_CFG *fb_cfg = hFbMixer->fb_cfg; + + IF( fb_cfg->active_w_mixing ) + { + num_chs_ingest = fb_cfg->num_in_chans; + move16(); + } + ELSE + { + num_chs_ingest = 1; /* forward Filterbank MDFT only on W */ + move16(); + } + + + FOR( i = 0; i < fb_cfg->num_in_chans; i++ ) + { + Word16 q_temp = s_min( hFbMixer->q_ppFilterbank_prior_input_fx[i], q_data_fix[HOA_md_ind[i]] ); + + + // mvr2r(&hFbMixer->ppFilterbank_prior_input[i][fb_cfg->prior_input_length - frame_len], ppOut_pcm[i], frame_len); + Copy32( &hFbMixer->ppFilterbank_prior_input_fx[i][fb_cfg->prior_input_length - frame_len], ppOut_pcm[i], frame_len ); + + IF( LT_16( q_temp, hFbMixer->q_ppFilterbank_prior_input_fx[i] ) ) + { + FOR( Word16 x = 0; x < frame_len; x++ ) + { + ppOut_pcm[i][x] = L_shr( ppOut_pcm[i][x], sub( hFbMixer->q_ppFilterbank_prior_input_fx[i], q_temp ) ); + move32(); + } + } + // mvr2r(pcm_in[HOA_md_ind[i]], &ppOut_pcm[i][frame_len], frame_len); + Copy32( pcm_in[HOA_md_ind[i]], &ppOut_pcm[i][frame_len], frame_len ); + + IF( LT_16( q_temp, q_data_fix[HOA_md_ind[i]] ) ) + { + FOR( Word16 x = frame_len; x < shl( frame_len, 1 ); x++ ) + { + ppOut_pcm[i][x] = L_shr( ppOut_pcm[i][x], sub( q_data_fix[HOA_md_ind[i]], q_temp ) ); + move32(); + } + } + q_ppOut_pcm[i] = q_temp; + move16(); + } + + Word16 guard_bits = find_guarded_bits_fx( shl( frame_len, 1 ) ); + + FOR( i = 0; i < num_chs_ingest; i++ ) + { + Word16 q_shift = sub( getScaleFactor32( ppOut_pcm[fb_cfg->remix_order[i]], shl( frame_len, 1 ) ), guard_bits ); + Scale_sig32( ppOut_pcm[fb_cfg->remix_order[i]], shl( frame_len, 1 ), q_shift ); + q_ppOut_pcm[fb_cfg->remix_order[i]] = add( q_ppOut_pcm[fb_cfg->remix_order[i]], q_shift ); + + ivas_mdft_fx( ppOut_pcm[fb_cfg->remix_order[i]], hFbMixer->ppFilterbank_inFR_re_fx[fb_cfg->remix_order[i]], hFbMixer->ppFilterbank_inFR_im_fx[fb_cfg->remix_order[i]], shl( frame_len, 1 ), frame_len ); + } + return; +} +#endif /*-----------------------------------------------------------------------------------------* * Function ivas_fb_mixer_update_prior_input() @@ -1002,6 +1182,26 @@ void ivas_fb_mixer_update_prior_input( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_fb_mixer_update_prior_input_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in_fx[], /* i : input audio channels */ + const Word16 length, /* i : length of time slot */ + const Word16 nchan_fb_in /* i : number of analysis channels */ +) +{ + Word16 i; + + FOR( i = 0; i < nchan_fb_in; i++ ) + { + Copy32( &hFbMixer->ppFilterbank_prior_input_fx[i][length], hFbMixer->ppFilterbank_prior_input_fx[i], hFbMixer->fb_cfg->prior_input_length - length ); + Copy32( pcm_in_fx[i], &hFbMixer->ppFilterbank_prior_input_fx[i][hFbMixer->fb_cfg->prior_input_length - length], length ); + } + + return; +} +#endif + /*-----------------------------------------------------------------------------------------* * Function ivas_fb_mixer_get_windowed_fr() @@ -1009,6 +1209,61 @@ void ivas_fb_mixer_update_prior_input( * *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_fb_mixer_get_windowed_fr_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in_fx[], + Word32 *frame_f_real_fx[], + Word32 *frame_f_imag_fx[], + const Word16 length, /* i : number of new samples in time slot */ + const Word16 mdft_len, /* i : MDFT frame length */ + const Word16 nchan_fb_in, /* i : number of analysis channels */ + Word16 gb ) +{ + Word16 ch_idx, j, offset, rev_offset; + Word16 n_old_samples; + Word16 n_new_samples; + Word32 fr_in_block_fx[L_FRAME48k * 2]; + const Word16 *win_ptr_fx; + + n_old_samples = s_min( ( sub( hFbMixer->fb_cfg->prior_input_length, hFbMixer->fb_cfg->windowed_fr_offset ) ), ( shl( mdft_len, 1 ) ) ); + n_new_samples = s_max( 0, sub( shl( length, 1 ), n_old_samples ) ); + offset = (Word16) ( sub( sub( shl( mdft_len, 1 ), length ), hFbMixer->ana_window_offset ) ); + rev_offset = (Word16) ( sub( shl( mdft_len, 1 ), hFbMixer->ana_window_offset ) ); + set32_fx( fr_in_block_fx, 0, offset ); + + FOR( ch_idx = 0; ch_idx < nchan_fb_in; ch_idx++ ) + { + Copy32( &hFbMixer->ppFilterbank_prior_input_fx[ch_idx][offset + hFbMixer->fb_cfg->windowed_fr_offset], &fr_in_block_fx[offset], n_old_samples - offset ); + Copy32( pcm_in_fx[ch_idx], &fr_in_block_fx[n_old_samples], n_new_samples ); + + win_ptr_fx = hFbMixer->pAna_window_fx; /*Q15*/ + + FOR( j = offset; j < sub( shl( mdft_len, 1 ), length ); j++ ) + { + fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( win_ptr_fx++ ) ) ); + move16(); + } + + FOR( j = rev_offset; j < shl( mdft_len, 1 ); j++ ) + { + fr_in_block_fx[j] = Mpy_32_16_1( fr_in_block_fx[j], ( *( --win_ptr_fx ) ) ); + move16(); + } + + FOR( Word16 i = 0; i < shl( mdft_len, 1 ); i++ ) + { + fr_in_block_fx[i] = L_shr( fr_in_block_fx[i], gb ); + move16(); + } + + ivas_mdft_fx( fr_in_block_fx, frame_f_real_fx[ch_idx], frame_f_imag_fx[ch_idx], mdft_len << 1, mdft_len ); + } + + return; +} +#endif + void ivas_fb_mixer_get_windowed_fr( IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ float *pcm_in[], /* i : input audio channels */ @@ -1989,6 +2244,12 @@ static ivas_error ivas_filterbank_setup( { return error; } +#ifdef IVAS_FLOAT_FIXED + IF( ( error = ivas_fb_mixer_get_window_fx( pCfg->fb_latency, sampling_rate, &( hFbMixer->pAna_window_fx ) ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif if ( ( error = ivas_fb_mixer_get_window( pCfg->fade_len, sampling_rate, &( hFbMixer->pFilterbank_cross_fade ) ) ) != IVAS_ERR_OK ) { diff --git a/lib_com/ivas_ism_com.c b/lib_com/ivas_ism_com.c index 82a5ba5884fad693d101e4992c4775fe59cc84e6..458e473aaf848d7093a359a2f0f54cb6e8a2c926 100644 --- a/lib_com/ivas_ism_com.c +++ b/lib_com/ivas_ism_com.c @@ -1140,6 +1140,10 @@ void ivas_param_ism_config_fx( hParamIsm->last_dmx_gain_e = 1; move16(); set16_fx( hParamIsm->last_cardioid_left_fx, (Word16) 16384, MAX_NUM_OBJECTS ); +#if 1 // TODO: To be removed later + hParamIsm->last_dmx_gain = 1.0f; + set_f( hParamIsm->last_cardioid_left, 1.0f, MAX_NUM_OBJECTS ); +#endif return; } diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 51a7644727c618f5439f4d63475712ccc155d725..b352b4803c386a6ef89082867955c2845c09f56e 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -159,7 +159,7 @@ void destroy_cpe_enc( void ivas_mct_enc_close( MCT_ENC_HANDLE *hMCT /* i/o: MCT encoder structure */ ); - +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_corecoder_enc_reconfig( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t nSCE_old, /* i : number of SCEs in previous frame */ @@ -169,7 +169,7 @@ ivas_error ivas_corecoder_enc_reconfig( const int32_t brate_CPE, /* i : bitrate to be set for the CPEs */ const MC_MODE last_mc_mode /* i : switching between MC modes: last mode */ ); - +#endif ivas_error ivas_sce_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t sce_id, /* i : SCE # identifier */ @@ -258,6 +258,7 @@ ivas_error pre_proc_front_ivas_fx( const int16_t nb_bits_metadata, /* i : number of metadata bits */ const int16_t input_frame, /* i : frame length */ const int16_t n, /* i : channel number */ + Word16 old_inp_12k8_fx[], /* o : buffer of old input signal */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ float *ener, /* o : residual energy from Levinson-Durbin */ @@ -279,6 +280,7 @@ ivas_error pre_proc_front_ivas_fx( int16_t *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* o : energy buffer */ float fft_buff[2 * L_FFT], /* o : FFT buffer */ + Word16 fft_buff_fx[2 * L_FFT], /* o : FFT buffer */ const float tdm_A_PCh[M + 1], /* i : unq. LP coeff. of primary channel */ const float tdm_lsp_new_PCh[M], /* i : unq. LSPs of primary channel */ const float currFlatness, /* i : flatness parameter */ @@ -315,29 +317,51 @@ ivas_error pre_proc_ivas( int16_t *Voicing_flag, /* o : voicing flag for HQ FEC */ const float old_wsp[], /* i : weighted input signal buffer */ const int16_t loc_harm, /* i : harmonicity flag */ +#ifndef IVAS_FLOAT_FIXED const float cor_map_sum, /* i : speech/music clasif. parameter */ +#endif const int16_t vad_flag_dtx, /* i : HE-SAD flag with additional DTX HO */ - const float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ - const float fft_buff[2 * L_FFT], /* i : FFT buffer */ +#ifndef IVAS_FLOAT_FIXED + /*const*/ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ + /*const*/ float fft_buff[2 * L_FFT], /* i : FFT buffer */ +#endif const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ const int16_t vad_hover_flag, /* i : VAD hangover flag */ const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ +#ifdef IVAS_FLOAT_FIXED + , + Word32 enerBuffer_fx[CLDFB_NO_CHANNELS_MAX], + Word16 e_enerBuffer, + Word16 fft_buff_fx[2 * L_FFT], + Word32 cor_map_sum_fx, + Word16 exp_cor_map_sum +#endif ); ivas_error ivas_compute_core_buffers( - Encoder_State *st, /* i/o: encoder state structure */ - float **inp16k_out, /* o : ptr. to inp. signal in the current frame*/ - float *old_inp_16k, /* i/o: buffer of old input signal @ 16kHz */ - float new_inp_resamp16k[], /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ - const int16_t input_frame, /* i : frame length */ - const int16_t last_element_mode, /* i : last element mode */ - const int32_t sr_core, /* i : core-coder sampling rate */ - float *ener, /* o : residual energy from Levinson-Durbin */ - float A[NB_SUBFR16k * ( M + 1 )], /* i/o: A(z) unquantized for the 4 subframes */ - float Aw[NB_SUBFR16k * ( M + 1 )], /* i/o: weighted A(z) unquantized for subframes */ - float epsP[M + 1], /* i/o: LP prediction errors */ - float lsp_new[M], /* i/o: LSPs at the end of the frame */ - float lsp_mid[M] /* i/o: LSPs in the middle of the frame */ + Encoder_State *st, /* i/o: encoder state structure */ + float **inp16k_out, /* o : ptr. to inp. signal in the current frame */ + float *old_inp_16k, /* i/o: buffer of old input signal @ 16kHz */ + float new_inp_resamp16k_out[], /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + const int16_t input_frame, /* i : frame length */ + const int16_t last_element_mode, /* i : last element mode */ + const int32_t sr_core, /* i : core-coder sampling rate */ + float *ener, /* o : residual energy from Levinson-Durbin */ +#ifndef IVAS_FLOAT_FIXED + float A[NB_SUBFR16k * (M + 1)], /* i/o: A(z) unquantized for the 4 subframes */ + float Aw[NB_SUBFR16k * (M + 1)], /* i/o: weighted A(z) unquantized for subframes */ +#else + Word16 A_fx[NB_SUBFR16k * (M + 1)], /* i/o: A(z) unquantized for the 4 subframes */ + Word16 Aw_Fx[NB_SUBFR16k * (M + 1)], /* i/o: weighted A(z) unquantized for subframes */ +#endif + float epsP[M + 1], /* i/o: LP prediction errors */ +#ifndef IVAS_FLOAT_FIXED + float lsp_new[M], /* i/o: LSPs at the end of the frame */ + float lsp_mid[M] /* i/o: LSPs in the middle of the frame */ +#else + Word16 lsp_new_fx[M], /* i/o: LSPs at the end of the frame */ + Word16 lsp_mid_fx[M] /* i/o: LSPs in the middle of the frame */ +#endif ); /*! r: number of clipped samples */ @@ -635,6 +659,7 @@ ivas_error ivas_core_dec( #endif +#ifndef IVAS_FLOAT_FIXED void encod_gen_2sbfr( Encoder_State *st, /* i/o: state structure */ const float speech[], /* i : input speech */ @@ -650,6 +675,7 @@ void encod_gen_2sbfr( const int16_t tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ const float tdm_Pri_pitch_buf[] /* i : pitch values for primary channel */ ); +#endif void decod_gen_2sbfr( Decoder_State *st, /* i/o: decoder static memory */ @@ -701,6 +727,7 @@ void stereo_tcx_init_enc( Encoder_State *st /* i/o: encoder state structure */ ); +#ifndef IVAS_FLOAT_FIXED void stereo_tcx_core_enc( Encoder_State *st, /* i/o: encoder state structure */ const float new_samples_12k8[], /* i : buffer of input signal @12.8 kHz */ @@ -713,7 +740,6 @@ void stereo_tcx_core_enc( const int16_t vad_hover_flag /* i : VAD hangover flag */ ); -#ifndef IVAS_FLOAT_FIXED void stereo_tcx_core_dec( Decoder_State *st, /* i/o: decoder state structure */ const FRAME_MODE frameMode, /* i : Decoder frame mode */ @@ -785,20 +811,23 @@ void ivas_smc_mode_selection( ); /*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ +#ifndef IVAS_FLOAT_FIXED int16_t ivas_acelp_tcx20_switching( - Encoder_State *st, /* i/o: encoder state structure */ - const float *inp, /* i : new input signal */ - const float *wsp, /* i : input weighted signal */ - const float non_staX, /* i : unbound non-stationarity for sp/mu clas */ - const float *pitch_fr, /* i : fraction pitch values */ - const float *voicing_fr, /* i : fractional voicing values */ - const float currFlatness, /* i : flatness */ - const float lsp_mid[M], /* i : LSPs at the middle of the frame */ - const float stab_fac, /* i : LP filter stability */ - float *res_cod_SNR_M, - const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ + Encoder_State *st, /* i/o: encoder state structure */ + const float *inp, /* i : new input signal */ + const float *wsp, /* i : input weighted signal */ + const float non_staX, /* i : unbound non-stationarity for sp/mu clas */ + const float *pitch_fr, /* i : fraction pitch values */ + const float *voicing_fr, /* i : fractional voicing values */ + const float currFlatness, /* i : flatness */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + const float stab_fac, /* i : LP filter stability */ + float *res_cod_SNR_M, + const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ ); +#endif +#ifndef IVAS_FLOAT_FIXED void ivas_decision_matrix_enc( Encoder_State *st, /* i/o: encoder state structure */ const int32_t element_brate, /* i : element bitrate */ @@ -806,6 +835,16 @@ void ivas_decision_matrix_enc( const float enerBuffer[], /* i : energy buffer */ const int16_t last_element_mode /* i : last element mode */ ); +#else +void ivas_decision_matrix_enc_fx( + Encoder_State *st, /* i : encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + const Word16 fft_buff[], /* i : FFT buffer */ + const Word32 enerBuffer[], /* i : energy buffer */ + Word16 enerBuffer_exp, + const Word16 last_element_mode /* i : last element mode */ +); +#endif #ifdef IVAS_FLOAT_FIXED void ivas_signaling_enc_fx( @@ -1409,12 +1448,7 @@ ivas_error ivas_ism_metadata_dec( *----------------------------------------------------------------------------------*/ /*! r: ISM format mode */ -#ifdef IVAS_FLOAT_FIXED -ISM_MODE ivas_ism_mode_select( - const Word16 nchan_inp, /* i : number of input objects */ - const Word32 ivas_total_brate /* i : IVAS total bitrate */ -); -#else +#ifndef IVAS_FLOAT_FIXED ISM_MODE ivas_ism_mode_select( const int16_t nchan_inp, /* i : number of input objects */ const int32_t ivas_total_brate /* i : IVAS total bitrate */ @@ -1424,12 +1458,13 @@ ISM_MODE ivas_ism_mode_select( ivas_error ivas_param_ism_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); - +#ifndef IVAS_FLOAT_FIXED void ivas_param_ism_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ float *data[MAX_NUM_OBJECTS], /* i : input signal */ const int16_t input_frame /* i : input frame length per channel */ ); +#endif void ivas_param_ism_enc_close( PARAM_ISM_CONFIG_HANDLE *hParamIsm, /* i/o: ParamISM handle */ @@ -1441,11 +1476,13 @@ void ivas_ism_metadata_close( const int16_t first_idx /* i : index of first handle to deallocate */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_param_ism_stereo_dmx( Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ float *data[MAX_NUM_OBJECTS], /* i/o: input signal/stereo dmx */ const int16_t input_frame /* i : Length of input frame */ ); +#endif void ivas_param_ism_config( PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i/o: IVAS Param ISM Config Structure */ @@ -1753,19 +1790,6 @@ void stereo_dft_enc_analyze( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_enc_analyze_fx( - Encoder_State **sts, /* i/o: encoder state structure */ - const Word16 n_channels, /* i : number of input channels */ - const Word16 input_frame, /* i : input frame length */ - STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ - STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ - Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ - Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ - Word16 *q_input_mem - ); -#endif - float stereo_dft_enc_synthesize( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ float *output, /* o : output synthesis */ @@ -1784,6 +1808,7 @@ void stereo_dft_enc_process( ); #endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_res( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ const float *input_8k, /* i : input buffer sampled at 8kHz */ @@ -1791,11 +1816,14 @@ void stereo_dft_enc_res( int16_t *nb_bits, /* o : number of bits written */ const int16_t max_bits ); +#endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_write_BS( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ int16_t *nb_bits /* o : number of bits written */ ); +#endif void stereo_dtf_cng( CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ @@ -1844,6 +1872,7 @@ void stereo_dft_dequantize_itd( const int32_t output_Fs ); +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_sid_calc_coh( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ float prev_cohBand[2*(STEREO_DFT_BAND_MAX/2)], /* i/o: Previous coherence */ @@ -1851,7 +1880,9 @@ void stereo_dft_enc_sid_calc_coh( int16_t *first_SID, /* i/o: First SID indicator */ float *cohBand /* i/o: Coherence per band */ ); +#endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_sid_coh( BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ float *mem_cohBand, /* i/o: Coherence memory */ @@ -1859,6 +1890,7 @@ void stereo_dft_enc_sid_coh( int16_t *nb_bits, /* i/o: number of bits written */ float *cohBand /* i/o: Coherence per band */ ); +#endif #ifdef IVAS_FLOAT_FIXED void stereo_dft_dec_sid_coh_fx( Decoder_State *st, /* i/o: decoder state structure */ @@ -2003,7 +2035,8 @@ int16_t res_bpf_adapt( Word16 res_bpf_adapt_ivas_fx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo decoder handle */ const Word32 *bpf_error_signal_8k, /* i : BPF modification signal */ - Word32 res_buf[STEREO_DFT_N_8k] /* i : residual buffer Q12 */ + Word32 res_buf[STEREO_DFT_N_8k], /* i : residual buffer Q_res */ + Word16 q_res ); #endif void bpf_pitch_coherence( @@ -2262,22 +2295,6 @@ void stereo_dft_hybrid_ITD_flag( const Word16 hybrid_itd_max /* i : flag for hybrid ITD for very large ITDs */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_enc_compute_itd_fx( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - Word32 *DFT_L, - Word16 *DFT_L_e, - Word32 *DFT_R, - Word16 *DFT_R_e, - const Word16 k_offset, - const Word16 input_frame, - const Word16 vad_flag_dtx[], - const Word16 vad_hover_flag[], - Word32 *bin_nrgL, - Word16 *bin_nrgL_e, - Word32 *bin_nrgR, - Word16 *bin_nrgR_e ); -#endif void stereo_dft_enc_compute_itd( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float *DFT_L, @@ -2314,32 +2331,10 @@ void stereo_td_itd( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_td_itd_fx( - ITD_DATA *hITD, /* i/o: ITD data structure */ - Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ - Word16 *q_input_mem_itd, - const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ - const Word16 dft_ovl, /* i : size of DFT overlap */ - Encoder_State **sts, /* i/o: Encoder state structure */ - const Word16 input_frame, /* i : input frame length */ - Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ - Word16 *q_input_mem -); -#endif - void stereo_dft_dmx_out_reset( STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_unify_dmx_fx( - STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ - Decoder_State *st0, /* i/o: decoder state structure */ - Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ - Word32 *input_mem, /* i/o: mem of buffer DFT analysis */ - const Word16 prev_sid_nodata /* i : Previous SID/No data indicator */ -); -#endif + void stereo_dft_unify_dmx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ Decoder_State *st0, /* i/o: decoder state structure */ @@ -2463,18 +2458,22 @@ float ECSQ_dequantize_gain( const int16_t index ); +#ifndef IVAS_FLOAT_FIXED void ECSQ_quantize_vector( const float *input, const float global_gain, const int16_t N, int16_t *output ); +#endif +#ifndef IVAS_FLOAT_FIXED float ECSQ_compute_optimal_gain( const float *input, const int16_t N, const int16_t *output ); +#endif void ECSQ_init_instance( ECSQ_instance *ecsq_inst, @@ -2482,6 +2481,7 @@ void ECSQ_init_instance( void *ac_handle ); +#ifndef IVAS_FLOAT_FIXED int32_t ECSQ_encode_target_SNR( ECSQ_instance *ecsq_inst, const float *input, @@ -2491,6 +2491,7 @@ int32_t ECSQ_encode_target_SNR( float *output, int16_t *global_gain_index_output ); +#endif // IVAS_FLOAT_FIXED #ifndef IVAS_FLOAT_FIXED void ECSQ_decode( @@ -2666,11 +2667,11 @@ void unclr_classifier_dft( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); #endif - +#ifndef IVAS_FLOAT_FIXED void unclr_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); - +#endif #ifdef IVAS_FLOAT_FIXED void xtalk_classifier_dft_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ @@ -2683,11 +2684,11 @@ void xtalk_classifier_dft( const int16_t itd, /* i : ITD from DFT stereo - used as a feature */ const float gcc_phat[] /* i : GPHAT cross-channel correlation function */ ); - +#ifndef IVAS_FLOAT_FIXED void xtalk_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); - +#endif /*----------------------------------------------------------------------------------* * TD Stereo prototypes @@ -2702,18 +2703,34 @@ void stereo_td_init_enc_fx( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ const Word16 last_element_mode /* i : last element mode */ ); - +#ifndef IVAS_FLOAT_FIXED ivas_error stereo_set_tdm( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int16_t input_frame /* i : input frame length per channel */ ); - +#else +ivas_error stereo_set_tdm_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 input_frame, /* i : input frame length per channel */ + Word16 input_q +); +#endif +#ifndef IVAS_FLOAT_FIXED void stereo_tdm_prep_dwnmx ( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const float *input1, /* i : right channel input */ const int16_t input_frame /* i : frame lenght */ ); +#else +void stereo_tdm_prep_dwnmx_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word32 *input1, /* i : right channel input */ + const Word16 input_frame, /* i : frame lenght */ + const Word16 input_q /* i : frame lenght */ +); +#endif +#ifndef IVAS_FLOAT_FIXED int16_t stereo_tdm_ener_analysis( const int16_t ivas_format, /* i : IVAS format */ CPE_ENC_HANDLE hCPE, /* i : CPE structure */ @@ -2721,7 +2738,7 @@ int16_t stereo_tdm_ener_analysis( int16_t *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */ int16_t *tdm_ratio_idx_SM /* o : TDM ratio index for SM mode */ ); - +#endif void stereo_tdm_downmix( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i : TD stereo IVAS encoder structure */ float *Left_in, /* i/o: Left channel -> Primary channel */ @@ -2791,7 +2808,21 @@ void stereo_tdm_combine_fx( const Word16 flag_HB, /* i : flag to distinguish between core (0) and HB (1) synthesis */ const Word16 tdm_ratio_idx /* i : TDM ratio index */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 tdm_lp_comparison_fx( + STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + Encoder_State *st, /* i/o: Encoder structure */ + Word32 *speech_buff, /* i : Current speech frame Q_speech */ + const Word16 *A_PCh_fx, /* i : primary channel LP coefficients Q12*/ + const Word16 *A_SCh_fx, /* i : secondary channel LP coeff. Q12*/ + const Word16 m, /* i : filter length */ + const Word32 *isp_PCh_fx, /* i : primary channel LSPs Q31 */ + const Word32 *isp_SCh_fx, /* i : secondary channel LSPs Q31 */ + const Word16 L_frame, /* i : frame length */ + const Word32 element_brate_wo_meta, /* i : element bitrate without metadata*/ + Word16 Q_speech ); +#else /*! r: replication decision; 1 = Use old LP */ int16_t tdm_lp_comparison( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ @@ -2806,7 +2837,7 @@ int16_t tdm_lp_comparison( const int16_t L_frame, /* i : frame length */ const int32_t element_brate_wo_meta /* i : element bitrate without metadata */ ); - +#endif /*! r: replication decision; 1 = Use old LP */ void tdm_ol_pitch_comparison( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ @@ -3089,7 +3120,17 @@ void TNSAnalysisStereo( int16_t param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ const int16_t mct_on /* i : flag mct block (1) or stereo (0) */ ); - +#ifdef IVAS_FLOAT_FIXED +void TNSAnalysisStereo_fx( + Encoder_State **sts, /* i : encoder state handle */ + Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* o : MDST spectrum Qx*/ + const Word16 bWhitenedDomain, /* i : whitened domain flag Q0*/ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : number of tns parameters put into prm Q0*/ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : number of tns bits in the frame Q0*/ + Word16 param_core[][NB_DIV * NPRM_DIV], /* o : TNS parameters Q0*/ + const Word16 mct_on /* i : flag mct block (1) or stereo (0) Q0*/ +); +#endif void InternalTCXDecoder( Encoder_State *st, /* i/o: state handle */ const int16_t frame_cnt, /* i : frame counter in the super_frame */ @@ -3650,6 +3691,11 @@ ivas_error front_vad_create_fx( void front_vad_destroy( FRONT_VAD_ENC_HANDLE *hFrontVad /* i/o: front-VAD handle */ ); +#ifdef IVAS_FLOAT_FIXED +void front_vad_destroy_fx( + FRONT_VAD_ENC_HANDLE *hFrontVad /* i/o: front-VAD handle */ +); +#endif ivas_error front_vad( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure, nullable */ @@ -3668,7 +3714,28 @@ ivas_error front_vad( float *PS_out, /* o : energy spectrum */ float *Bin_E_out /* o : log-energy spectrum of the current frame*/ ); - +#ifdef IVAS_FLOAT_FIXED +ivas_error front_vad_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure, nullable */ + Encoder_State * st, /* i/o: encoder state structure */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + FRONT_VAD_ENC_HANDLE *hFrontVads, /* i/o: FrontVad handles */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const Word16 input_frame, /* i : frame length */ + Word16 vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ + Word32 fr_bands_fx[][2 * NB_BANDS], /* o : energy in frequency bands Q_buffer[n] + QSCALE + 2 */ + Word16 Etot_LR_fx[], /* o : total energy Left & Right channel Q8 */ + Word32 lf_E_fx[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels Q_buffer[n] + QSCALE */ + Word16 localVAD_HE_SAD[], /* o : HE-SAD flag without hangover, LR channels */ + Word16 vad_hover_flag[], /* o : VAD hangover flag */ + Word32 band_energies_LR_fx[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN Q_buffer[1] + QSCALE + 2 - band_ener_guardbits*/ + Word32 *PS_out_fx, /* o : energy spectrum Q_buffer + QSCALE */ + Word16 *Bin_E_out_fx, /* o : log-energy spectrum of the current frame Q7 */ + Word16 Q_inp, + Word16 *Q_buffer, + Word16 Q_add, + Word16 *front_create_flag ); +#endif ivas_error front_vad_spar( SPAR_ENC_HANDLE hSpar, /* i/o: SPAR encoder structure */ const float *omni_in, /* i : omnidirectional input signal */ @@ -3997,7 +4064,16 @@ Word32 check_bounds_l( const Word32 low, /* i : Low limit */ const Word32 high /* i : High limit */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error stereo_memory_enc_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const int32_t input_Fs, /* i : input sampling rate */ + const int16_t max_bwidth, /* i : maximum audio bandwidth */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const int16_t nchan_transport /* i : number transport chans */ +); +#else ivas_error stereo_memory_enc( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int32_t input_Fs, /* i : input sampling rate */ @@ -4007,6 +4083,7 @@ ivas_error stereo_memory_enc( const int16_t nchan_transport /* i : number transport chans */ ); +#endif ivas_error stereo_memory_dec( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ @@ -4017,13 +4094,20 @@ ivas_error stereo_memory_dec( const MC_MODE mc_mode, /* i : MC mode */ const int16_t nchan_transport /* i : number of transport channels */ ); - +#ifdef IVAS_FLOAT_FIXED +void stereo_switching_enc_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 old_input_signal_pri[], /* i : old input signal of primary channel */ + const Word16 input_frame, /* i : input frame length */ + const Word16 q_inp +); +#else void stereo_switching_enc( CPE_ENC_HANDLE hCPE, /* i : CPE structure */ float old_input_signal_pri[], /* i : old input signal of primary channel */ const int16_t input_frame /* i : input frame length */ ); - +#endif void stereo_switching_dec( CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ const int32_t ivas_total_brate /* i : IVAS total bitrate */ @@ -4122,14 +4206,6 @@ void ivas_mdct_quant_coder( const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); -void ivas_mdct_quant_coder_fx( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ -); - void apply_MCT_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ @@ -4158,23 +4234,7 @@ void getChannelEnergies( float nrg[MCT_MAX_CHANNELS], /* o : energies */ const int16_t nchan /* i : number of channels */ ); -#ifdef IVAS_FLOAT_FIXED -void mctStereoIGF_enc_fx( - MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ - Encoder_State **sts, /* i/o: encoder state structure */ - Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ - Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ - Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ - Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ -#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED - float *orig_spectrum[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ - float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ - float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ - float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ -#endif - const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ -); -#endif + void mctStereoIGF_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ @@ -5085,12 +5145,22 @@ void calculate_hodirac_sector_parameters( float *ene /* o : array of sector energy values, flat */ ); +#ifdef IVAS_FLOAT_FIXED void ivas_mc_paramupmix_enc( Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ float *data_f[], /* i/o: input/transport MC data */ + Word32 *data_fx[], const int16_t input_frame /* i : input frame length */ ); +#else +void ivas_mc_paramupmix_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ + float *data_f[], /* i/o: input/transport MC data */ + const int16_t input_frame /* i : input frame length */ +); +#endif ivas_error ivas_mc_paramupmix_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ @@ -7469,6 +7539,7 @@ void ivas_ls_custom_setup( * McMASA prototypes *----------------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_mcmasa_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); @@ -7481,6 +7552,7 @@ void ivas_mcmasa_enc_close( ivas_error ivas_mcmasa_enc_reconfig( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); +#endif ivas_error ivas_mcmasa_dec_reconfig( Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ @@ -7507,6 +7579,7 @@ void ivas_mcmasa_split_brate( int32_t *brate_cpe /* o : Pointer to CPE element bitrate */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_mcmasa_enc( MCMASA_ENC_HANDLE hMcMasa, /* i/o: Encoder McMASA handle */ IVAS_QMETADATA_HANDLE hQMeta, /* o : Qmetadata handle */ @@ -7530,6 +7603,7 @@ void ivas_mcmasa_param_est_enc( const int16_t nchan_inp /* i : Number of input channels */ ); +#endif void ivas_mcmasa_dmx_modify( const int16_t n_samples, /* i : input frame length in samples */ float dmx[][L_FRAME48k + NS2SA( 48000, IVAS_FB_ENC_DELAY_NS )], /* i/o: downmix signal to be transformed into another format */ @@ -7748,19 +7822,28 @@ void ivas_filter_process_fx( /*----------------------------------------------------------------------------------* * OSBA prototypes *----------------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_osba_enc_open_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +); +#else ivas_error ivas_osba_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); - +#endif +#ifdef IVAS_FLOAT_FIXED +void ivas_osba_enc_close_fx( + OSBA_ENC_HANDLE *hOSba /* i/o: encoder OSBA handle */ +); +#else void ivas_osba_enc_close( OSBA_ENC_HANDLE *hOSba /* i/o: encoder OSBA handle */ ); - +#endif ivas_error ivas_osba_enc_reconfig( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ); - +#ifndef IVAS_FLOAT_FIXED void ivas_osba_enc( OSBA_ENC_HANDLE hOSba, /* i/o: OSBA encoder handle */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ @@ -7772,7 +7855,20 @@ void ivas_osba_enc( const int32_t input_Fs, /* i : input sampling rate */ const int16_t sba_planar /* i : planar SBA flag */ ); - +#else +void ivas_osba_enc_fx( + OSBA_ENC_HANDLE hOSba, /* i/o: OSBA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + Word32 *data_in_fx[], /* i/o: Input / transport audio signals */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_ism, /* i : Number of objects for parameter analysis */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const int16_t sba_analysis_order, /* i : SBA order evaluated in DirAC/SPAR encoder */ + const int32_t input_Fs, /* i : input sampling rate */ + const int16_t sba_planar, /* i : planar SBA flag */ + Word16 *q_data + ); +#endif ivas_error ivas_osba_data_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ ); @@ -7862,13 +7958,17 @@ ivas_error ivas_omasa_dec_config( int16_t *data /* o : output synthesis signal */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_omasa_set_config( OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ const int32_t input_Fs, /* i : Input sample rate */ const ISM_MODE ism_mode /* i : ISM mode */ ); +#endif // !IVAS_FLOAT_FIXED + +#ifndef IVAS_FLOAT_FIXED void ivas_omasa_enc( OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */ @@ -7881,6 +7981,7 @@ void ivas_omasa_enc( float *data_separated_object, /* o : Separated object audio signal */ int16_t* idx_separated_object /* o : Index of the separated object */ ); +#endif // !IVAS_FLOAT_FIXED void ivas_set_surplus_brate_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ @@ -7915,6 +8016,7 @@ void ivas_set_ism_importance_interformat( int16_t ism_imp[] /* o : ISM importance flags */ ); +#ifndef IVAS_FLOAT_FIXED /*! r: flag for using less bitrate for objects in OMASA */ int16_t ivas_omasa_ener_brate( const int16_t nchan_ism, /* i : number of ISMs */ @@ -7922,6 +8024,7 @@ int16_t ivas_omasa_ener_brate( float *data_f[], /* i : Input / transport audio signals */ const int16_t input_frame /* i : Input frame size */ ); +#endif // !IVAS_FLOAT_FIXED /*! r: adjusted bitrate */ int32_t ivas_interformat_brate( @@ -8009,8 +8112,8 @@ void ivas_omasa_dirac_rend_jbm( #ifdef IVAS_FLOAT_FIXED void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( Decoder_Struct *st_ivas, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ Word16 *cldfb_buf_q, const Word16 nBins, const Word16 subframe @@ -8150,6 +8253,16 @@ void ivas_fb_mixer_pcm_ingest( const int16_t frame_length, /* i : frame length */ const int16_t HOA_md_ind[IVAS_SPAR_MAX_CH] ); +#ifdef IVAS_FLOAT_FIXED +void ivas_fb_mixer_pcm_ingest_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in[], /* i : input audio channels Qq_data_fix[] */ + Word32 **ppOut_pcm, /* o : output audio channels Qq_ppOut_pcm[] */ + const Word16 frame_len, /* i : frame length */ + const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH], + Word16 q_data_fix[MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS], + Word16 *q_ppOut_pcm ); +#endif void ivas_fb_mixer_update_prior_input( IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 866c42a6695b252fc2c623923ea0f321a90db9ec..0a07ebf4708e83fec11b6c4d4a8ccaac7214d5ac 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -296,10 +296,10 @@ Word16 res_bpf_adapt_fx( // ivas_sns_com_fx.c void sns_compute_scf_fx( - Word32 spectrum[], + Word32 spectrum[], /* i : Spectrum (Q_in) */ const PsychoacousticParameters *pPsychParams, const Word16 L_frame, - Word32 *scf, + Word32 *scf, /* o : Scalefactors (Q16)*/ Word16 q ); void sns_interpolate_scalefactors_fx( @@ -835,20 +835,25 @@ void ivas_lfe_dec_close_fx( void td_stereo_param_updt_fx( - const Word16 lsp_old_PCh[], /* i : primary channel old LSPs */ - const Word16 lsf_old_PCh[], /* i : primary channel old LSFs */ - const Word16 pitch_buf_PCh[], /* i : primary channel pitch buffer */ - Word16 tdm_lspQ_PCh[], /* o : Q LSPs for primary channel */ - Word16 tdm_lsfQ_PCh[], /* o : Q LSFs for primary channel */ - Word16 tdm_Pri_pitch_buf[], /* o : pitch values for primary channel */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ + const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15 */ + const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qlog2(2.56) */ + const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q6 */ + Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15 */ + Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qlog2(2.56) */ + Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q6 */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ #ifndef FIX_798_WRONG_CPY_OF_PITCH , Word16 Q_var #endif ); +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ +); + + void updateBuffersForDmxMdctStereo_fx( CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ const Word16 output_frame, /* i : output frame length */ @@ -927,6 +932,17 @@ ivas_error ivas_ism_config_fx( const Word16 combined_format_flag /* i : flag indicating combined format */ ); +void stereo_dft_enc_analyze_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + const Word16 n_channels, /* i : number of input channels */ + const Word16 input_frame, /* i : input frame length */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 DFT_e[CPE_CHANNELS], /* o : DFT buffers */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ); + Word16 IGF_MapBitRateToIndex( const Word32 brate, /* i : bitrate */ const Word16 bwidth, /* i : audio bandwidth */ @@ -949,6 +965,47 @@ void stereo_dft_config_fx( Word16 *bits_frame_nominal_2 /* o : secondary channel nominal bits per frame*/ ); +void stereo_td_itd_mdct_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : frame length */ +); + +void stereo_td_itd_fx( + ITD_DATA *hITD, /* i/o: ITD data structure */ + Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ + Word16 *q_input_mem_itd, + const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ + const Word16 dft_ovl, /* i : size of DFT overlap */ + Encoder_State **sts, /* i/o: Encoder state structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ); + +void stereo_dft_unify_dmx_fx( + STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ + Decoder_State *st0, /* i/o: decoder state structure */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ + Word32 *input_mem, /* i/o: mem of buffer DFT analysis */ + const Word16 prev_sid_nodata /* i : Previous SID/No data indicator */ +); + +void stereo_dft_enc_compute_itd_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word32 *DFT_L, + Word16 *DFT_L_e, + Word32 *DFT_R, + Word16 *DFT_R_e, + const Word16 k_offset, + const Word16 input_frame, + const Word16 vad_flag_dtx[], + const Word16 vad_hover_flag[], + Word32 *bin_nrgL, + Word16 *bin_nrgL_e, + Word32 *bin_nrgR, + Word16 *bin_nrgR_e ); + Word16 stereo_dft_band_config_fx( Word16 *band_limits, /* o : DFT band limits */ const Word16 band_res, /* i : DFT band resolution */ @@ -1296,6 +1353,15 @@ void stereo_tcx_init_dec_fx( const Word16 last_element_mode /* i : element mode of previous frame */ ); +void stereo_icBWE_enc_ivas_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word32 shb_speech_ref_fx[], /* i : SHB speech ref channel */ + const Word16 shb_speech_ref_e, /* i : SHB speech ref channel */ + Word32 shb_speech_nonref_fx[], /* i/o: SHB speech non-ref channel */ + Word16 shb_speech_nonref_e, /* i/o: SHB speech non-ref channel */ + const Word32 *voice_factors_fx /* i : voicing factors Q31 */ +); + void initMdctStereoDecData_fx( STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: mdct stereo parameters structure */ const Word16 igf, /* i : flag indicating IGF activity */ @@ -1304,6 +1370,16 @@ void initMdctStereoDecData_fx( const Word16 bwidth /* i : audio bandwidth */ ); +void stereo_tdm_downmix_ivas_fx( + STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i : TD stereo IVAS encoder structure */ + Word16 *Left_in_fx, /* Qx */ + Word16 *Right_in_fx, /* Qx */ + const Word16 input_frame, /* i : Number of samples */ + const Word16 tdm_ratio_idx, /* i : TDM ratio index */ + const Word16 tdm_SM_flag, /* i : channel combination scheme flag */ + const Word16 tdm_ratio_idx_SM /* i : TDM ratio index for SM mode */ +); + void stereo_mdct_init_bands_fx( const Word16 L_frame, /* i : frame length */ const Word16 tmp_tcx_mode, /* i : tcx mode (TCX10, TCX 20), -1 if transition frame */ @@ -1402,10 +1478,18 @@ void dtx_read_padding_bits_fx( DEC_CORE_HANDLE st, const Word16 num_bits ); +void FdCngEncodeMDCTStereoSID_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ +); + void FdCngDecodeMDCTStereoSID_fx( CPE_DEC_HANDLE hCPE /* i/o: CPE decoder state structure */ ); +void FdCngEncodeDiracMDCTStereoSID_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ +); + void FdCngDecodeDiracMDCTStereoSID_fx( CPE_DEC_HANDLE hCPE /* i/o: CPE decoder state structure */ ); @@ -1756,6 +1840,24 @@ void ivas_interpolate_3_over_1_allpass_fx( Word16 *mem_fx /* i/o: memory */ /* Q_input */ ); +void tdm_configure_enc_fx( + const Word16 ivas_format, /* i : IVAS format */ + const Word16 ism_mode, /* i : ISM mode in combined format */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 Etot_last_fx[CPE_CHANNELS], /* i/o: Energy of last frame Q8*/ + const Word16 tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const Word16 tdm_ratio_idx, /* i : ratio index */ + const Word16 tdm_ratio_idx_SM, /* i : ratio index in SM mode */ + const Word16 attack_flag, /* i : Primary channel attack flag */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +); + +void stereoFdCngCoherence_fx( + Encoder_State **sts, /* i/o: core encoder structures */ + const Word16 last_element_mode, /* i : last element mode */ + Word16 fft_buff[CPE_CHANNELS][2 * L_FFT], /* i : fft buffers for L and R channels fft_exp*/ + Word16 fft_exp ); + void ivas_wb_tbe_dec_fx( Decoder_State *st_fx, /* i/o: decoder state structure */ const Word16 coder_type, /* i : coding type */ @@ -1962,6 +2064,16 @@ void masa_compensate_two_dir_energy_ratio_index_fx( const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ ); +#ifdef IVAS_FLOAT_FIXED +int16_t stereo_tdm_ener_analysis_fx( + const Word16 ivas_format, /* i : IVAS format */ + CPE_ENC_HANDLE hCPE, /* i : CPE structure */ + const Word16 input_frame, /* i : Number of samples */ + Word16 *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */ + Word16 *tdm_ratio_idx_SM /* o : TDM ratio index for SM mode */ +); +#endif + #ifdef IVAS_FLOAT_FIXED /*! r: projected azimuth index */ Word16 ivas_dirac_project_azimuth_index( @@ -2369,6 +2481,13 @@ ivas_error ivas_jbm_dec_render_fx( Word16 *data /* o : output synthesis signal */ ); +void ivas_sba_zero_vert_comp_fx( + Word32 *sba_data[], /* i : SBA signals */ + const Word16 sba_order, /* i : SBA order */ + const Word16 sba_planar, /* i : SBA planar flag */ + const Word16 input_frame /* i : frame length */ +); + /*! r: MC format mode (MCT, McMASA, ParamMC) */ MC_MODE ivas_mc_mode_select_fx( const MC_LS_SETUP mc_ls_setup, /* i : MC loudspeaker setup */ @@ -2635,7 +2754,22 @@ void ivas_spar_bitrate_dist_fx( const Word16 sba_order, /* i : Ambisonic (SBA) order */ const Word16 bwidth /* i : audio bandwidth */ ); +ivas_error ivas_corecoder_enc_reconfig_fx( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const Word16 nSCE_old, /* i : number of SCEs in previous frame */ + const Word16 nCPE_old, /* i : number of CPEs in previous frame */ + const Word16 nchan_transport_old, /* i : number of TCs in previous frame */ + const Word32 brate_SCE, /* i : bitrate to be set for the SCEs */ + const Word32 brate_CPE, /* i : bitrate to be set for the CPEs */ + const MC_MODE last_mc_mode /* i : switching between MC modes: last mode */ +); +void ivas_sba_zero_vert_comp_fx( + Word32 *sba_data[], /* i : SBA signals */ + const Word16 sba_order, /* i : SBA order */ + const Word16 sba_planar, /* i : SBA planar flag */ + const Word16 input_frame /* i : frame length */ +); void tdm_configure_dec_fx( const Word16 ivas_format, /* i : IVAS format */ const Word16 ism_mode, /* i : ISM mode in combined format */ @@ -2653,6 +2787,14 @@ void ivas_param_mc_metadata_open_fx( HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC /* o : handle for the Parametric MC parameter coding state */ ); +Word16 mdct_classifier_ivas_fx( + Encoder_State *st, /* i/o: Encoder state variable */ + const Word16 *fft_buff, /* i : FFT spectrum from fft_rel */ + const Word32 enerBuffer[], /* i : energy buffer */ + Word16 enerBuffer_exp, /* i: enenrgy buffer exponent */ + const Word32 brate /* i : current brate, IVAS: nominal bitrate, EVS: st->total_brate */ +); + /*----------------------------------------------------------------------------------* * Range Coder prototypes *----------------------------------------------------------------------------------*/ @@ -2692,7 +2834,6 @@ void rc_uni_enc_encode_bits( const Word16 bits /* i : Number of bits */ ); -#ifdef IVAS_FLOAT_FIXED void stereo_dft_enc_process_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ @@ -2700,6 +2841,84 @@ void stereo_dft_enc_process_fx( const Word16 input_frame /* i : input frame length */ ); +void stereo_dft_cng_side_gain_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word32 last_core_brate, /* i : last core bitrate */ + const Word16 bwidth /* i : audio band-width */ +); + +Word16 quantize_sns_fx( + Word32 sns_in_fx[CPE_CHANNELS][NB_DIV][M], /* sns_e */ + Word32 snsQ_out_fx[CPE_CHANNELS][NB_DIV][M], /* sns_e */ + Word16 *sns_e, + Encoder_State **sts, + Word16 *indices, /* Q0 */ + Word16 *zero_side_flag, /* Q0 */ + Word16 *sns_stereo_mode ); /* Q0 */ + +void stereo_cng_upd_counters_fx( + STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ + const Word32 element_mode, /* i : element mode */ + const Word16 nbands, /* i : Number of bands in active */ + const Word32 sidSideGain[], /* i : SID side gains */ + const Word16 burst_ho_count, /* i : Hang-over count */ + Word16 *coh_fade_counter /* i : Coherence fade counter */ +); + + +void stereo_dft_enc_sid_calc_coh_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + Word32 prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence Q31 */ + Word16 *td_active, /* i/o: TD stereo mode indicator */ + Word16 *first_SID, /* i/o: First SID indicator */ + Word32 *cohBand /* i/o: Coherence per band Q31 */ +); + +void stereo_dft_enc_sid_coh_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word32 *mem_cohBand, /* i/o: Coherence memory */ + const Word16 nbands, /* i : number of DFT stereo bands */ + Word16 *nb_bits, /* i/o: number of bits written */ + Word32 *cohBand /* i/o: Coherence per band */ +); + +void stereo_dft_enc_write_BS_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word16 *nb_bits /* o : number of bits written */ +); + +void stereo_dft_enc_res_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word32 *input_8k, /* i : input buffer sampled at 8kHz Q16 */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word16 *nb_bits, /* o : number of bits written */ + const Word16 max_bits ); + +Word32 ECSQ_encode_target_SNR_fx( + ECSQ_instance *ecsq_inst, + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word32 target_SNR, // Q25 + const Word16 max_bits, + Word32 *output, + Word16 *global_gain_index_output ); + +void ECSQ_quantize_vector_fx( + const Word32 *input, + const Word16 input_e, + const Word32 global_gain, // Q15 + const Word16 N, + Word16 *output ); + +Word32 ECSQ_compute_optimal_gain_fx( // Q15 + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word16 *output ); + void spectral_balancer_fx16( Word16 *signal, /* i/o : signal Qx */ Word16 *mem, /* i/o : mem Qx */ @@ -2707,6 +2926,13 @@ void spectral_balancer_fx16( const Word16 coeff_set /* i : coefficient set */ ); +void spectral_balancer_fx( + Word32 *signal, /* i/o : signal Qx */ + Word32 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +); + void stereo_icBWE_preproc_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const Word16 input_frame, /* i : input frame length */ @@ -2723,19 +2949,350 @@ void core_switching_pre_enc_ivas_fx( const Word16 active_cnt, /* i : active frame counter */ const Word16 last_element_mode /* i : last_element_mode */ ); -#endif + +Word16 ivas_acelp_tcx20_switching_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *inp_fx, /* i : new input signal */ + Word16 q_inp, /* i : i/p Q */ + Word16 *wsp, /* i : input weighted signal */ + Word16 non_staX, /* i : unbound non-stationarity for sp/mu clas */ + Word16 *pitch_fr, /* i : fraction pitch values */ + Word16 *voicing_fr, /* i : fractional voicing values */ + Word16 currFlatness, /* i : flatness */ + Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */ + Word16 stab_fac, /* i : LP filter stability */ + Word32 *res_cod_SNR_M, + Word16 *res_cod_SNR_M_e, + Word16 *tcx_mdct_window_fx, + const Word16 flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ +); + +void encod_gen_2sbfr( + Encoder_State *st, /* i/o: state structure */ + const Word16 speech[], /* i : input speech */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : LP coefficients */ + const Word16 *res, /* i : residual signal */ + Word16 *syn, /* i/o: core synthesis */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + Word16 *exc2, /* i/o: current enhanced excitation */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[], /* i : pitch values for primary channel */ + Word16 *Q_new ); + +void acelp_fast_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 cdk_index, /* i : codebook index */ + const Word16 dn_orig[L_SUBFR], + /* i : corr. between target and h[]. */ // Q_new + 1 + Word16 Q_dn, + const Word16 cn[L_SUBFR], + /* i : residual after long term prediction */ // Q_new + 1 + const Word16 H[L_SUBFR], + /* i : impulse response of weighted synthesis filter */ // e(norm_s(H[0])+1) + Word16 code[L_SUBFR], /* o : algebraic (fixed) codebook excitation */ + Word16 y[], /* o : filtered fixed codebook excitation */ + const Word16 L_subfr /* i : subframe length */ +); + +void ivas_mdct_quant_coder_fx( + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + Word16 p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); + +void ivas_mdct_tcx10_bit_distribution_fx( + Word16 target_bitsTCX10[NB_DIV], /* o : target bit distribution */ + const Word16 nbits_tcx, /* i : TCX bits */ + const Word16 nTnsBitsTCX10[NB_DIV] /* i : TNS bits */ +); void QuantizeSpectrum_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - const float A[], /* i : quantized coefficients NxAz_q[M+1] */ - const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ - float gainlpc[], /* i : MDCT gains of the previous frame */ - float synth[], /* o : synthesis buffer */ - const int16_t nb_bits, /* i : bit budget */ - const int16_t tnsSize, /* i : number of tns parameters put into prm */ - int16_t prm[], /* o : tcx parameters */ - const int16_t frame_cnt, /* i : frame counter in the super_frame */ - CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ - const int16_t vad_hover_flag /* i : VAD hangover flag */ + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 A_fx[], /* i : quantized coefficients NxAz_q[M+1] */ + const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ + Word16 gainlpc_fx[], /* i : MDCT gains of the previous frame */ + Word16 gainlpc_e[], /* i : exponents of MDCT gains of the previous frame */ + Word16 synth[], /* o : synthesis buffer, Q0 */ + const Word16 nb_bits, /* i : bit budget */ + const Word16 tnsSize, /* i : number of tns parameters put into prm */ + Word16 prm[], /* o : tcx parameters */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); + +void InternalTCXDecoder_fx( + Encoder_State *st, /* i/o: state handle */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + const Word16 L_frameTCX, /* i : full frame length */ + const Word16 L_frame, /* i : frame length */ + const Word16 L_spec, /* i : length of the coded spectrum */ + const Word16 tcx_offset, /* i : folding point offset relative to the end of the previous frame */ + const Word16 noiseFillingBorder, /* i : noise filling border */ + const Word32 *x_quant_fx, /* i : quantized spectrum */ + const Word32 ener_fx, /* i : energy of the quantized spectrum */ + const Word16 ener_e, /* i : energy of the quantized spectrum exponent */ + Word16 lf_deemph_fact_fx[], /* i/o: low frequency deemphasis factors */ + const Word16 fac_ns_fx, /* i : noise filling level, Q15 */ + const Word16 nf_seed, /* i : noise filling random seed, Q0 */ + const Word16 *A_fx, /* i : LPC representation of the FDNS gains */ + Word16 gainlpc_fx[], /* i/o: FDNS gains */ + Word16 gainlpc_e[], /* i/o: FDNS gains exponent */ + const Word16 hm_active, /* i : flag indicating if the harmonic model is active */ + Word16 gain_tcx_fx, /* i/o: global gain / quantized global gain */ + Word16 *gain_tcx_e, /* i/o: global gain / quantized global gain exponent */ + Word32 spectrum_fx[], /* o : dequantized spectrum */ + Word16 *spectrum_e, /* o : dequantized spectrum */ + Word16 synth[], /* o : time domain signal */ + Word16 *gain_tcx_q /* o : quantized global gain (at low bitrates) */ +); + +void stereo_tcx_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float new_samples_12k8[], /* i : buffer of input signal @12.8 kHz */ + const float new_samples_16k[], /* i : buffer of input signal @16 kHz */ + const Word16 Aw_fx[], /* i : weighted A(z) unquant. for subframes, Q12 */ + float lsp_new[], /* i : LSPs at the end of the frame, Q15 */ + float lsp_mid[], /* i : LSPs in the middle of the frame, Q15 */ + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : pitch for each subframe, Q6 */ + const Word16 last_element_mode, /* i : last element mode, Q0 */ + const Word16 vad_hover_flag /* i : VAD hangover flag, Q0 */ +); + + +Word16 transient_analysis_ivas_fx( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const Word16 cor_map_LT[], /* i : LT correlation map Q_cor_map = Qx */ + Word16 Q_cor_map, + const Word16 multi_harm_limit, /* i : multi harmonic threshold Q_multi_harm_limit = Qx */ + Word16 Q_multi_harm_limit ); + +void set_transient_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE structure */ + Word16 currFlatness[] /* i/o: current flatness Q7*/ +); + +void ivas_smc_mode_selection_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + Word16 smc_dec, /* i : raw decision of the 1st stage classifier*/ + const Word16 relE, /* i : relative frame energy, Q8 */ + const Word16 Etot, /* i : total frame energy, Q8 */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Q_new, /* i : Q of input signal */ + const Word16 S_map[], /* i : short-term correlation map, Q7 */ + const Word16 flag_spitch /* i : flag to indicate very short stable pitch*/ +); + +void stereo_classifier_features_ivas_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 idchan, /* i : channel ID */ + const Word16 element_mode, /* i : element mode */ + const Word16 vad_flag, /* i : VAD flag */ + Word32 lsf_new_fx[], /* i : LSFs at the end of the frame */ + Word32 epsP_fx[], /* i : LP analysis residual energies for each iteration*/ + Word16 pitch[], /*q0 i : open-loop pitch values for quantiz. */ + Word16 voicing_fx[], /* i : OL maximum normalized correlation */ + Word32 cor_map_sum_fx, /* i : speech/music clasif. parameter */ + Word32 non_staX_fx, /* i : unbound non-stationarity for sp/mu clas. */ + Word32 sp_div_fx, /* i : spectral diversity feature */ + const Word16 clas, /* i : signal class */ + Word16 epsP_e, /*exponent for epsP_fx */ + Word16 voicing_e, /*exponent for voicing_fx */ + Word16 cor_map_sum_e, /*exponent for cor_map_sum_fx */ + Word16 non_staX_e, /*exponent for non_staX_fx */ + Word16 sp_div_e /*exponent for sp_div_fx */ +); + +void tdm_ol_pitch_comparison_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values, Q6 */ + Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15 */ +); + +#ifdef IVAS_FLOAT_FIXED +void xtalk_classifier_td_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +); + +void unclr_classifier_td_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +); +#endif + +#ifdef IVAS_FLOAT_FIXED + +void ivas_param_ism_stereo_dmx_fx( + Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ + Word32 *data[MAX_NUM_OBJECTS], /* i/o: input signal/stereo dmx Qx */ + const Word16 input_frame /* i : Length of input frame */ +); + +void ivas_param_ism_enc_fx( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + Word32 *data[MAX_NUM_OBJECTS], /* i : input signal q_pcm_in */ + const Word16 input_frame, /* i : input frame length per channel */ + const Word16 q_pcm_in ); +#endif + +ISM_MODE ivas_ism_mode_select( + const Word16 nchan_inp, /* i : number of input objects */ + const Word32 ivas_total_brate /* i : IVAS total bitrate */ +); + +void ivas_fb_mixer_update_prior_input_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in_fx[], /* i : input audio channels */ + const Word16 length, /* i : length of time slot */ + const Word16 nchan_fb_in /* i : number of analysis channels */ +); + +void ivas_fb_mixer_get_windowed_fr_fx( + IVAS_FB_MIXER_HANDLE hFbMixer, /* i/o: FB mixer handle */ + Word32 *pcm_in_fx[], + Word32 *frame_f_real_fx[], + Word32 *frame_f_imag_fx[], + const int16_t length, /* i : number of new samples in time slot */ + const int16_t mdft_len, /* i : MDFT frame length */ + const int16_t nchan_fb_in, /* i : number of analysis channels */ + Word16 gb ); +void ivas_omasa_set_config_fx( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ + const Word32 input_Fs, /* i : Input sample rate */ + const ISM_MODE ism_mode /* i : ISM mode */ +); +Word16 ivas_omasa_ener_brate_fx( + const Word16 nchan_ism, /* i : number of ISMs */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + Word32 *data_f[], /* i : Input / transport audio signals */ + const Word16 input_frame, /* i : Input frame size */ + Word16 data_e /*i:exponent for data_f */ +); +void computeDiffuseness_mdft_fx( + Word32 **buffer_intensity[DIRAC_NUM_DIMS], + const Word32 *buffer_energy, + const Word16 num_freq_bands, + const UWord16 no_col_avg_diff, + Word32 *diffuseness, + Word16 *q_factor_intensity, + Word16 *q_factor_energy, + Word16 *q_diffuseness /*Ouput Q*/ +); + +void computeDirectionVectors_fixed( + Word32 *intensity_real_x, + Word32 *intensity_real_y, + Word32 *intensity_real_z, + const Word16 enc_param_start_band, + const Word16 num_frequency_bands, + Word32 *direction_vector_x, /*Q30*/ + Word32 *direction_vector_y, /*Q30*/ + Word32 *direction_vector_z, /*Q30*/ + Word16 i_e /*Exponent of all the intensity buffers*/ ); + + +UWord8 ivas_masa_surrcoh_signicant_fx( + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */ + Word32 diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio */ + const Word16 nSubFrames, /* i : Number of sub frames */ + const Word16 nBands /* i : Number of frequency bands */ +); + +/*----------------------------------------------------------------------------------* + * McMASA prototypes + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_mcmasa_enc_open_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +); +void ivas_mcmasa_enc_close_fx( + MCMASA_ENC_HANDLE *hMcMasa, /* i/o: encoder McMASA handle */ + const Word32 input_Fs /* i : input sampling rate */ +); + +ivas_error ivas_mcmasa_enc_reconfig_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +); + +void ivas_mcmasa_enc_fx( + MCMASA_ENC_HANDLE hMcMasa, /* i/o: Encoder McMASA handle */ + IVAS_QMETADATA_HANDLE hQMeta, /* o : Qmetadata handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: Encoder MASA handle */ + Word32 *data_f[], /* i : Input frame of audio */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport, /* i : Number of transport channels */ + const Word16 nchan_inp, /* i : Number of input channels */ + const Word16 q_inp /* i : Input data q-format */ +); +void ivas_mcmasa_param_est_enc_fx( + MCMASA_ENC_HANDLE hMcMasa, /* i : McMASA encoder structure */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder structure */ + Word32 *data_f[], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp, /* i : Number of input channels */ + const Word16 q_inp /* i : Number of input channels */ +); + +void computeReferencePower_enc_fx( + const Word16 *band_grouping, /* i : Band grouping for estimation */ + Word32 Cldfb_RealBuffer[][DIRAC_NO_FB_BANDS_MAX], /* i : Real part of input signal */ + Word32 Cldfb_ImagBuffer[][DIRAC_NO_FB_BANDS_MAX], /* i : Imag part of input signal */ + Word32 *reference_power, /* o : Estimated power */ + const Word16 enc_param_start_band, /* i : first band to process */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + const IVAS_FORMAT ivas_format, /* i : ivas_format */ + Word16 ref_power_w, /* i : use 0 if hodirac is enabled */ + const Word16 nchan_ana /* i : number of analysis channels */ +); +void ivas_omasa_enc( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + float *data_in_f[], /* i/o: Input / transport audio signals */ + Word32 *data_in[], /* i/o: Input / transport audio signals */ + Word16 q_data, /* i:Q0 Stores the q for data_in_f */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_transport, /* i : Number of transport channels */ + const int16_t nchan_ism, /* i : Number of objects for parameter analysis */ + const ISM_MODE ism_mode, /* i : ISM mode */ + float *data_separated_object, /* o : Separated object audio signal */ + int16_t *idx_separated_object /* o : Index of the separated object */ +); + +void mctStereoIGF_enc_fx( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + Encoder_State **sts, /* i/o: encoder state structure */ + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + Word16 q_origSpec, /* i : Q for MDCT spectrum */ + Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ + Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + Word16 q_powerSpec[MCT_MAX_CHANNELS], /* i : Q for powSpec_fx and powSpecMsInv_fx*/ + Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ +); + +void ivas_mct_core_enc_fx( + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ + const Word16 nChannels, /* i : number of channels to be coded */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + const Word16 switch_bw, /* i : flag bandwidth switch occurance */ + const Word16 lfe_bits, /* i : bits spent for LFE */ + const Word16 sba_order /* i : Ambisonic (SBA) order */ ); + #endif diff --git a/lib_com/ivas_qspherical_com.c b/lib_com/ivas_qspherical_com.c index 0eb7f6a1c32a0cb85e321b729c21320757e4c906..e4ae2107919bffa213460f371769c06169dd9cce 100644 --- a/lib_com/ivas_qspherical_com.c +++ b/lib_com/ivas_qspherical_com.c @@ -50,7 +50,25 @@ * ivas_qmetadata_reorder_generic() * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +UWord16 ivas_qmetadata_reorder_generic( + const Word16 signed_value ) +{ + UWord16 unsigned_value; + + IF( signed_value < 0 ) + { + // unsigned_value = ( ( UWord16 ) - ( signed_value + 1 ) << 1 ) + 1; + unsigned_value = (UWord16) L_add( L_shl( negate( add( signed_value, 1 ) ), 1 ), 1 ); + } + ELSE + { + unsigned_value = (UWord16) L_shl( signed_value, 1 ); + } + return unsigned_value; +} +#else uint16_t ivas_qmetadata_reorder_generic( const int16_t signed_value ) { @@ -67,6 +85,7 @@ uint16_t ivas_qmetadata_reorder_generic( return unsigned_value; } +#endif /*------------------------------------------------------------------------- diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 679dbe800b411b84005d7c24109f6bc95281f672..ff79170198cd26371eefe34a31b2b31e798ad93d 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -159,9 +159,11 @@ extern const float nf_tw_smoothing_coeffs[N_LTP_GAIN_MEMS]; * Stereo DTX ROM tables *----------------------------------------------------------------------------------*/ +extern const Word16 dft_cng_coh_pred_fx[][STEREO_DFT_COH_PRED_COEFFS]; extern const float dft_cng_coh_pred[][STEREO_DFT_COH_PRED_COEFFS]; extern const int16_t dft_cng_coh_u2i[9]; extern const int16_t dft_cng_coh_i2u[9]; +extern const Word16 dft_cng_alpha_bits_fx[STEREO_DFT_N_COH_ALPHA_STEPS][STEREO_DFT_N_COH_ALPHA_LEVELS]; extern const float dft_cng_alpha_bits[STEREO_DFT_N_COH_ALPHA_STEPS][STEREO_DFT_N_COH_ALPHA_LEVELS]; extern const int16_t dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1]; diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index affd420b94eb44e1325d8fb7fdcd7c3bad5380f4..ad8fe5a8d1b4ce26dc98f9dbfc498a4762411c51 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -519,25 +519,40 @@ const UWord16 cum_n_for_id_th[122] = { * Multi-channel LS setups *----------------------------------------------------------------------------------*/ /*Azimuth and elevation LS Tables in Q22*/ + +/* Q22 */ const Word32 ls_azimuth_CICP1_fx[1] = { 0 }; +/* Q22 */ const Word32 ls_elevation_CICP1_fx[1] = { 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP2_fx[2] = { 125829120, -125829120 }; +/* Q22 */ const Word32 ls_elevation_CICP2_fx[2] = { 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP6_fx[5] = { 125829120, -125829120, 0, 461373440, -461373440 }; +/* Q22 */ const Word32 ls_elevation_CICP6_fx[5] = { 0, 0, 0, 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP12_fx[7] = { 125829120, -125829120, 0, 461373440, -461373440, 566231040, -566231040 }; +/* Q22 */ const Word32 ls_elevation_CICP12_fx[7] = { 0, 0, 0, 0, 0, 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP14_fx[7] = { 125829120, -125829120, 0, 461373440, -461373440, 125829120, -125829120 }; +/* Q22 */ const Word32 ls_elevation_CICP14_fx[7] = { 0, 0, 0, 0, 0, 146800640, 146800640 }; +/* Q22 */ const Word32 ls_azimuth_CICP16_fx[9] = { 125829120, -125829120, 0, 461373440, -461373440, 125829120, -125829120, 461373440, -461373440 }; +/* Q22 */ const Word32 ls_elevation_CICP16_fx[9] = { 0, 0, 0, 0, 0, 146800640, 146800640, 146800640, 146800640 }; +/* Q22 */ const Word32 ls_azimuth_CICP19_fx[11] = { 125829120, -125829120, 0, 566231040, -566231040, 377487360, -377487360, 125829120, -125829120, 566231040, -566231040 }; +/* Q22 */ const Word32 ls_elevation_CICP19_fx[11] = { 0, 0, 0, 0, 0, 0, 0, 146800640, 146800640, 146800640, 146800640 }; const Word16 pow_10_q11[128] = { @@ -549,6 +564,19 @@ const Word16 pow_10_q11[128] = { }; #ifdef IVAS_FLOAT_FIXED + +// Q12 +const Word16 icbwe_gsMapping_tbl_fx[16] = { -8192, -5527, -3935, -2907, -2289, -1824, -1404, -1035, -692, -404, -286, -204, -81, 0, 163, 327 }; + +// Q12 +const Word16 icbwe_gsMappingDFT_tbl_fx[128] = { + -20480, -18432, -16384, -14336, -12288, -10240, -7782, -6338, -6144, -5926, -5694, -5640, -5363, -5164, -4475, -4441, -4237, -4213, -4162, -4111, -4019, -3972, -3921, + -3852, -3808, -3740, -3696, -3629, -3578, -3508, -3442, -3421, -3375, -3292, -3245, -3190, -3145, -3111, -3099, -3075, -3042, -3025, -3006, -2990, -2966, -2944, -2904, + -2886, -2867, -2827, -2803, -2782, -2754, -2736, -2718, -2698, -2670, -2643, -2628, -2601, -2578, -2557, -2532, -2512, -2495, -2474, -2455, -2435, -2415, -2396, -2378, + -2359, -2342, -2322, -2306, -2283, -2257, -2227, -2197, -2163, -2129, -2087, -2042, -1991, -1935, -1880, -1822, -1765, -1707, -1652, -1596, -1542, -1481, -1422, -1362, + -1308, -1253, -1194, -1140, -1082, -1026, -970, -902, -833, -765, -700, -639, -581, -517, -453, -390, -329, -270, -216, -164, -117, -75, -38, 0, 30, 63, 91, 122, 153, 187, 225, 270, 321 +}; + const Word32 pow_10_q23[14] = { 2364231, 2652711, 3339565, 4204263, 5803499, 8011059, 8388608, 6818517, 7222539, 5292854, 4204263, 6977341, 7919357, 8388608 }; @@ -1260,6 +1288,14 @@ const Word32 ica_sincInterp2_fx[2 * SINC_ORDER1 + 1] = { -4988604, 0 }; +const Word32 ica_sincInterp4_fx[2 * SINC_ORDER1 + 1] = { + 0, -7054484, -11890617, -10587094, 0, 17813376, 32618130, 29564408, 0, -46911780, -82209968, -71380208, 0, 105465072, 180201792, 153819952, 0, -226492960, -394310208, -349923872, 0, 621904832, 1345701248, 1925805312, 2147483647, 1925805312, 1345701248, 621904832, 0, -349923872, -394310208, -226492960, 0, 153819952, 180201792, 105465072, 0, -71380208, -82209968, -46911780, 0, 29564408, 32618130, 17813376, 0, -10587094, -11890617, -7054484, 0 +}; + +const Word32 ica_sincInterp6_fx[2 * SINC_ORDER1 + 1] = { + 0, -7481833, -15444702, -22462678, -25151328, -18893562, 0, 31359704, 68816112, 99516536, 106796512, 75709536, 0, -111862424, -234090752, -326303712, -341870816, -240232560, 0, 371151744, 833251584, 1319259392, 1748116096, 2042624128, 2147483647, 2042624128, 1748116096, 1319259392, 833251584, 371151744, 0, -240232560, -341870816, -326303712, -234090752, -111862424, 0, 75709536, 106796512, 99516536, 68816112, 31359704, 0, -18893562, -25151328, -22462678, -15444702, -7481833, 0 +}; + /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com_fx.h b/lib_com/ivas_rom_com_fx.h index 6692f0afd9713eac8bd2f0078baadd5a04cb058a..67dabdce32a7028ec56b6e7f62a6b34bac99073e 100644 --- a/lib_com/ivas_rom_com_fx.h +++ b/lib_com/ivas_rom_com_fx.h @@ -92,7 +92,9 @@ extern const Word16 ivas_tan_panning_gain_dirac_tbl_fx[601]; * Stereo ICA ROM tables *----------------------------------------------------------------------------------*/ -extern const Word32 ica_sincInterp2_fx[]; +extern const Word32 ica_sincInterp2_fx[]; // Q31 +extern const Word32 ica_sincInterp4_fx[]; // Q31 +extern const Word32 ica_sincInterp6_fx[]; // Q31 /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables @@ -108,6 +110,8 @@ extern const Word16 pow_10_icbwe_gsMappingDFT_tbl_fx[]; extern const UWord32 tdm_ratio_tabl_fx[TDM_NQ + 1]; extern const Word32 tdm_ratio_tabl_fx_Q24[TDM_NQ + 1]; extern const UWord32 tdm_den_ratio_tabl_fx[]; +extern const Word16 icbwe_gsMapping_tbl_fx[]; // Q12 +extern const Word16 icbwe_gsMappingDFT_tbl_fx[]; // Q12 /* LSFs Intra-frame prediction tables */ extern const Word16 tdm_LSF_MEAN_RE_USE_OUT_fx[M]; diff --git a/lib_com/ivas_sba_config.c b/lib_com/ivas_sba_config.c index c5860c1c8287da6dfcd9cf0cc39df4512dddb0da..3aebb59f52cba1aebbf7b63b69147bd9b562be65 100644 --- a/lib_com/ivas_sba_config.c +++ b/lib_com/ivas_sba_config.c @@ -563,7 +563,35 @@ void ivas_sba_get_spar_hoa_md_flag_fx( * * Zero vertical Ambisonics components *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_sba_zero_vert_comp_fx( + Word32 *sba_data[], /* i : SBA signals */ + const Word16 sba_order, /* i : SBA order */ + const Word16 sba_planar, /* i : SBA planar flag */ + const Word16 input_frame /* i : frame length */ +) +{ + Word16 i, j; + /* Channels in the range i^2+1 to (i+1)^2 -1 are zeroed (retain only first and last channel for that order) */ + FOR( i = 1; i <= sba_order; i++ ) + { + test(); + /* Keep Z if not planar */ + IF( !sba_planar && EQ_16( i, 1 ) ) + { + continue; + } + + FOR( j = ( i * i + 1 ); j < ( ( i + 1 ) * ( i + 1 ) - 1 ); j++ ) + { + set_val_Word32( sba_data[j], 0, input_frame ); + } + } + + return; +} +#endif void ivas_sba_zero_vert_comp( float *sba_data[], /* i : SBA signals */ const int16_t sba_order, /* i : SBA order */ diff --git a/lib_com/ivas_sns_com_fx.c b/lib_com/ivas_sns_com_fx.c index e215c00ff73650ef2883c31f0e3ac7d6f02caae8..ff8fcd8aa641b03937e01fd485a7496cca789834 100644 --- a/lib_com/ivas_sns_com_fx.c +++ b/lib_com/ivas_sns_com_fx.c @@ -50,22 +50,24 @@ *-------------------------------------------------------------------*/ void sns_compute_scf_fx( - Word32 spectrum[], + Word32 spectrum[], /* i : Spectrum (Q_in) */ const PsychoacousticParameters *pPsychParams, const Word16 L_frame, - Word32 *scf, + Word32 *scf, /* o : Scalefactors (Q16)*/ Word16 q ) { - Word16 i, n, k, exp; + Word16 i, n, k; Word32 x[FDNS_NPTS], xs[FDNS_NPTS], mean, xl4[SNS_NPTS], nf, xl[FDNS_NPTS]; + Word64 x_64[FDNS_NPTS]; Word64 sum; Word32 L_tmp; - const Word16 *pow_tilt; + const Word32 *pow_tilt; const UWord8 nBands = pPsychParams->nBands; move16(); const UWord8 *bandLengths = pPsychParams->bandLengths; Word8 bw = 0; move16(); + Word16 q_shift; const Word16 w_0 = 2730; // (1.0f / 12.0f) in Q15 move16(); @@ -82,6 +84,7 @@ void sns_compute_scf_fx( assert( nBands == FDNS_NPTS ); + set64_fx( x_64, 0, FDNS_NPTS ); set32_fx( x, 0, FDNS_NPTS ); IF( bandLengths == NULL ) @@ -93,19 +96,13 @@ void sns_compute_scf_fx( move16(); FOR( i = 0; i < nBands; ++i ) { - x[i] = 0; - move32(); + x_64[i] = 0; + move64(); FOR( n = 0; n < bw; ( ++n, ++k ) ) { - x[i] = L_add_sat( x[i], spectrum[k] ); - move32(); + x_64[i] = W_add( x_64[i], W_deposit32_l( spectrum[k] ) ); // Q_in + move64(); } - exp = 15; - move16(); - Word16 inv_bw = Invert16( bw, &exp ); - inv_bw = shl( inv_bw, exp ); - x[i] = Mpy_32_16_1( x[i], inv_bw ); - move32(); } } ELSE @@ -115,46 +112,73 @@ void sns_compute_scf_fx( move32(); FOR( i = 0; i < nBands; ++i ) { - x[i] = 0; - move32(); + x_64[i] = 0; + move64(); FOR( n = 0; n < bandLengths[i]; ( ++n, ++k ) ) { - x[i] = L_add_sat( x[i], spectrum[k] ); - move32(); + x_64[i] = W_add( x_64[i], W_deposit32_l( spectrum[k] ) ); // Q_in + move64(); } - exp = 15; - move16(); + } + } + + /* Move accumulated values to 32-bit */ + q_shift = W_norm( x_64[0] ); + FOR( i = 1; i < nBands; ++i ) + { + q_shift = s_min( q_shift, W_norm( x_64[i] ) ); + } + FOR( i = 0; i < nBands; ++i ) + { + x[i] = W_extract_l( W_shl( x_64[i], sub( q_shift, 32 ) ) ); // Q_in + (q_shift - 32) + } + IF( bandLengths == NULL ) + { + Word16 inv_bw; + bw = (Word8) shr( L_frame, 6 ); + move16(); + inv_bw = div_l( ONE_IN_Q16, bw ); // Q15 + FOR( i = 0; i < nBands; ++i ) + { + x[i] = Mpy_32_16_1( x[i], inv_bw ); // Q_in + (q_shift - 32) + move32(); + } + } + ELSE + { + FOR( i = 0; i < nBands; ++i ) + { Word16 inv_bw = div_l( ONE_IN_Q16, bandLengths[i] ); // Q15 - x[i] = Mpy_32_16_1( x[i], inv_bw ); + x[i] = Mpy_32_16_1( x[i], inv_bw ); // Q_in + (q_shift - 32) move32(); } } /* Smoothing */ - xs[0] = L_add( Mpy_32_16_1( x[0], 24576 /* 0.75 in Q15 */ ), Mpy_32_16_1( x[1], 8192 /* 0.25 in Q15 */ ) ); + xs[0] = L_add( Mpy_32_16_1( x[0], 24576 /* 0.75 in Q15 */ ), Mpy_32_16_1( x[1], 8192 /* 0.25 in Q15 */ ) ); // Q_in + (q_shift - 32) move32(); FOR( i = 1; i < FDNS_NPTS - 1; i++ ) { - xs[i] = L_add( L_add( Mpy_32_16_1( x[i], 16384 /* 0.5 in Q15 */ ), Mpy_32_16_1( x[i - 1], 8192 /* 0.25 in Q15 */ ) ), Mpy_32_16_1( x[i + 1], 8192 /* 0.25 in Q15 */ ) ); + xs[i] = L_add( L_add( Mpy_32_16_1( x[i], 16384 /* 0.5 in Q15 */ ), Mpy_32_16_1( x[i - 1], 8192 /* 0.25 in Q15 */ ) ), Mpy_32_16_1( x[i + 1], 8192 /* 0.25 in Q15 */ ) ); // Q_in + (q_shift - 32) move32(); } - xs[FDNS_NPTS - 1] = L_add( Mpy_32_16_1( x[FDNS_NPTS - 1], 24576 /* 0.75 in Q15 */ ), Mpy_32_16_1( x[FDNS_NPTS - 2], 8192 /* 0.25 in Q15 */ ) ); + xs[FDNS_NPTS - 1] = L_add( Mpy_32_16_1( x[FDNS_NPTS - 1], 24576 /* 0.75 in Q15 */ ), Mpy_32_16_1( x[FDNS_NPTS - 2], 8192 /* 0.25 in Q15 */ ) ); // Q_in + (q_shift - 32) move32(); /* Pre-emphasis */ SWITCH( L_frame ) { case L_FRAME16k: - pow_tilt = pow_tilt_16k; // Q7 + pow_tilt = pow_tilt_16k; // Q23 BREAK; case L_FRAME25_6k: - pow_tilt = pow_tilt_25_6k; // Q7 + pow_tilt = pow_tilt_25_6k; // Q23 BREAK; case L_FRAME32k: - pow_tilt = pow_tilt_32k; // Q7 + pow_tilt = pow_tilt_32k; // Q23 BREAK; default: pow_tilt = NULL; @@ -163,9 +187,7 @@ void sns_compute_scf_fx( FOR( i = 0; i < FDNS_NPTS; i++ ) { - xs[i] = Mpy_32_16_1( xs[i], pow_tilt[i] ); - move32(); - xs[i] = L_shl( xs[i], Q4 ); // xs => Q8 + xs[i] = Mpy_32_32( xs[i], pow_tilt[i] ); // Q_in + (q_shift - 32) move32(); } @@ -174,20 +196,18 @@ void sns_compute_scf_fx( move64(); FOR( Word16 ind = 0; ind < FDNS_NPTS; ind++ ) { - sum = W_add( sum, (Word64) xs[ind] ); + sum = W_add( sum, (Word64) xs[ind] ); // Q_in + (q_shift - 32) } - mean = (Word32) W_shr( sum, 6 ); - move32(); - - nf = Mpy_32_16_1( mean, 3 ); // 3 => powf( 10.0f, -4.0f ) in Q15 - nf = L_max( nf, 0 ); // 0 => powf( 2.0f, -32.0f ) in Q15 + mean = W_extract_l( W_shr( sum, 6 ) ); // Q_in + (q_shift - 32) + nf = Mpy_32_32( mean, 214748 /* powf( 10.0f, -4.0f ) in Q31 */ ); // Q_in + (q_shift - 32) + nf = L_max( nf, 0 /* powf( 2.0f, -32.0f ) in Q31 */ ); // Q_in + (q_shift - 32) FOR( i = 0; i < FDNS_NPTS; i++ ) { if ( LT_32( xs[i], nf ) ) { - xs[i] = nf; + xs[i] = nf; // Q_in + (q_shift - 32) move32(); } } @@ -205,13 +225,13 @@ void sns_compute_scf_fx( /* Downsampling */ L_tmp = L_deposit_l( 0 ); - L_tmp = Madd_32_16( L_tmp, xl[0], w_0 ); - L_tmp = Madd_32_16( L_tmp, xl[0], w_1 ); - L_tmp = Madd_32_16( L_tmp, xl[1], w_2 ); - L_tmp = Madd_32_16( L_tmp, xl[2], w_3 ); - L_tmp = Madd_32_16( L_tmp, xl[3], w_4 ); - L_tmp = Madd_32_16( L_tmp, xl[4], w_5 ); - xl4[0] = L_tmp; + L_tmp = Madd_32_16( L_tmp, xl[0], w_0 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[0], w_1 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[1], w_2 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[2], w_3 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[3], w_4 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[4], w_5 ); // Q16 + xl4[0] = L_tmp; // Q16 move32(); FOR( n = 1; n < SNS_NPTS - 1; n++ ) @@ -219,37 +239,38 @@ void sns_compute_scf_fx( Word16 n4 = shl( n, 2 ); L_tmp = L_deposit_l( 0 ); - L_tmp = Madd_32_16( L_tmp, xl[n4 - 1], w_0 ); - L_tmp = Madd_32_16( L_tmp, xl[n4], w_1 ); - L_tmp = Madd_32_16( L_tmp, xl[n4 + 1], w_2 ); - L_tmp = Madd_32_16( L_tmp, xl[n4 + 2], w_3 ); - L_tmp = Madd_32_16( L_tmp, xl[n4 + 3], w_4 ); - L_tmp = Madd_32_16( L_tmp, xl[n4 + 4], w_5 ); - xl4[n] = L_tmp; + L_tmp = Madd_32_16( L_tmp, xl[n4 - 1], w_0 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[n4], w_1 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[n4 + 1], w_2 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[n4 + 2], w_3 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[n4 + 3], w_4 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[n4 + 4], w_5 ); // Q16 + xl4[n] = L_tmp; // Q16 move32(); } L_tmp = L_deposit_l( 0 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 5], w_0 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 4], w_1 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 3], w_2 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 2], w_3 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_4 ); - L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_5 ); - xl4[SNS_NPTS - 1] = L_tmp; + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 5], w_0 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 4], w_1 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 3], w_2 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 2], w_3 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_4 ); // Q16 + L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_5 ); // Q16 + xl4[SNS_NPTS - 1] = L_tmp; // Q16 + move32(); /* Remove mean and scaling */ sum = 0; move64(); FOR( Word16 ind = 0; ind < SNS_NPTS; ind++ ) { - sum = W_add( sum, (Word64) xl4[ind] ); + sum = W_add( sum, (Word64) xl4[ind] ); // Q16 } - mean = (Word32) W_shr( sum, 4 ); + mean = W_extract_l( W_shr( sum, 4 ) ); // Q16 FOR( i = 0; i < SNS_NPTS; i++ ) { - scf[i] = Mpy_32_16_1( L_sub( xl4[i], mean ), 27853 /* 0.85 in in Q15 */ ); + scf[i] = Mpy_32_16_1( L_sub( xl4[i], mean ), 27853 /* 0.85 in in Q15 */ ); // Q16 move32(); } diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index a4337b805a52fa768c08d01069a0e2ceb5ae4f67..283896b865d9b25b10d65c38653ff7df4609bbe7 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -552,6 +552,10 @@ typedef struct ivas_qdirection_band_data_struct uint16_t elevation_index[MAX_PARAM_SPATIAL_SUBFRAMES]; float q_azimuth[MAX_PARAM_SPATIAL_SUBFRAMES]; float q_elevation[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef IVAS_FLOAT_FIXED + Word32 q_azimuth_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; /* Q22 */ + Word32 q_elevation_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; /* Q22 */ +#endif } IVAS_QDIRECTION_BAND_DATA; @@ -855,6 +859,9 @@ typedef struct ivas_fb_mixer_state_structure Word32 *ppFilterbank_inFR_re_fx[IVAS_MAX_FB_MIXER_IN_CH]; Word32 *ppFilterbank_inFR_im_fx[IVAS_MAX_FB_MIXER_IN_CH]; Word32 *ppFilterbank_prior_input_fx[IVAS_MAX_FB_MIXER_IN_CH]; + Word16 q_ppFilterbank_inFR_re_fx[IVAS_MAX_FB_MIXER_IN_CH]; + Word16 q_ppFilterbank_inFR_im_fx[IVAS_MAX_FB_MIXER_IN_CH]; + Word16 q_ppFilterbank_prior_input_fx[IVAS_MAX_FB_MIXER_IN_CH]; Word32 *prior_mixer_fx[IVAS_MAX_FB_MIXER_OUT_CH][IVAS_MAX_SPAR_FB_MIXER_IN_CH]; #endif @@ -915,7 +922,7 @@ typedef struct ivas_param_ism_data_structure Word16 last_dmx_gain_fx; Word16 last_dmx_gain_e; - Word16 last_cardioid_left_fx[MAX_NUM_OBJECTS]; + Word16 last_cardioid_left_fx[MAX_NUM_OBJECTS]; // Q14 } PARAM_ISM_CONFIG_DATA, *PARAM_ISM_CONFIG_HANDLE; #ifdef IVAS_FLOAT_FIXED diff --git a/lib_com/ivas_stereo_td_bit_alloc.c b/lib_com/ivas_stereo_td_bit_alloc.c index d16f7b320360777799a331a18a6924ef4f725712..995c70ed2148105d11b944643f60ccd837e5c482 100644 --- a/lib_com/ivas_stereo_td_bit_alloc.c +++ b/lib_com/ivas_stereo_td_bit_alloc.c @@ -968,16 +968,15 @@ void td_stereo_param_updt( } #ifdef IVAS_FLOAT_FIXED - void td_stereo_param_updt_fx( - const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15*/ - const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qx2.56*/ - const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q_var*/ - Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15*/ - Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qx2.56*/ - Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q_var */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ + const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15 */ + const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qlog2(2.56) */ + const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q6 */ + Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15 */ + Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qlog2(2.56) */ + Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q6 */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ #ifndef FIX_798_WRONG_CPY_OF_PITCH , Word16 Q_var diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c index 3a84633af2e48acbabf532b9a707a22512981fa7..143821c93806fc7ec2a7ac38f4a7d096a0fa86e8 100644 --- a/lib_com/lsf_tools_fx.c +++ b/lib_com/lsf_tools_fx.c @@ -555,8 +555,6 @@ Word16 lpc2lsp_fx( move16(); move16(); move16(); - move16(); - move16(); low = 0; high = 8; prev_rt = 0; @@ -1454,7 +1452,7 @@ void lsp_weights_fx( move16(); } - *Qout = 9 - n_max; + *Qout = sub( 9, n_max ); move16(); } @@ -2895,7 +2893,7 @@ void lsf_syn_mem_backup_fx( *gc_threshold_fx = hLPDmem->gc_threshold; move16(); Copy( st_fx->clip_var_fx, clip_var_bck_fx, 6 ); - *next_force_sf_bck_fx = st_fx->next_force_safety_net_fx; + *next_force_sf_bck_fx = st_fx->next_force_safety_net; move16(); @@ -2975,7 +2973,7 @@ void lsf_syn_mem_backup_ivas_fx( *gc_threshold_fx = hLPDmem->gc_threshold; move16(); Copy( st_fx->clip_var_fx, clip_var_bck_fx, 6 ); - *next_force_sf_bck_fx = st_fx->next_force_safety_net_fx; + *next_force_sf_bck_fx = st_fx->next_force_safety_net; move16(); @@ -3116,11 +3114,91 @@ void lsf_syn_mem_restore_fx( hLPDmem->tilt_code = btilt_code_fx; hLPDmem->gc_threshold = gc_threshold_fx; Copy( clip_var_bck_fx, st_fx->clip_var_fx, 6 ); - st_fx->next_force_safety_net_fx = next_force_sf_bck_fx; + st_fx->next_force_safety_net = next_force_sf_bck_fx; return; } +#ifdef IVAS_FLOAT_FIXED +void lsf_syn_mem_restore_ivas_fx( + Encoder_State *st_fx, /* o: state structure */ + Word16 btilt_code_fx, /* i: */ + Word32 gc_threshold_fx, /* i: */ + Word16 *clip_var_bck_fx, /* i: */ + Word16 next_force_sf_bck_fx, /* i: */ + Word16 *lsp_new, /* o: LSP vector to quantize */ + Word16 *lsp_mid, /* o: mid-frame LSP vector */ + Word16 clip_var, /* i: pitch clipping state var */ + Word16 *mem_AR, /* i: quantizer memory for AR model */ + Word16 *mem_MA, /* i: quantizer memory for MA model */ + Word16 *lsp_new_bck, /* i: LSP vector to quantize- backup */ + Word16 *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + Word32 *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* i: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* i: synthesis filter memory */ + Word16 mem_w0_bck, /* i: memory of the weighting filter */ + Word16 streaklimit, /* i:LSF quantizer */ + Word16 pstreaklen /* i:LSF quantizer */ +) +{ + Word16 i; + LPD_state_HANDLE hLPDmem = st_fx->hLPDmem; + + /* restore lsf memories */ + st_fx->clip_var_fx[0] = clip_var; + move16(); + + FOR( i = 0; i < M; i++ ) + { + st_fx->mem_AR_fx[i] = mem_AR[i]; + move16(); + st_fx->mem_MA_fx[i] = mem_MA[i]; + move16(); + lsp_new[i] = lsp_new_bck[i]; + move16(); + lsp_mid[i] = lsp_mid_bck[i]; + move16(); + } + + st_fx->streaklimit_fx = streaklimit; + move16(); + st_fx->pstreaklen = pstreaklen; + move16(); + + FOR( i = 0; i < L_FFT; i++ ) + { + st_fx->Bin_E_fx[i] = Bin_E[i]; + move16(); + } + + FOR( i = 0; i < ( L_FFT / 2 ); i++ ) + { + st_fx->Bin_E_old_fx[i] = Bin_E_old[i]; + move32(); + } + + /* restoring memories */ + hLPDmem->mem_w0 = mem_w0_bck; + move16(); + + FOR( i = 0; i < M; i++ ) + { + hLPDmem->mem_syn[i] = mem_syn_bck[i]; + move16(); + } + + move16(); + hLPDmem->tilt_code = btilt_code_fx; + move32(); + hLPDmem->gc_threshold = gc_threshold_fx; + Copy( clip_var_bck_fx, st_fx->clip_var_fx, 6 ); + st_fx->next_force_safety_net = next_force_sf_bck_fx; + move16(); + + return; +} +#endif + /* Returns: codebook index */ Word16 tcxlpc_get_cdk( Word16 acelp_ext_mode /* (I) GC/VC indicator */ diff --git a/lib_com/modif_fs_fx.c b/lib_com/modif_fs_fx.c index c84dc802a8f1e167b77caa0e348636851d4c1a51..9c490a012a7851a22740fb65a5ac50236adef11f 100644 --- a/lib_com/modif_fs_fx.c +++ b/lib_com/modif_fs_fx.c @@ -39,6 +39,303 @@ /*------------------------------------------------------------------------------*/ /* CALLED FROM : TX/RX */ /*==============================================================================*/ +Word16 modify_Fs_ivas_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[], /* i/o: filter memory Q0 */ + const Word16 nblp, /* i : flag indicating if NB low-pass is applied */ + Word16 *Q_new_inp, /*scaling added on sigOut_fx */ + Word16 *mem_decim_size /*i: size modified for mem_fx*/ +) +{ + Word16 i; + + Word16 lg_out, fac_num, fac_den, filt_len, frac, temp_n, mem_len; + Word16 num_den; + Word16 datastep, fracstep; + Word16 *sigIn_ptr, *sigPtr; + Word16 signal_tab_fx[3 * L_FILT_MAX + L_FRAME48k], *signal_fx, *signal_ana_fx; /* 3* as 2* for memory and 1* for future prediction */ + Word16 A_fx[M + 1], r_fx_h[M + 1], r_fx_l[M + 1]; + Word16 mem_len_ana; + Word16 plus_sample_in; + Word16 j; + Word16 mu_preemph_fx; + Word16 mem_preemph_fx; + Word16 Q_r; + Word16 mem_lev_fx[18]; + Word32 t0, t1, t2, L_tmp; /* temporary variables */ + Word32 LepsP[M + 1]; + Word16 flag_low_order = 0; + move16(); + Word16 filt_len_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + const Resampling_cfg *cfg_ptr_fx; + + /*-------------------------------------------------------------------* + * Find the resampling configuration + *-------------------------------------------------------------------*/ + *Q_new_inp = 0; + move16(); + /* check if fin and fout are the same */ + IF( EQ_32( fin, fout ) ) + { + /* just copy the signal_fx and quit */ + Copy( sigIn_fx, sigOut_fx, lg ); + *mem_decim_size = 0; + *Q_new_inp = 0; + move16(); + move16(); + return lg; + } + ELSE + { + /* find the resampling configuration in the lookup table */ + cfg_ptr_fx = &resampling_cfg_tbl[0]; + WHILE( ( cfg_ptr_fx->fin_fx != 0 ) && !( EQ_32( cfg_ptr_fx->fin_fx, fin ) && EQ_32( cfg_ptr_fx->fout_fx, fout ) ) ) + { + test(); + test(); + cfg_ptr_fx++; + } + + + /* find config with NB 4kHz low-pass */ + test(); + test(); + IF( nblp && ( GT_32( fin, 8000 ) ) && ( EQ_32( fout, 12800 ) ) ) + { + flag_low_order = 1; + move16(); + cfg_ptr_fx++; + WHILE( ( cfg_ptr_fx->fin_fx != 0 ) && !( ( EQ_32( cfg_ptr_fx->fin_fx, fin ) ) && ( EQ_32( cfg_ptr_fx->fout_fx, fout ) ) ) ) + { + test(); + test(); + cfg_ptr_fx++; + } + } + + /*-------------------------------------------------------------------* + * Retrieve and/or calculate the resampling parameters + *-------------------------------------------------------------------*/ + fac_num = cfg_ptr_fx->fac_num_fx; + move16(); /*Q0*/ + fac_den = cfg_ptr_fx->fac_den_fx; + move16(); + + lg_out = idiv1616( i_mult2( lg, fac_num ), fac_den ); + filt_len = cfg_ptr_fx->filt_len_fx; + move16(); + plus_sample_in = 0; + move16(); /*default, regular delay*/ + frac = 0; + move16(); + + test(); + IF( ( EQ_32( fin, 8000 ) ) && ( EQ_32( fout, 12800 ) ) ) + { + plus_sample_in = 7; + move16(); + frac = 4; + move16(); + } + + mem_len = shl( filt_len, 1 ); + *mem_decim_size = mem_len; + move16(); + signal_fx = signal_tab_fx + 2 * L_FILT_MAX + sub( L_FRAME48k, add( mem_len, lg ) ); + signal_ana_fx = signal_fx; + mem_len_ana = mem_len; + move16(); + } + + + /*-------------------------------------------------------------------* + * Resample + *-------------------------------------------------------------------*/ + /* append filter memory */ + Copy( mem_fx, signal_fx, mem_len ); + + sigPtr = signal_fx + mem_len; + Copy( sigIn_fx, sigPtr, lg ); + + IF( plus_sample_in > 0 ) + { + autocorr_fx( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, 1, r_fx_h, r_fx_l, &Q_r, LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + + t1 = L_Comp( r_fx_h[1], r_fx_l[1] ); /* R[1] in Q31 */ + t2 = L_abs( t1 ); /* abs R[1] */ + t0 = L_deposit_l( 0 ); + IF( r_fx_h[0] != 0 ) + { + t0 = Div_32( t2, r_fx_h[0], r_fx_l[0] ); /* R[1]/R[0] in Q31 */ + } + if ( t1 < 0 ) + { + t0 = L_negate( t0 ); /* R[1]/R[0] */ + } + + + mu_preemph_fx = extract_h( t0 ); /*r_fx[1] / r_fx[0]; */ + mem_preemph_fx = signal_ana_fx[mem_len_ana + lg - LEN_WIN_SSS - 1]; + move16(); + PREEMPH_FX( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, mu_preemph_fx, LEN_WIN_SSS, &mem_preemph_fx ); + + + /* Autocorrelations */ + autocorr_fx( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, M, r_fx_h, r_fx_l, &Q_r, + LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + /* Lag windowing */ + lag_wind( r_fx_h, r_fx_l, M, fin, LAGW_STRONG ); + + /* Levinson-Durbin */ + set16_fx( mem_lev_fx, 0, 18 ); + E_LPC_lev_dur( r_fx_h, r_fx_l, A_fx, LepsP, M, NULL ); + + Copy_Scale_sig( A_fx, A_fx, M + 1, sub( norm_s( A_fx[0] ), 2 ) ); + + FOR( i = 0; i < plus_sample_in; i++ ) + { + sigPtr = signal_fx + add( lg, add( mem_len, i ) ); + L_tmp = syn_kern_16( 0, A_fx, sigPtr ); +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( L_tmp, 3 ); + *sigPtr = round_fx_sat( L_tmp ); /* AZ ringing padding */ +#else + L_tmp = L_shl( L_tmp, 3 ); + *sigPtr = round_fx( L_tmp ); /* AZ ringing padding */ +#endif + move16(); + } + mem_preemph_fx = signal_fx[mem_len + lg - LEN_WIN_SSS - 1]; + move16(); + deemph_fx( signal_fx + mem_len + lg - LEN_WIN_SSS, mu_preemph_fx, LEN_WIN_SSS + plus_sample_in, &mem_preemph_fx ); + } + /* interpolation */ + + datastep = shr( div_s( shl( fac_den, 7 ), shl( fac_num, 10 ) ), 12 ); + /* equivalent to 'datastep = fac_den % fac_num' */ + temp_n = i_mult2( datastep, fac_num ); /*Q0*/ + fracstep = sub( fac_den, temp_n ); + + sigIn_ptr = signal_fx + add( filt_len, plus_sample_in ); + + filt_len_tmp = filt_len; + move16(); + IF( flag_low_order ) + { + filt_len_tmp = shr( add( filt_len, 1 ), 1 ); + } + + Word16 norm_cfg_ptr = norm_s( sub( cfg_ptr_fx->filter_fx[0], 1 ) ); + FOR( i = 0; i < lg_out; i++ ) + { +#ifdef BASOP_NOGLOB + sigOut_fx[i] = round_fx_sat( Interpol_lc_fx( sigIn_ptr, cfg_ptr_fx->filter_fx, frac, fac_num, filt_len_tmp ) ); +#else + sigOut_fx[i] = round_fx( Interpol_lc_fx( sigIn_ptr, cfg_ptr_fx->filter_fx, frac, fac_num, filt_len_tmp ) ); +#endif + move16(); + frac = add( frac, fracstep ); + + j = sub( fac_num, frac ); + if ( j < 0 ) + { + frac = sub( frac, fac_num ); + } + sigIn_ptr += add( lshr( j, 15 ), datastep ); + } + *Q_new_inp = negate( norm_cfg_ptr ); + move16(); + /* rescaling */ + test(); + + IF( EQ_32( ( GT_16( fac_num, fac_den ) ), ( ( cfg_ptr_fx->flags_fx & RS_INV_FAC ) != 0 ) ) ) + { + IF( LT_16( fac_num, fac_den ) ) + { + num_den = div_s( fac_num, fac_den ); /*Q15*/ + test(); + IF( GT_32( fin, 16000 ) && EQ_16( lg_out, 512 ) ) + { + + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = round_fx( L_shl( L_mult( sigOut_fx[i], num_den ), 1 ) ); /*Q0*/ + move16(); + } + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); + } + ELSE + { + test(); + test(); + test(); + if ( GT_32( fin, 16000 ) && ( EQ_16( lg_out, L_FRAME ) || EQ_16( lg_out, L_FRAME16k ) || EQ_16( lg_out, 512 ) ) ) + { +#ifdef BASOP_NOGLOB + num_den = shl_o( num_den, 1, &Overflow ); + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); +#else + num_den = shl( num_den, 1 ); +#endif + } + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], num_den ); /*Q0*/ + move16(); + } + } + } + ELSE + { + IF( EQ_16( fac_num, 8 ) ) + { + num_den = 26214; + move16(); + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], num_den ); /*Q-1*/ + move16(); + } + } + ELSE + { + num_den = div_s( sub( fac_num, fac_den ), fac_den ); /*Q15*/ + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = round_fx( L_mac( L_deposit_h( sigOut_fx[i] ), sigOut_fx[i], num_den ) ); /*Q0*/ + move16(); + } + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); + } + } + } + ELSE IF( ( LT_16( fac_num, fac_den ) ) && ( ( cfg_ptr_fx->flags_fx & RS_INV_FAC ) != 0 ) ) + { + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], 16384 ); + move16(); /*Q-1*/ + } + } + /* update the filter memory */ + sigPtr = signal_fx + lg; + Copy( sigPtr, mem_fx, mem_len ); + + return lg_out; +} Word16 modify_Fs_fx( /* o : length of output Q0 */ const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ Word16 lg, /* i : length of input Q0 */ diff --git a/lib_com/options.h b/lib_com/options.h index 34db79ed7a45a0e8110da0b67798735f3f9413e8..db4a7408c56eeff150da10981cdbb55112895855 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -54,11 +54,9 @@ #define SUPPORT_JBM_TRACEFILE /* Support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */ -//#define WMOPS /* Activate complexity and memory counters */ +/*#define WMOPS*/ /* Activate complexity and memory counters */ #ifdef WMOPS /*#define WMOPS_PER_FRAME*/ /* Output per-frame complexity (writes one float value per frame to the file "wmops_analysis") */ -/*#define WMOPS_DETAIL*/ /* Output detailed complexity printout for every function. Increases runtime overhead */ -/*#define WMOPS_WC_FRAME_ANALYSIS*/ /* Output detailed complexity analysis for the worst-case frame */ /*#define MEM_COUNT_DETAILS*/ /* Output detailed memory analysis for the worst-case frame (writes to the file "mem_analysis.csv") */ #endif @@ -183,7 +181,7 @@ #define FIX_871_REMOVE_UNNECESSARY_CONDITION /* VA: remove a condition that is not needed and prevented correct frame classification of the secondary channel of the TD stereo */ #define FIX_875_SATURATION_DURING_ROUNDING /* VA: fix a possible saturation when rounding */ - +#define FIX_882_LOW_LEVEL_DISCONTINUITIES /* VA: Fix 882, discontinuities for low level signal by adding a scaling function that uses rounding, this function is more complex than normal one, has to be used only when necessary*/ #define FIX_879_DIFF_CONCEAL_PATH /* FhG: Fix for issue 879 and different concelalment paths that led to crash */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_com/parameter_bitmaping.c b/lib_com/parameter_bitmaping.c index 4c8d6d9993763eabe312a33229f06fe6ee9dab54..ff7a9c5bd6783d0bc3a10e91833ece8cdc33996b 100644 --- a/lib_com/parameter_bitmaping.c +++ b/lib_com/parameter_bitmaping.c @@ -187,6 +187,64 @@ void GetParameters( return; } +void GetParameters_fx( + ParamsBitMap const *paramsBitMap, + const Word16 nArrayLength, // Q0 + void const *pParameter, // Q0 + Word16 **pStream, // Q0 + Word16 *pnSize, // Q0 + Word16 *pnBits ) // Q0 +{ + Word16 index; + Word16 iParam, nParams; + Word16 value; + void const *pSubStruct; + + assert( ( paramsBitMap != NULL ) && ( nArrayLength > 0 ) && ( pParameter != NULL ) && ( pStream != NULL ) && ( pnSize != NULL ) && ( pnBits != NULL ) ); + + nParams = paramsBitMap->nParams; + move16(); + FOR( index = 0; index < nArrayLength; index++ ) + { + FOR( iParam = 0; iParam < nParams; iParam++ ) + { + ParamBitMap const *const param = ¶msBitMap->params[iParam]; + +#define WMC_TOOL_SKIP + pSubStruct = param->GetParamValue( pParameter, index, &value ); +#undef WMC_TOOL_SKIP + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + IF( param->fZeroAllowed || ( param->EncodeValue != NULL ) ) + { + *( *pStream )++ = value; + move16(); + } + ELSE + { + *( *pStream )++ = sub( value, 1 ); + move16(); + } + ++*pnSize; +#define WMC_TOOL_SKIP + IF( ( param->nBits != 0 ) ) + { + *pnBits = add( *pnBits, param->nBits ); + } + ELSE + { + *pnBits = add( *pnBits, param->GetNumberOfBits( value, index ) ); + } + move16(); +#undef WMC_TOOL_SKIP + IF( ( param->pSubParamBitMap != NULL ) && ( value > 0 ) ) + { + GetParameters_fx( param->pSubParamBitMap, value, ( pSubStruct != NULL ) ? pSubStruct : pParameter, pStream, pnSize, pnBits ); + } + } + } + + return; +} void SetParameters( ParamsBitMap const *paramsBitMap, diff --git a/lib_com/prot.h b/lib_com/prot.h index df837c21f38acea83410e4bb488316923234f0ed..e302692962f3e3fd184a3041de7a231875028e4b 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -2379,9 +2379,9 @@ ivas_error acelp_core_enc( ); #else ivas_error acelp_core_enc( - Encoder_State *st, /* i/o: encoder state structure */ - /*const*/ float inp[], /* i : input signal of the current frame */ - const float ener, /* i : residual energy from Levinson-Durbin */ + Encoder_State *st, /* i/o: encoder state structure */ + /*const*/ float inp[], /* i : input signal of the current frame */ + // const float ener, /* i : residual energy from Levinson-Durbin */ float A[NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes */ float Aw[NB_SUBFR16k * ( M + 1 )], /* i : weighted A(z) unquant. for subframes */ const float epsP[M + 1], /* i : LP prediction errors */ @@ -5985,10 +5985,13 @@ void core_switching_pre_enc( ); void core_switching_post_enc( - Encoder_State *st, /* i/o: encoder state structure */ - const float *old_inp_12k8, /* i : old input signal @12.8kHz */ - const float *old_inp_16k, /* i : old input signal @16kHz */ - const float A[] /* i : unquant LP filter coefs. */ + Encoder_State *st, /* i/o: encoder state structure */ + // const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + float *old_inp_12k8, /* i : old input signal @12.8kHz */ + // const float *old_inp_16k, /* i : old input signal @16kHz */ + float *old_inp_16k, /* i : old input signal @16kHz */ + // const float A[] /* i : unquant. LP filter coefs. */ + float A[] /* i : unquant. LP filter coefs. */ ); ivas_error core_switching_post_dec( @@ -6173,10 +6176,12 @@ void Next_good_after_burst_erasures( const int16_t ol_size /* i : overlap size */ ); +#ifndef IVAS_FLOAT_FIXED void update_average_rate( SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ const int32_t core_brate /* i : core bitrate */ ); +#endif void reset_preecho_dec( HQ_DEC_HANDLE hHQ_core /* i/o: HQ decoder handle */ @@ -9195,8 +9200,10 @@ void analysisCldfbEncoder_ivas( float *ppBuf_Ener ); void analysisCldfbEncoder_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - const Word16 *timeIn, + Encoder_State *st, /* i/o: encoder state structure */ + Word32 *timeIn, /*q11*/ + Word16 timeInq, /*q0*/ + Word16 samplesToProcess, /*q0*/ Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], @@ -10021,7 +10028,7 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int16_t isTNSActive, /* i : flag indicating if the TNS is active */ const int16_t sp_aud_decision0, /* i : first stage switching decision */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ); diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 9c6706c11a1c7ff49b454ed46e60187c943f08b4..a468fe60781de9389288dc3825bce0da4fec8508 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -88,6 +88,7 @@ Word32 floatToFixed( float f, Word16 Q ); float fixedToFloat( Word32 i, Word16 Q ); Word32 floatToFixed_32( float f, Word16 Q ); float fixedToFloat_32( Word32 i, Word16 Q ); +float fixedToFloat_16( Word16 i, Word16 Q ); void floatToFixed_arr16( float *f, Word16 *i, Word16 Q, Word16 l ); void floatToFixed_arr32( float *f, Word32 *i, Word16 Q, Word16 l ); @@ -871,6 +872,29 @@ void lsf_syn_mem_restore_fx( Word16 pstreaklen /* i:LSF quantizer */ ); +#ifdef IVAS_FLOAT_FIXED +void lsf_syn_mem_restore_ivas_fx( + Encoder_State *st_fx, /* o: state structure */ + Word16 btilt_code_fx, /* i: */ + Word32 gc_threshold_fx, /* i: */ + Word16 *clip_var_bck_fx, /* i: */ + Word16 next_force_sf_bck_fx, /* i: */ + Word16 *lsp_new, /* o: LSP vector to quantize */ + Word16 *lsp_mid, /* o: mid-frame LSP vector */ + Word16 clip_var, /* i: pitch clipping state var */ + Word16 *mem_AR, /* i: quantizer memory for AR model */ + Word16 *mem_MA, /* i: quantizer memory for MA model */ + Word16 *lsp_new_bck, /* i: LSP vector to quantize- backup */ + Word16 *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + Word32 *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* i: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* i: synthesis filter memory */ + Word16 mem_w0_bck, /* i: memory of the weighting filter */ + Word16 streaklimit, /* i:LSF quantizer */ + Word16 pstreaklen /* i:LSF quantizer */ +); +#endif + void lsf_update_memory( Word16 narrowband, /* i : narrowband flag */ const Word16 qisf[], /* i : quantized xSF coefficients */ @@ -1349,7 +1373,13 @@ void scale_sig32( const Word16 lg, /* i : size of x[] Q0 */ const Word16 exp0 /* i : exponent: x = round(x << exp) Qx xx exp */ ); - +#ifdef FIX_882_LOW_LEVEL_DISCONTINUITIES +void scale_sig32_r( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */ +); +#endif Word16 rescale_mem( const Word16 *Q_exc, /* i : current excitation scaling (>=0) */ Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */ @@ -1575,6 +1605,16 @@ void int_lsp4_fx( Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ ); +void int_lsp4_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +); + // interleave_spectrum.c void de_interleave_spectrum_fx( Word32 *coefs, /* i/o: i and output coefficients Q? */ @@ -1735,6 +1775,30 @@ void wtda_fx( const Word16 L /* i : length */ ); +#ifdef IVAS_FLOAT_FIXED +void wtda_ivas_fx( + Word16 *new_audio, /* i : input audio Q0 */ + Word16 *Q, /* i/o : Q of input/Output Audio */ + Word16 *wtda_audio, /* o : windowed audio Qout */ + Word16 *old_wtda, /* i/o: windowed audio from previous frame Qout */ + Word16 *Qold_wtda, + const Word16 left_mode, /* i : window overlap of previous frame (0: full, 2: none, or 3: half) */ + const Word16 right_mode, /* i : window overlap of current frame (0: full, 2: none, or 3: half) */ + const Word16 L /* i : length */ +); +#endif + +#ifdef IVAS_FLOAT_FIXED +void wtda_ext_fx( + const Word16 *new_audio, /* i : input audio (Q_in) */ + Word16 *wtda_audio, /* o : windowed audio (Q_in) */ + const Word16 left_mode, /* i : window overlap of previous frame (0: full, 2: none, or 3: half) */ + const Word16 right_mode, /* i : window overlap of current frame (0: full, 2: none, or 3: half) */ + const Word16 L, /* i : length */ + const UWord16 kernel_type /* i : transform kernel type (0 - 3) */ +); +#endif + /*========================================================================================================/ swb_bwe_com_lr_fx.c /========================================================================================================*/ @@ -2414,6 +2478,17 @@ Word32 Interpol_lc_fx( /* o : interpolated value const Word16 nb_coef /* i : number of coefficients Q0 */ ); +Word16 modify_Fs_ivas_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[], /* i/o: filter memory Q0 */ + const Word16 nblp, /* i : flag indicating if NB low-pass is applied */ + Word16 *Q_new_inp, /*scaling added on sigOut_fx */ + Word16 *mem_decim_size /*i: size modified for mem_fx*/ +); // modif_fs_fx.c Word16 modify_Fs_fx( /* o : length of output Q0 */ const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ @@ -2659,6 +2734,13 @@ void save_old_syn_fx( ); // swb_tbe_com_fx.c +void find_td_envelope_fx( + const Word16 inp[], /* i : input signal Qx */ + const Word16 len, /* i : length of the input signal */ + const Word16 len_h, /* i : length of the MA filter */ + Word16 mem_h[], /* i/o: memory of the MA filter, length len_h/2 Qx */ + Word16 out[] /* o : td envelope of the input signal Qx */ +); void swb_tbe_reset_fx( Word32 mem_csfilt[], @@ -2954,10 +3036,10 @@ void interp_code_4over2_fx( void wb_tbe_extras_reset_synth_fx( Word16 state_lsyn_filt_shb[], Word16 state_lsyn_filt_dwn_shb[], Word16 state_32and48k_WB_upsample[], Word16 state_resamp_HB[] ); void elliptic_bpf_48k_generic_fx( - const Word16 input_fx[], /* i : i signal */ + const Word16 input_fx[], /* i : i signal Q_input_fx */ Word16 *Q_input_fx, Word16 output_fx[], /* o : output signal */ - Word32 memory_fx[][4], /* i/o: 4 arrays of 4 for memory */ + Word32 memory_fx[][4], /* i/o: 4 arrays of 4 for memory memory_fx_Q */ Word16 memory_fx_Q[], const Word16 full_band_bpf[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ ); @@ -3555,6 +3637,13 @@ void nelp_encoder_fx( Word16 *qIn1, Word16 reduce_gains ); +void nelp_encoder_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state */ + Word16 *in_fx, /* i : residual signal */ + Word16 *exc_fx, /* o : NELP quantized excitation signal */ + Word16 *qIn1, + Word16 reduce_gains ); + /*========================================================================================================/ swb_bwe_enc_lr_fx.c /========================================================================================================*/ @@ -3936,6 +4025,19 @@ void mdct_window_aldo( // tcx_utils.c Word16 getInvFrameLen( const Word16 L_frame ); /* returns 1/L_frame in Q21 format */ +#ifdef IVAS_FLOAT_FIXED +void tcx_get_windows( + TCX_CONFIG_HANDLE hTcxCfg, /* i : TCX configuration */ + const Word16 left_mode, /* i: overlap mode of left window half */ + const Word16 right_mode, /* i: overlap mode of right window half */ + Word16 *left_overlap, /* o: left overlap length */ + const PWord16 **left_win, /* o: left overlap window */ + Word16 *right_overlap, /* o: right overlap length */ + const PWord16 **right_win, /* o: right overlap window */ + const Word8 fullband /* i: fullband flag */ +); +#endif + void WindowSignal( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 offset, /* i : left folding point offset relative to the i signal pointer */ @@ -5867,6 +5969,14 @@ Word32 dotp_fixed_32( Word16 *res_q /*stores resultant Q*/ ); +Word32 dotp_fixed_ivas_fx( + const Word32 x[], /* i : vector x[] */ + Word16 x_e, + const Word32 y[], /* i : vector y[] */ + Word16 y_e, + const Word16 n, /* i : vector length */ + Word16 *out_e ); + #ifdef IVAS_FLOAT_FIXED Word32 dotp_fixed_guarded( const Word32 x[], /* i : vector x[] */ @@ -7443,6 +7553,15 @@ void fd_bwe_dec_init( FD_BWE_DEC_HANDLE hBWE_FD /* i/o: FD BWE data handle */ ); +void hq_core_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 *audio_fx, /* i : input audio signal Q0 */ + const Word16 input_frame, /* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag, /* i : Voicing flag for FER method selection */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); + // hq_core_dec_fx.c void hq_core_dec_fx( Decoder_State *st_fx, /* i/o: decoder state structure fx */ @@ -7459,6 +7578,7 @@ void HQ_nbfec_init_fx( HQ_NBFEC_HANDLE hHQ_nbfec /* i/o: HQ NB FEC data handle */ ); +void GetAttackForTCXDecision_fx( Word32 const *pSubblockNrg, Word32 const *pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 *pbIsAttackPresent, Word16 *pAttackIndex ); // FEC_HQ_phase_ecu_fx.c void hq_ecu_fx( @@ -8188,6 +8308,29 @@ void stat_noise_uv_mod_fx( Word16 *Q_stat_noise_ge /* i/o: noise scaling */ ); +void stat_noise_uv_mod_ivas_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter Q=0 */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr Q=15*/ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes Q=12*/ + Word16 *exc2, /* i/o: excitation buffer Q=Q_exc*/ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi, /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain Q=Q_stat_noise_ge (6) */ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP Q=15*/ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha Q=15*/ + Word16 *exc_pe, /* i/o: scale Q_stat_noise Q=Q_stat_noise*/ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : i bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +); + // FEC_adao_codebook_fx.c Word16 FEC_SinOnset_fx( Word16 *exc, /* i/o : exc vector to modify */ @@ -8662,6 +8805,22 @@ void GetParameters( int16_t *pnSize, int16_t *pnBits ); +void GetParameters_fx( + ParamsBitMap const *paramsBitMap, + const Word16 nArrayLength, // Q0 + void const *pParameter, // Q0 + Word16 **pStream, // Q0 + Word16 *pnSize, // Q0 + Word16 *pnBits ); // Q0 + +void EncodeTnsData_ivas_fx( + STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + STnsData const *pTnsData, /* i : TNS data struct (quantized param) */ + Word16 *stream, /* o : internal data stream Q0*/ + Word16 *pnSize, /* o : number of written parameters Q0*/ + Word16 *pnBits /* o : number of written bits Q0*/ +); + void SetParameters( ParamsBitMap const *paramsBitMap, const int16_t nParams, @@ -9537,6 +9696,11 @@ Word32 sum2_f_16_gb_fx( const Word16 lvec, /* i : length of input vector */ Word16 gb ); +Word32 sum_32_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 *e ); + Word16 vq_dec_lvq_ivas_fx( Word16 sf_flag, /* i : safety net flag */ Word16 x[], /* o : Decoded vector Q(x2.56)*/ @@ -9716,6 +9880,11 @@ Word16 mean_fx( /* o : mean of vector const Word16 lvec_fx /* i : length of i vector */ ); +Word16 mean_no_sat_fx( /* o : mean of vector Qx */ + const Word16 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx /* i : length of input vector */ +); + void sort( UWord16 *x, /* i/o: Vector to be sorted */ UWord16 len /* i/o: vector length */ @@ -9915,9 +10084,9 @@ Word32 root_a_fx( Word16 *exp_out ); Word32 root_a_over_b_fx( - Word32 a, + Word32 a, /* Q(Q_a) */ Word16 Q_a, - Word32 b, + Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ); @@ -9975,6 +10144,13 @@ Word16 squant_fx( /* o: index of the winning codeword */ const Word16 cbsize /* i: codebook size */ ); +Word16 squant_int_fx( + UWord8 x, /* i : scalar value to quantize */ + UWord8 *xq, /* o : quantized value */ + const UWord8 *cb, /* i : codebook */ + const Word16 cbsize /* i : codebook size */ +); + void pz_filter_dp_fx( const Word16 b[], const Word16 a[], @@ -10163,6 +10339,24 @@ Word32 imax_pos_fx( const Word32 *y /* i : Input vector for peak interpolation */ ); +void msvq_enc_ivas_fx( + const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) Q_cb */ + const Word16 Q_cb, /* i : Codebook Q */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word32 u_fx[], /* i : Vector to be encoded (prediction and mean removed) (exp : u_e) */ + const Word16 u_e, /* i : Exponent for Vector to be encoded */ + const Word16 *levels, /* i : Number of levels in each stage */ + const Word16 maxC, /* i : Tree search size (number of candidates kept from from one stage to the next == M-best) */ + const Word16 stages, /* i : Number of stages */ + const Word16 w[], /* i : Weights Q8 */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 applyDCT_flag, /* i : applyDCT flag */ + Word32 *invTrfMatrix_fx, /* i/o: synthesis matrix Q31 */ + Word16 Idx[] /* o : Indices */ +); + void msvq_dec_fx( const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ @@ -10390,14 +10584,33 @@ Word16 sr2fscale( // pre_proc functions /*full implementation pending*/ + +void Copy_Scale_sig32( + const Word32 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + void swb_pre_proc_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - float *new_swb_speech, /* o : original input signal at 32kHz */ - Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz */ - float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ - float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ - float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer */ - CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ + Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ + Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 *shb_speech_32, /* o : SHB target signal (6-14kHz) at 16kHz- Q - q_reImBuffer */ + Word16 *use_shb32, /* o : flags valid data in 32-bit shb buffer for better precision. */ + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ + Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +); + +void core_encode_update_ivas_fx( + Encoder_State *st /* i/o: Encoder state structure */ +); + +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ ); // tools.c @@ -10407,6 +10620,13 @@ Word32 sum2_f_32_fx( /* o : Q(2x - 31 - gb) Word16 gb /* i : guard bits */ ); +Word32 sum2_16_exp_fx( + const Word16 *vec, /* i : input vector Q(15 - exp) */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +); + Word32 sum2_32_exp_fx( const Word32 *vec, /* i : input vector, Qx */ const Word16 lvec, /* i : length of input vector */ @@ -10674,4 +10894,63 @@ void init_tcx_cfg_ivas_fx( const Word16 ini_frame, const Word16 MCT_flag ); +Word16 msvq_stage1_dct_search_fx( + const Word32 *u_fx, /* i : target exp : u_e */ + const Word16 u_e, /* i : exp for target Q0 */ + const Word16 N, /* i : target length and IDCT synthesis length */ + const Word16 maxC_st1, /* i : number of final stage 1 candidates to provide */ + const DCTTYPE dcttype, /* e.g. DCT_T2_16_XX, DCT_T2_24_XX; */ + const Word16 max_dct_trunc, /* i : maximum of truncation lenghts */ + Word32 *invTrfMatrix_fx, /* i : IDCT synthesis matrix for dim N Q31 */ + const Word16 *midQ_truncQ_fx, /* i : midQ vector */ + const Word32 *dct_scaleF_fx, /* i : global scale factors Q10 */ + const Word16 n_segm, /* i : number of segments */ + const Word16 *cols_per_segment, /* i : remaining length per segment */ + const Word16 *trunc_dct_cols_per_segment, /* i : trunc length per segment */ + const Word16 *entries_per_segment, /* i : number of rows per segment */ + const Word16 *cum_entries_per_segment, /* i : number of cumulative entries */ + const Word8 *const W8Qx_dct_sections[], /* i : Word8(byte) segment table ptrs */ + const Word16 *col_syn_shift[], /* i : columnwise syn shift tables */ + const Word8 *segm_neighbour_fwd, /* i : circular neighbour list fwd */ + const Word8 *segm_neighbour_rev, /* i : circular neighbour list reverse */ + const Word16 npost_check, /* i : number of neigbours to check , should be even */ + Word32 *st1_mse_ptr_fx, /* i : dynRAM buffer for MSEs exp : u_e */ + Word16 *indices_st1_local, /* o : selected cand indices */ + Word32 *st1_syn_vec_ptr_fx, /* i/o: buffer for IDCT24 synthesis i :exp : u_e */ + Word32 *dist1_ptr_fx, /* o : resulting stage 1 MSEs in DCT-N domain */ + Word16 *dist1_ptr_e ); + +Word16 msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( + const Word32 *st1_syn_vec_ptr_fx, /* i : IDCT24 synthesis vectors */ + const Word16 st1_syn_vec_e, /* i : exp for IDCT24 synthesis vectors */ + const Word32 *u_fx, /* i : target signal */ + const Word16 u_e, /* i : exp for target signal */ + const int16_t maxC_st1, /* i : number of candidates in stage1 */ + Word32 *dist_ptr_fx, /* i/o: updated MSE vector for stage1 */ + Word16 *dist_ptr_e /* i/o: exp for updated MSE vector for stage1 */ +); + +void FEC_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const ACELP_config acelp_cfg, /* i/o: configuration of the ACELP */ + const Word16 *synth, /* i : pointer to synthesized speech for E computation */ + const Word16 coder_type, /* i : type of coder */ + Word16 clas, /* i : signal clas for current frame */ + const Word16 *fpit, /* i : close loop fractional pitch buffer Q6 */ + const Word16 *res, /* i : LP residual signal frame */ + Word16 *last_pulse_pos, /* i/o: Position of the last pulse */ + const Word16 L_frame, /* i : Frame length */ + const Word32 total_brate, /* i : total codec bitrate */ + const Word16 Q_synth /* i : input scaling */ +); + +ivas_error IGF_Reconfig_fx( + IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word16 igf, /* i : IGF on/off */ + const Word16 reset, /* i : reset flag */ + const Word32 brate, /* i : bitrate for configuration */ + const Word16 bwidth, /* i : signal bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +); #endif diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index a442ebd84e0bc2582b8d111024f9484deb20761e..a496c0dd1c065d5fdd27cb99aa133c109c7761b8 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -481,7 +481,14 @@ const float crit_bands[] = 1720.0f, 2000.0f, 2320.0f, 2700.0f, 3150.0f, 3700.0f, 4400.0f, 5300.0f, 6350.0f, 7700.0f, 9500.0f, 12000.0f, 15500.0f, 40000.0f }; - +#ifdef IVAS_FLOAT_FIXED +const Word32 crit_bands_fx[] =//Q0 +{ + 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, + 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6350, 7700, + 9500, 12000, 15500, 40000 +}; +#endif const float crit_bins_corr[CRIT_NOIS_BAND] = { 0.9f, 0.9f, 0.85f, 0.8f, 0.775f, 0.75f, 0.725f, 0.7f, 0.675f, 0.65f, 0.625f, @@ -11803,6 +11810,7 @@ const Word8* const cdk_37bits_ivas_stage1_W8Qx_dct_sections[] = { cdk1_ivas_dct_ /* scaling constants */ const float fdcng_dct_scaleF[3] = { 0.420288085937500f , (0.420288085937500f / 16.0f) , (0.420288085937500f * 0.420288085937500f) / (16.0f*16.0f) }; const float fdcng_dct_invScaleF[2] = { 2.379272460937500f ,2.379272460937500f*16.0f }; +const Word32 fdcng_dct_scaleF_fx[3] = { 902561792, 56410112,1481781 }; const Word16 stage1_col_syn_shift_segm0[8] = { 4, 4, 4, 3, 2, 2, 2, 1 @@ -40859,37 +40867,41 @@ const Word16 swb_lsp_prev_interp_init[10] = { 32767, 31164, 26510, 19261, 10126, 22.f for L_FRAME25_6k, 23.5f for L_FRAME32k; */ -const Word16 pow_tilt_16k[64] = { /* Q7 */ - 128, 137, 147, 157, 168, 181, 194, 208, - 223, 239, 256, 274, 294, 315, 338, 362, - 388, 416, 446, 478, 513, 550, 589, 632, - 677, 726, 778, 834, 894, 958, 1027, 1101, - 1181, 1266, 1357, 1454, 1559, 1671, 1791, 1920, - 2058, 2206, 2365, 2535, 2717, 2913, 3122, 3347, - 3587, 3845, 4122, 4418, 4736, 5077, 5442, 5833, - 6253, 6702, 7184, 7701, 8255, 8848, 9485, 10167 -}; - -const Word16 pow_tilt_25_6k[64] = { /* Q7 */ - 128, 138, 150, 162, 176, 191, 207, 224, - 243, 263, 286, 309, 335, 364, 394, 427, - 463, 502, 544, 589, 639, 692, 750, 813, - 881, 955, 1035, 1122, 1216, 1317, 1428, 1547, - 1677, 1817, 1970, 2135, 2313, 2507, 2717, 2945, - 3191, 3459, 3748, 4062, 4402, 4771, 5170, 5603, - 6072, 6581, 7132, 7729, 8376, 9078, 9838, 10662, - 11554, 12522, 13570, 14707, 15938, 17273, 18719, 20286 -}; - -const Word16 pow_tilt_32k[64] = { /* Q7 */ - 128, 139, 151, 165, 180, 196, 214, 233, - 254, 277, 302, 329, 358, 390, 426, 464, - 505, 551, 600, 654, 713, 777, 846, 922, - 1005, 1095, 1194, 1301, 1417, 1545, 1683, 1834, - 1999, 2178, 2373, 2586, 2818, 3071, 3347, 3647, - 3974, 4330, 4719, 5142, 5603, 6106, 6654, 7250, - 7901, 8609, 9381, 10223, 11140, 12139, 13228, 14414, - 15707, 17115, 18650, 20323, 22146, 24132, 26297, 28655 + +/* Q23 */ +const Word32 pow_tilt_16k[64] = { + 8388608, 8991841, 9638454, 10331564, 11074518, 11870897, 12724546, 13639580, + 14620416, 15671785, 16798759, 18006775, 19301660, 20689662, 22177476, 23772281, + 25481769, 27314189, 29278380, 31383818, 33640660, 36059793, 38652889, 41432458, + 44411907, 47605612, 51028980, 54698525, 58631951, 62848233, 67367713, 72212193, + 77405045, 82971319, 88937870, 95333482, 102189009, 109537523, 117414477, 125857870, + 134908436, 144609837, 155008876, 166155720, 178104145, 190911793, 204640453, 219356353, + 235130489, 252038960, 270163335, 289591052, 310415836, 332738151, 356665686, 382313874, + 409806450, 439276044, 470864826, 504725189, 541020486, 579925813, 621628862, 666330818 +}; + +/* Q23 */ +const Word32 pow_tilt_25_6k[64] = { + 8388608, 9090977, 9852154, 10677063, 11571041, 12539871, 13589820, 14727680, + 15960812, 17297192, 18745466, 20315003, 22015955, 23859325, 25857039, 28022019, + 30368270, 32910971, 35666569, 38652889, 41889251, 45396590, 49197594, 53316853, + 57781011, 62618949, 67861961, 73543965, 79701717, 86375050, 93607134, 101444752, + 109938604, 119143637, 129119397, 139930415, 151646628, 164343826, 178104145, 193016600, + 209177658, 226691863, 245672512, 266242389, 288534558, 312693225, 338874669, 367248256, + 397997530, 431321405, 467435450, 506573283, 548988082, 594954222, 644769055, 698754827, + 757260765, 820665338, 889378703, 963845359, 1044547023, 1132005744, 1226787283, 1329504771 +}; + +/* Q23 */ +const Word32 pow_tilt_32k[64] = { + 8388608, 9140953, 9960774, 10854121, 11827590, 12888365, 14044278, 15303861, + 16676411, 18172061, 19801850, 21577810, 23513049, 25621853, 27919788, 30423818, + 33152425, 36125751, 39365745, 42896322, 46743545, 50935812, 55504069, 60482037, + 65906462, 71817384, 78258437, 85277166, 92925380, 101259536, 110341153, 120237270, + 131020935, 142771749, 155576454, 169529568, 184734089, 201302251, 219356353, 239029666, + 260467410, 283827832, 309283369, 337021925, 367248256, 400185482, 436076734, 475186948, + 517804822, 564244946, 614850125, 669993906, 730083343, 795561993, 866913198, 944663645, + 1029387260, 1121709444, 1222311686, 1331936594, 1451393382, 1581563835, 1723408827, 1877975405 }; const Word16 L_frame_inv[8] = { 0x4000, 0x369D, 0x3333, 0x2D83, 0x2AAB, 0x28F6, 0, 0x2222 }; diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 3eb6bdf92c2f83894f6272a5be64c5fde271bfc1..3bf5740f56c6118da1038219da3ff53b74e99ee3 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -184,6 +184,9 @@ extern const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB]; extern const float h_high[]; /* HP filter for filtering random part of excitation in FEC */ extern const Word16 h_high_fx[5]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 crit_bands_fx[]; +#endif // IVAS_FLOAT_FIXED extern const float crit_bands[]; /* Table of critical bands */ extern const float sincos_t[]; /* FFT - sinus and cosinus tables */ extern const Word16 sincos_t_fx[161]; @@ -207,6 +210,7 @@ extern const float grid40[]; /* Table of grid points for evaluating Cheby #ifdef IVAS_FLOAT_FIXED extern const Word16 grid50_fx[( GRID50_POINTS - 1 ) / 2 - 1]; extern const Word16 grid40_fx[( GRID40_POINTS - 1 ) / 2 - 1]; +extern const Word32 crit_bands_fx[]; /* Table of critical bands */ #endif extern const float grid100[]; /* Table of 100 grid points for evaluating Chebyshev polynomials */ @@ -1770,6 +1774,7 @@ extern const Word16 cdk1r_tr_midQ_truncQ_fx[]; #endif extern const float fdcng_dct_invScaleF[]; extern const float fdcng_dct_scaleF[]; +extern const Word32 fdcng_dct_scaleF_fx[]; extern const Word16 unique_idctT2_24coeffsQ16[]; @@ -2149,9 +2154,9 @@ extern const Word16 Es_pred_qua_2[16]; extern const Word16 T_DIV_L_Frame[]; /*0Q15 * 2^-7 */ // ivas_sns_com_fx.c -extern const Word16 pow_tilt_16k[64]; /* Q7 */ -extern const Word16 pow_tilt_25_6k[64]; /* Q7 */ -extern const Word16 pow_tilt_32k[64]; /* Q7 */ +extern const Word32 pow_tilt_16k[64]; /* Q23 */ +extern const Word32 pow_tilt_25_6k[64]; /* Q23 */ +extern const Word32 pow_tilt_32k[64]; /* Q23 */ /*EVS basop*/ diff --git a/lib_com/scale_mem_fx.c b/lib_com/scale_mem_fx.c index 2e61cb93851f6c4ecd3d80bc635244242a40b630..c02eff2a512d205ab069ba0e9004a0c11fb074ba 100644 --- a/lib_com/scale_mem_fx.c +++ b/lib_com/scale_mem_fx.c @@ -309,7 +309,23 @@ void scale_sig32( move32(); } } +#ifdef FIX_882_LOW_LEVEL_DISCONTINUITIES +void scale_sig32_r( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */ +) +{ + Word16 i; + FOR( i = 0; i < lg; i++ ) + { + /* saturation can occur here */ + x[i] = L_shl_r( x[i], exp0 ); + move32(); + } +} +#endif /*-------------------------------------------------------------------* * Rescale_mem: diff --git a/lib_com/stat_noise_uv_mod_fx.c b/lib_com/stat_noise_uv_mod_fx.c index e91ea907e3085529012cd2d9b505d6a8ec7f1242..c022ab04f7eca5102b75236fd166f48a4517bb6e 100644 --- a/lib_com/stat_noise_uv_mod_fx.c +++ b/lib_com/stat_noise_uv_mod_fx.c @@ -358,6 +358,339 @@ void stat_noise_uv_mod_fx( } } } + +/*--------------------------------------------------------------------* + * stat_noise_uv_mod() + * + * Modifies excitation signal in stationary noise segments + *--------------------------------------------------------------------*/ + +void stat_noise_uv_mod_ivas_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter Q=0 */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr Q=15*/ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes Q=12*/ + Word16 *exc2, /* i/o: excitation buffer Q=Q_exc*/ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi, /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain Q=Q_stat_noise_ge (6)*/ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP Q=15*/ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha Q=15*/ + Word16 *exc_pe, /* i/o: scale Q_stat_noise Q=Q_stat_noise*/ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : i bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +) +{ + Word16 exctilt; /* Q15 */ + Word32 vare; /* Q31 */ + Word16 randval; /* Q?? */ + Word16 alpha; /* Q15 */ + Word16 alpha_m1; /* (1-alpha) Q15 */ + Word16 min_alpha; /* Q15 */ + Word16 lspnew_s[M]; /* Same for all LSP (Q15) */ + Word16 oldlsp_mix[M]; + Word16 midlsp_mix[M]; + Word16 newlsp_mix[M]; + Word16 beta; /* Q15 */ + Word16 Noimix_fract; /* (noimix_fac - 1.0) in Q15 */ + /* noimix_fax * x <-> x + Noimix_fract * x */ + Word16 i_subfr; + Word16 i, k; + + /* Work variables for div and sqrt */ + Word16 tmp_nom, tmp_den, tmp_shift, tmp_res; + Word16 Qdiff, Q_local; /* new Q to be used for states Exc_pe and Ge_sm, and Exc2_local */ + Word32 L_tmp_res, L_tmp, L_tmp3, L_Ge; + + Word16 En_shift, Tmp; + Word16 Exc2_local[L_FRAME]; /* local_copy in scaled Q_local*/ +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /*---------------------------------------------------------* + * Init local variables + *---------------------------------------------------------*/ + alpha = 32767; + move16(); + min_alpha = 16384; + move16(); + + test(); + test(); + test(); + IF( EQ_16( coder_type, INACTIVE ) && ( EQ_32( bitrate, ACELP_9k60 ) || ( LT_32( bitrate, ACELP_9k60 ) && GT_16( bwidth_fx, NB ) ) ) ) + { + min_alpha = *st_min_alpha; + move16(); + /*---------------------------------------------------------* + * decode noisiness parameter + *---------------------------------------------------------*/ + IF( bfi == 0 ) + { + tmp_den = 31; + move16(); + tmp_shift = norm_s( tmp_den ); + L_tmp_res = L_deposit_h( noisiness ); + L_tmp_res = L_shl( L_tmp_res, sub( tmp_shift, 1 ) ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_l( L_tmp_res, tmp_den ); +#ifdef BASOP_NOGLOB + min_alpha = add_o( tmp_res, 16384, &Overflow ); +#else /* BASOP_NOGLOB */ + min_alpha = add( tmp_res, 16384 ); +#endif /* BASOP_NOGLOB */ + + /**st_min_alpha = sub(*st_min_alpha, 1638); move16();*/ + min_alpha = s_max( min_alpha, sub( *st_min_alpha, 1638 ) ); + + *st_min_alpha = min_alpha; + move16(); + } + } + + /*---------------------------------------------------------* + * Mix excitation signal with random noise + *---------------------------------------------------------*/ + test(); + test(); + test(); + IF( EQ_16( coder_type, INACTIVE ) && ( EQ_32( bitrate, ACELP_9k60 ) || ( LT_32( bitrate, ACELP_9k60 ) && GT_16( bwidth_fx, NB ) ) ) ) + { + /* use a local working copy for scaling and filtering, not needed if input Q-range is fixed */ + Copy( exc2, Exc2_local, L_FRAME ); + + /* bound Q for internal use, optimization possible */ + Q_local = s_min( 11, s_max( -1, Q_exc ) ); + /* local excitation Q and incoming excitation Q*/ + Qdiff = sub( Q_local, Q_exc ); + /* only shift if incoming Q is outside [11..-1] shift is done in energy calculations aswell */ + Scale_sig( Exc2_local, L_FRAME, Qdiff ); + /* current excitation Q and previous stat_noise states Q */ + Qdiff = sub( Q_local, *Q_stat_noise ); + + *Q_stat_noise_ge = GE_SHIFT; + move16(); /* assign the fixed Q for Ge_sm */ + + IF( Qdiff != 0 ) + { + Scale_sig( exc_pe, 1, Qdiff ); + } + + En_shift = 0; + move16(); + if ( GT_16( Q_local, 3 ) ) + { + /* increase margin for energy accumulation in calc_tilt and vare accumulation */ + En_shift = sub( Q_local, 3 ); + } + + IF( LT_16( min_alpha, TILT_COMP_LIM_FX ) ) + { + FOR( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + exctilt = calc_tilt_fx( &Exc2_local[i_subfr], En_shift, L_SUBFR ); /*Q15 */ +#ifdef BASOP_NOGLOB + exctilt = mult( shl_o( sub( TILT_COMP_LIM_FX, min_alpha ), 2, &Overflow ), exctilt ); /*Q15 */ +#else /* BASOP_NOGLOB */ + exctilt = mult( shl( sub( TILT_COMP_LIM_FX, min_alpha ), 2 ), exctilt ); /*Q15 */ +#endif /* BASOP_NOGLOB */ + + PREEMPH_FX( &Exc2_local[i_subfr], exctilt, L_SUBFR, exc_pe ); + } + } + + ( *uv_count )++; + + IF( LE_16( *uv_count, START_NG ) ) + { + alpha = 32767; + move16(); + *act_count = 3; + move16(); + Copy( lsp_new, lspold_s, M ); + } + ELSE + { + *uv_count = s_min( *uv_count, FULL_NG ); + move16(); + tmp_nom = sub( *uv_count, START_NG ); + tmp_den = sub( FULL_NG, START_NG ); + tmp_shift = norm_s( tmp_den ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_s( tmp_nom, tmp_den ); +#ifdef BASOP_NOGLOB + tmp_res = shl_o( tmp_res, tmp_shift, &Overflow ); +#else /* BASOP_NOGLOB */ + tmp_res = shl( tmp_res, tmp_shift ); +#endif + alpha = add( 32767, mult( tmp_res, sub( min_alpha, 32767 ) ) ); + + *act_count = 0; + move16(); + } + + /*---------------------------------------------------------* + * calculate lowpass filtered excitation gain + *---------------------------------------------------------*/ + Tmp = shr( Exc2_local[0], En_shift ); + vare = L_mult( Tmp, Tmp ); /* positive accumulation only */ + FOR( i = 1; i < L_FRAME; i++ ) + { + Tmp = shr( Exc2_local[i], En_shift ); +#ifdef BASOP_NOGLOB + vare = L_mac_sat( vare, Tmp, Tmp ); /* positive accumulation only */ +#else + vare = L_mac( vare, Tmp, Tmp ); /* positive accumulation only */ +#endif + } + + /* obtain Ge in Q_local with safety saturation */ + L_Ge = L_shl( L_Sqrt_Q0( L_shr( vare, 1 ) ), add( sub( *Q_stat_noise_ge, 4 ), En_shift ) ); /* L_Ge in Q_local*/ + + /* st->ge_sm = ISP_SMOOTHING_QUANT_A1 * st->ge_sm + (1.0f-ISP_SMOOTHING_QUANT_A1) * ge */ + + IF( EQ_16( *uv_count, 1 ) ) + { + *ge_sm = L_shr( L_Ge, Q_local ); + move32(); + } + ELSE + { + L_tmp = Mult_32_16( L_Ge, P1 ); /* 0.1*ge still in Q local */ + L_tmp3 = Mult_32_16( *ge_sm, P9 ); /* 0.9*ge_sm still in Q_ge */ + + *ge_sm = L_add( L_shr( L_tmp, Q_local ), L_tmp3 ); + move32(); /* addition in Q_ge domain*/ + } + + /*--------------------------------------------------------------------* + * generate mixture of excitation and noise + * float: + * noimix_fac = 1.0f/(float)sqrt(alpha*alpha + (1-alpha)*(1-alpha)) + *--------------------------------------------------------------------*/ + + beta = shl( sub( alpha, 16384 ), 1 ); + alpha_m1 = sub( 32767, alpha ); + L_tmp_res = L_mac( 0, alpha, alpha ); + L_tmp_res = L_mac( L_tmp_res, alpha_m1, alpha_m1 ); + tmp_den = round_fx( L_Frac_sqrtQ31( L_tmp_res ) ); + + tmp_nom = sub( 32767, tmp_den ); + tmp_shift = norm_s( tmp_den ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_s( tmp_nom, tmp_den ); + + Noimix_fract = shr( tmp_res, tmp_shift ); /* float value is in range 0.0 to 0.42 */ + + /* L_Ge might be 0 in unvoiced WB */ + L_Ge = L_max( L_Ge, 1 ); + tmp_shift = norm_l( L_Ge ); + tmp_den = extract_h( L_shl( L_Ge, tmp_shift ) ); /* Q_local+Q_ge+tmp_shift-16 */ + tmp_res = div_s( 1 << 14, tmp_den ); /* 15+14-Q_local-tmp_shift-Q_ge+16 */ + L_tmp_res = Mult_32_16( *ge_sm, tmp_res ); /* Q_stat_noise_ge+45-Q_local-Q_ge-tmp_shift-15 */ + L_tmp_res = Mult_32_16( L_tmp_res, sub( 32767, beta ) ); /*30-Q_local-tmp_shift+15-15 */ +#ifdef BASOP_NOGLOB + L_tmp_res = L_add_sat( L_shl_sat( L_tmp_res, sub( add( Q_local, tmp_shift ), 15 ) ), beta ); /* Q15 */ +#else + L_tmp_res = L_add( L_shl( L_tmp_res, sub( add( Q_local, tmp_shift ), 15 ) ), beta ); /* Q15 */ +#endif +#ifdef BASOP_NOGLOB + tmp_res = extract_h( L_shl_o( L_tmp_res, 15, &Overflow ) ); /* 15+15-16=14 */ +#else + tmp_res = extract_h( L_shl( L_tmp_res, 15 ) ); /* 15+15-16=14 */ +#endif + + Noimix_fract = extract_l( Mult_32_16( L_tmp_res, Noimix_fract ) ); /*15+15-15 */ + + FOR( i = 0; i < L_FRAME; i++ ) + { + /*--------------------------------------------------------------------* + * flt: exc2[i] = noimix_fac*exc2[i] * alpha + st->ge_sm*Rnd*((1.0f)-alpha) + * flt: exc2[i] = (noimix_fract*exc2[i]+exc2 )* alpha + st->ge_sm*Rnd*((1.0f)-alpha) + * NB: currently uses 32bit accumulation for best low level performance, + * possibly overkill if input is always up-scaled + *--------------------------------------------------------------------*/ + + /* (1-alpha)*(float)sqrt(12.0f) * ((float)own_random(&(st->noimix_seed))/65536.0f) */ + randval = Random( noimix_seed ); /* +/-32767 */ + randval = mult_r( 28378, randval ); /* Q downscaled by 2 bits ends up in Q14 */ /*sqrt(12.0f) in Q13*/ + randval = extract_l( L_shl( Mult_32_16( L_Ge, randval ), sub( 1, *Q_stat_noise_ge ) ) ); /*Q_local+Q_ge+14-15+1-Q_ge=Q_local */ + + L_tmp = L_mult( Exc2_local[i], alpha ); /* Q_local + 16 */ + L_tmp = L_mac( L_tmp, randval, alpha_m1 ); /* Q_local + 16 */ + L_tmp3 = Mult_32_16( L_tmp, Noimix_fract ); /* Q_local+16+15-15 */ +#ifdef BASOP_NOGLOB + L_tmp = L_add_sat( L_tmp3, L_shl_sat( Mult_32_16( L_tmp, tmp_res ), 1 ) ); /* Q_local+16+14-15+1 */ +#else + L_tmp = L_add( L_tmp3, L_shl( Mult_32_16( L_tmp, tmp_res ), 1 ) ); /* Q_local+16+14-15+1 */ +#endif + Exc2_local[i] = extract_h( L_tmp ); /*Q_local */ + move16(); + } + *Q_stat_noise = Q_local; /* update for next call, routine can only be called once every frame */ + move16(); + Qdiff = sub( Q_exc, Q_local ); /* local excitation and incoming excitation */ + Scale_sig( Exc2_local, L_FRAME, Qdiff ); + Copy( Exc2_local, exc2, L_FRAME ); + + /*--------------------------------------------------------------------* + * Generate low-pass filtered version of ISP coefficients + *--------------------------------------------------------------------*/ + FOR( k = 0; k < M; k++ ) + { + move16(); + lspnew_s[k] = add( + mult( ISP_SMOOTHING_QUANT_A1_FX, lspold_s[k] ), + mult( 32767 - ISP_SMOOTHING_QUANT_A1_FX, lsp_new[k] ) ); + } + + /*--------------------------------------------------------------------* + * replace LPC coefficients + *--------------------------------------------------------------------*/ + + /*--------------------------------------------------------------------* + * pre-calculation of (1-beta) + *--------------------------------------------------------------------*/ + FOR( i = 0; i < M; i++ ) + { + move16(); + move16(); + move16(); + oldlsp_mix[i] = add( mult( beta, lsp_old[i] ), + mult( sub( 32767, beta ), lspold_s[i] ) ); + + midlsp_mix[i] = add( mult( beta, lsp_mid[i] ), + mult( sub( 32767, beta ), add( shr( lspold_s[i], 1 ), + shr( lspnew_s[i], 1 ) ) ) ); + + newlsp_mix[i] = add( mult( beta, lsp_new[i] ), + mult( sub( 32767, beta ), lspnew_s[i] ) ); + } + + int_lsp4_ivas_fx( L_FRAME, oldlsp_mix, midlsp_mix, newlsp_mix, Aq, M, 0 ); + Copy( lspnew_s, lspold_s, M ); + } + ELSE /* (unvoiced_vad != 0) */ + { + ( *act_count )++; + IF( GT_16( *act_count, 3 ) ) + { + *act_count = 3; + move16(); + *uv_count = 0; + move16(); + } + } +} /*---------------------------------------------------------------------------* * calc_tilt() * diff --git a/lib_com/swb_bwe_com_fx.c b/lib_com/swb_bwe_com_fx.c index a308d15596b74e9168d564093a36dab1b17518ff..0025812db446db36ad216c3c9af78c3a79558b5a 100644 --- a/lib_com/swb_bwe_com_fx.c +++ b/lib_com/swb_bwe_com_fx.c @@ -528,7 +528,6 @@ void calc_normal_length_fx( n_band = 0; move16(); pit = sp; - move16(); /*Q_syn */ FOR( i = 0; i < N; i++ ) { peak = 0; @@ -547,11 +546,11 @@ void calc_normal_length_fx( L_tmp = L_mult0( peak, 15 + THRES ); /*Q_syn */ IF( EQ_16( THRES, 8 ) ) { - L_tmp1 = L_shl( Mult_32_16( L_mean, 32767 ), 3 ); + L_tmp1 = L_shl( Mpy_32_16_1( L_mean, 32767 ), 3 ); } ELSE { - L_tmp1 = L_shl( Mult_32_16( L_mean, 32767 ), 2 ); + L_tmp1 = L_shl( Mpy_32_16_1( L_mean, 32767 ), 2 ); } test(); @@ -605,6 +604,7 @@ void calc_normal_length_fx( /**L_swb_norm = add(mult_r(L_swb_norm_cur, 3277), mult_r(*prev_L_swb_norm, 29491)); */ *L_swb_norm = round_fx( L_mac( L_mult( L_swb_norm_cur, 3277 ), *prev_L_swb_norm, 29491 ) ); + move16(); *prev_L_swb_norm = L_swb_norm_cur; move16(); } @@ -897,7 +897,7 @@ void calc_norm_envelop_fx( envelope[env_index] = L_tmp; move32(); env_index++; - i++; + i = add( i, 1 ); } return; diff --git a/lib_com/swb_tbe_com_fx.c b/lib_com/swb_tbe_com_fx.c index 891e2524c0e9b19d3c980863c97c43cfa12108da..6cd0d33023b4aff8d7cf06bbc6b57b25e0056268 100644 --- a/lib_com/swb_tbe_com_fx.c +++ b/lib_com/swb_tbe_com_fx.c @@ -18,6 +18,8 @@ #define POW_EXC16k_WHTND 1.14e11f /* power of random excitation, length 320 samples, uniform distribution */ #define POW_EXC16k_WHTND_FX_INV_SQRT 6360 // Q31 #define POW_EXC16k_WHTND_FX 178125000 // Q-6 +#define THR_ENV_ERROR_PLOSIVE 200.0f /* threshold for envelope error used in plosive detection */ +#define THR_ENV_ERROR_PLOSIVE_FX 200 /* threshold for envelope error used in plosive detection Q0 */ /*-----------------------------------------------------------------* * Local function prototypes @@ -1158,6 +1160,7 @@ void flip_spectrum_and_decimby4_fx( /*--------------------------------------------------------------------------*/ /* CALLED FROM : */ /*==========================================================================*/ + #ifdef IVAS_FLOAT_FIXED void ivas_GenShapedWBExcitation_fx( Word16 *excSHB, /* o : synthesized shaped shb exctiation Q_bwe_exc*/ @@ -1455,20 +1458,20 @@ void ivas_GenShapedWBExcitation_fx( #endif void GenShapedWBExcitation_fx( - Word16 *excSHB, /* o : synthesized shaped shb exctiation Q_bwe_exc*/ - const Word16 *lpc_shb, /* i : lpc coefficients Q12*/ - Word16 *exc4kWhtnd, /* o : whitened synthesized shb excitation Q_bwe_exc*/ - Word32 *mem_csfilt, /* i/o : memory Q_bwe_exc+16*/ - Word16 *mem_genSHBexc_filt_down1, /* i/o : memory Q_bwe_exc*/ - Word16 *mem_genSHBexc_filt_down2, /* i/o : memory Q_bwe_exc*/ - Word16 *mem_genSHBexc_filt_down3, /* i/o : memory Q_bwe_exc*/ - Word16 *state_lpc_syn, /* i/o : memory Q_bwe_exc*/ - const Word16 coder_type, /* i : coding type */ - const Word16 *bwe_exc_extended, /* i : bwidth extended exciatation Q_bwe_exc*/ - const Word16 Q_bwe_exc, - Word16 bwe_seed[], /* i/o : random number generator seed */ - const Word16 voice_factors[], /* i : voicing factor Q15*/ - const Word16 uv_flag, /* i : unvoiced flag */ + Word16 *excSHB, /* o : synthesized shaped shb exctiation Q(Q_bwe_exc) */ + const Word16 *lpc_shb, /* i : lpc coefficients Q12 */ + Word16 *exc4kWhtnd, /* o : whitened synthesized shb excitation Q(Q_bwe_exc) */ + Word32 *mem_csfilt, /* i/o : memory Q(Q_bwe_exc+16) */ + Word16 *mem_genSHBexc_filt_down1, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *mem_genSHBexc_filt_down2, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *mem_genSHBexc_filt_down3, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *state_lpc_syn, /* i/o : memory Q(Q_bwe_exc) */ + const Word16 coder_type, /* i : coding type */ + const Word16 *bwe_exc_extended, /* i : bwidth extended exciatation Q(Q_bwe_exc) */ + const Word16 Q_bwe_exc, /* i : Q for memories */ + Word16 bwe_seed[], /* i/o : random number generator seed */ + const Word16 voice_factors[], /* i : voicing factor Q15 */ + const Word16 uv_flag, /* i : unvoiced flag */ const Word16 igf_flag ) { Word16 i, j, k; @@ -1498,6 +1501,9 @@ void GenShapedWBExcitation_fx( Flag Overflow = 0; move32(); #endif + move16(); + move16(); + move16(); /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ L_tmp = L_mult( voice_factors[0], 8192 ); @@ -1534,7 +1540,6 @@ void GenShapedWBExcitation_fx( create_random_vector_fx( exc4kWhtnd, L_FRAME16k / 4, bwe_seed ); IF( LT_16( Q_bwe_exc, 5 ) ) { - FOR( i = 0; i < L_FRAME16k / 4; i++ ) { exc4kWhtnd[i] = shl_r( exc4kWhtnd[i], sub( Q_bwe_exc, 5 ) ); /*Q(Q_bwe_exc)/Q5(if Q_bwe_exc > 5) */ @@ -1565,6 +1570,7 @@ void GenShapedWBExcitation_fx( /* Ensure pow1 is greater than zero when computing normalization */ max_val = 0; + move16(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) { excTmp2[i] = abs_s( exc4kWhtnd[i] ); @@ -1615,7 +1621,7 @@ void GenShapedWBExcitation_fx( excNoisyEnv[i] = L_add( *mem_csfilt, L_mult( csfilt_num2[0], excTmp2[i] ) ); #endif move32(); /* Q_bwe_exc+16 */ - *mem_csfilt = Mult_32_16( excNoisyEnv[i], neg_csfilt_den2[1] ); + *mem_csfilt = Mpy_32_16_1( excNoisyEnv[i], neg_csfilt_den2[1] ); move32(); /* Q_bwe_exc+16 */ } @@ -1623,9 +1629,10 @@ void GenShapedWBExcitation_fx( /* Ensure pow22 is greater than zero when computing normalization */ Lmax = 0; + move32(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) { - exc4k_32[i] = Mult_32_16( excNoisyEnv[i], exc4k[i] ); + exc4k_32[i] = Mpy_32_16_1( excNoisyEnv[i], exc4k[i] ); move32(); /* Q_bwe_exc+6 */ Lmax = L_max( Lmax, L_abs( exc4k_32[i] ) ); } @@ -1650,7 +1657,7 @@ void GenShapedWBExcitation_fx( #endif move16(); } - n2 = 30 - n2 - ( Q_bwe_exc + 6 ); + n2 = sub( sub( 30, n2 ), add( Q_bwe_exc, 6 ) ); pow22 = 1; move32(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) @@ -1719,7 +1726,7 @@ void GenShapedWBExcitation_fx( #else temp1 = round_fx( L_shl( Ltemp1, exp ) ); /* Q15 */ #endif - L_tmp = Mult_32_16( pow1, sub( 32767, tmp_vfac ) ); /* Q22*/ + L_tmp = Mpy_32_16_1( pow1, sub( 32767, tmp_vfac ) ); /* Q22*/ Ltemp2 = root_a_over_b_fx( L_tmp, sub( 22, shl( n1, 1 ) ), pow22, sub( 22, shl( n2, 1 ) ), &exp ); #ifdef BASOP_NOGLOB temp2 = round_fx_o( L_shl_o( Ltemp2, exp, &Overflow ), &Overflow ); /* Q15 */ @@ -1738,7 +1745,7 @@ void GenShapedWBExcitation_fx( exc4kWhtnd[k] = round_fx( L_tmp ); /* Q_bwe_exc */ #endif move16(); - k++; + k = add( k, 1 ); } } } @@ -1801,73 +1808,92 @@ void GenWBSynth_fx( return; } -#ifdef ADD_IVAS_TBE_CODE -void find_td_envelope( - const float inp[], /* i : input signal */ - const int16_t len, /* i : length of the input signal */ - const int16_t len_h, /* i : length of the MA filter */ - float mem_h[], /* i/o: memory of the MA filter, length len_h/2 */ - float out[] /* o : td envelope of the input signal */ + + +void find_td_envelope_fx( + const Word16 inp[], /* i : input signal Qx */ + const Word16 len, /* i : length of the input signal */ + const Word16 len_h, /* i : length of the MA filter */ + Word16 mem_h[], /* i/o: memory of the MA filter, length len_h/2 Qx */ + Word16 out[] /* o : td envelope of the input signal Qx */ ) { - int16_t k, K; - float buf_in[L_FRAME16k + MAX_LEN_MA_FILTER], *p_in, *p_out, *p_prev, w; + Word16 k, K; + Word16 buf_in[L_FRAME16k + MAX_LEN_MA_FILTER], *p_in, *p_out, *p_prev, w; + Word16 tmp1, tmp2; assert( len > 0 && len <= L_FRAME16k ); - K = (int16_t) ( len_h / 2 ); /* length of FIR filter memory = half of the total filter length */ - w = 1.0f / len_h; /* MA filtering coefficient */ + // len_h is 20 at all calling locations + K = 10; /* length of FIR filter memory = half of the total filter length */ + move16(); + w = 1639; /* 1 / 20 in Q15 */ /* MA filtering coefficient */ + move16(); /* copy filter memory to the input buffer */ - if ( mem_h != NULL ) + IF( mem_h != NULL ) { - mvr2r( mem_h, buf_in, K ); + Copy( mem_h, buf_in, K ); } - else + ELSE { /* no memory available, use the first len_h/2 samples as memory */ p_in = buf_in; - for ( k = 0; k < K; k++ ) + FOR( k = 0; k < K; k++ ) { - *p_in++ = (float) fabs( inp[k] ) * w; + *p_in++ = mult_r( abs_s( inp[k] ), w ); /* Qx */ + move16(); } } /* take the absolute value of the input signal and copy it to the input buffer */ /* multiply each value by 1 / filter length */ p_in = &buf_in[K]; - for ( k = 0; k < len; k++ ) + FOR( k = 0; k < len; k++ ) { - *p_in++ = (float) fabs( inp[k] ) * w; + *p_in++ = mult_r( abs_s( inp[k] ), w ); /* Qx */ + move16(); } /* update filter memory from the end of the input buffer */ - if ( mem_h != NULL ) + IF( mem_h != NULL ) { - mvr2r( &buf_in[len], mem_h, K ); + Copy( &buf_in[len], mem_h, K ); } /* do MA filtering */ - out[0] = sum_f( buf_in, len_h ); + out[0] = sum16_fx( buf_in, len_h ); + move16(); p_out = &buf_in[0]; /* pointer to leaving sample */ p_in = &buf_in[len_h]; /* pointer to entering sample*/ - for ( k = 1; k < len - K; k++ ) + FOR( k = 1; k < len - K; k++ ) { - out[k] = out[k - 1] - *p_out++ + *p_in++; + tmp1 = *p_out++; + move16(); + tmp2 = *p_in++; + move16(); + out[k] = add( sub( out[k - 1], tmp1 ), tmp2 ); /* Qx */ + move16(); } /* use IIR filtering to extrapolate the last K samples */ p_in = &buf_in[len - K]; p_out = &out[len - K]; p_prev = p_out - 1; - for ( k = 0; k < K; k++ ) + FOR( k = 0; k < K; k++ ) { - *p_out++ = 0.05f * ( *p_in++ ) + 0.95f * ( *p_prev++ ); + tmp1 = *p_in++; + move16(); + tmp2 = *p_prev++; + move16(); + *p_out++ = add( mult_r( 1638 /* 0.05f in Q15 */, ( tmp1 ) ), mult_r( 31130 /* 0.95f in Q15 */, ( tmp2 ) ) ); + move16(); } return; } -#endif + + /*======================================================================================*/ /* FUNCTION : void GenShapedSHBExcitation_fx () */ /*--------------------------------------------------------------------------------------*/ @@ -2757,24 +2783,21 @@ void GenShapedSHBExcitation_ivas_fx( Word16 *Q_bwe_exc, Word16 *Q_bwe_exc_fb, const Word16 Q_shb, - Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ - Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ - const Word32 bitrate, - const Word16 prev_bfi -#if 1 // def ADD_IVAS_TBE_CODE - , /* i : previous frame was concealed */ - const Word16 element_mode, /* i : element mode */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - Word16 *nlExc16k, /* i/o: NL exc for IC-BWE */ - Word16 *mixExc16k, /* i/o: exc spreading for IC-BWE */ - const Word32 extl_brate, /* i : extension layer bitarte */ - const Word16 MSFlag, /* i : Multi Source flag */ - Word16 EnvSHBres_4k[], /* i/o: TD envelope of the SHB residual signal */ - Word32 *prev_pow_exc16kWhtnd, /* i/o: power of the LB excitation signal in the previous frame */ - Word16 *prev_mix_factor, /* i/o: mixing factor in the previous frame */ - Word16 *Env_error, /* o : error in SHB residual envelope modelling*/ - Word16 Env_error_part[] /* o : per-segment error in SHB residual envelope modelling */ -#endif + Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ + Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ + const Word32 bitrate, /* i : bitrate */ + const Word16 prev_bfi, /* i : previous frame was concealed */ + const Word16 element_mode, /* i : element mode */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + Word16 *nlExc16k, /* i/o: NL exc for IC-BWE */ + Word16 *mixExc16k, /* i/o: exc spreading for IC-BWE */ + const Word32 extl_brate, /* i : extension layer bitarte */ + const Word16 MSFlag, /* i : Multi Source flag */ + Word16 EnvSHBres_4k[], /* i/o: TD envelope of the SHB residual signal */ + Word32 *prev_pow_exc16kWhtnd, /* i/o: power of the LB excitation signal in the previous frame */ + Word16 *prev_mix_factor, /* i/o: mixing factor in the previous frame */ + Word16 *Env_error, /* o : error in SHB residual envelope modelling Q0 */ + Word16 Env_error_part[] /* o : per-segment error in SHB residual envelope modelling Q0 */ ) { Word16 i, j, k; @@ -2786,7 +2809,7 @@ void GenShapedSHBExcitation_ivas_fx( Word32 LepsP[LPC_WHTN_ORDER + 1]; Word16 exc32k[L_FRAME32k], exc16k[L_FRAME16k]; Word32 pow1, pow22; - Word16 scale, temp1, temp2; + Word16 scale, temp1, temp2, temp3; Word16 excTmp2[L_FRAME16k]; Word16 *White_exc16k; @@ -2815,6 +2838,7 @@ void GenShapedSHBExcitation_ivas_fx( Word16 White_exc16k_FB_temp[L_FRAME16k]; Word32 White_exc16k_32[L_FRAME16k]; + Word16 White_exc16k_tmp[L_FRAME16k]; Word16 Q_temp; Word16 prev_Q_bwe_exc_fb; Word16 chk1, chk2; @@ -2825,14 +2849,16 @@ void GenShapedSHBExcitation_ivas_fx( Word16 alpha, step, mem_csfilt_left, mem_csfilt_right, excNoisyEnvLeft[L_FRAME16k], excNoisyEnvRight[L_FRAME16k]; Word16 cbsize; Word16 mix_factor, old_fact, new_fact, fact, old_scale, new_scale, step_scale; - Word16 c0, c1, c2, c3, c4, c5, g1, g2, g, den; + Word32 c0, c1, c2, c3, c4, c5, den; + Word16 g1, g2, g, g1_e, g2_e, g_e, den_e, shift, tmp_e, tmp1_e; Word16 EnvWhiteExc16k[L_FRAME16k], EnvExc16kWhtnd[L_FRAME16k]; Word16 EnvWhiteExc16k_4k[L_FRAME4k] = { 0 }, EnvExc16kWhtnd_4k[L_FRAME4k] = { 0 }; Word16 flag_plosive; Word16 delta; - Word16 c0_part[NUM_SHB_SUBGAINS], c1_part[NUM_SHB_SUBGAINS], c2_part[NUM_SHB_SUBGAINS], c3_part[NUM_SHB_SUBGAINS], c4_part[NUM_SHB_SUBGAINS], c5_part[NUM_SHB_SUBGAINS]; + Word32 c0_part[NUM_SHB_SUBGAINS], c1_part[NUM_SHB_SUBGAINS], c2_part[NUM_SHB_SUBGAINS], c3_part[NUM_SHB_SUBGAINS], c4_part[NUM_SHB_SUBGAINS], c5_part[NUM_SHB_SUBGAINS]; + Word64 W_tmp; - mix_factor = 0; + mix_factor = 0; /* Q15 */ move16(); #endif set16_fx( zero_mem, 0, LPC_SHB_ORDER ); @@ -3180,84 +3206,185 @@ void GenShapedSHBExcitation_ivas_fx( { IF( EQ_16( *vf_ind, 20 ) ) /* encoder side */ { -#ifdef ADD_IVAS_TBE_CODE // BELOW PART WILL NEED TO BE CONVERTED FOR ENCODER!! - if ( extl_brate == SWB_TBE_1k10 || extl_brate == SWB_TBE_1k75 ) +#ifndef ADD_IVAS_TBE_CODE // BELOW PART WILL NEED TO BE CONVERTED FOR ENCODER!! + test(); + IF( EQ_32( extl_brate, SWB_TBE_1k10 ) || EQ_32( extl_brate, SWB_TBE_1k75 ) ) { + FOR( k = 0; k < L_FRAME16k; k++ ) + { + White_exc16k_tmp[k] = round_fx( L_shl( White_exc16k_32[k], *Q_bwe_exc ) ); + move16(); + } + /* calculate TD envelopes of exc16kWhtnd and White_exc16k */ - find_td_envelope( White_exc16k, L_FRAME16k, 20, NULL, EnvWhiteExc16k ); - find_td_envelope( exc16kWhtnd, L_FRAME16k, 20, NULL, EnvExc16kWhtnd ); + find_td_envelope_fx( White_exc16k_tmp, L_FRAME16k, 20, NULL, EnvWhiteExc16k ); /* Q_bwe_exc */ + find_td_envelope_fx( exc16kWhtnd, L_FRAME16k, 20, NULL, EnvExc16kWhtnd ); /* Q_bwe_exc */ - for ( k = 0; k < L_FRAME4k; k++ ) + FOR( k = 0; k < L_FRAME4k; k++ ) { - EnvWhiteExc16k_4k[k] = EnvWhiteExc16k[4 * k]; - EnvExc16kWhtnd_4k[k] = EnvExc16kWhtnd[4 * k]; + EnvWhiteExc16k_4k[k] = EnvWhiteExc16k[4 * k]; /* Q_bwe_exc */ + move16(); + EnvExc16kWhtnd_4k[k] = EnvExc16kWhtnd[4 * k]; /* Q_bwe_exc */ + move16(); } /* calculate the optimal mix factor */ - c0 = c1 = c2 = c3 = c4 = c5 = 0.0f; - for ( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + c0 = c1 = c2 = c3 = c4 = c5 = 0; /* Q0 */ + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + + temp1 = add( shl( *Q_bwe_exc, 1 ), 1 ); + temp2 = add( add( Q_shb, *Q_bwe_exc ), 1 ); + temp3 = add( shl( Q_shb, 1 ), 1 ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { - c0_part[i] = sum2_f( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c1_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c2_part[i] = sum2_f( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c3_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c4_part[i] = 2.0f * dotp( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c5_part[i] = sum2_f( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + // c0_part[i] = sum2_f( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c0_part[i] = L_shr( sum2_fx( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp1 ); /* Q0 */ + move32(); + // c1_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c1_part[i] = L_shr( L_negate( Dot_product( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ) ), sub( temp2, 1 ) ); /* Q0 */ + move32(); + // c2_part[i] = sum2_f( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c2_part[i] = L_shr( sum2_fx( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp1 ); /* Q0 */ + move32(); + // c3_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c3_part[i] = L_shr( L_negate( Dot_product( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ) ), sub( temp2, 1 ) ); /* Q0 */ + move32(); + // c4_part[i] = 2.0f * dotp( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c4_part[i] = L_shr( Dot_product( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), sub( temp1, 1 ) ); /* Q0 */ + move32(); + // c5_part[i] = sum2_f( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c5_part[i] = L_shr( sum2_fx( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp3 ); /* Q0 */ + move32(); + + c0 = L_add( c0, c0_part[i] ); + c1 = L_add( c1, c1_part[i] ); + c2 = L_add( c2, c2_part[i] ); + c3 = L_add( c3, c3_part[i] ); + c4 = L_add( c4, c4_part[i] ); + c5 = L_add( c5, c5_part[i] ); + } - c0 += c0_part[i]; - c1 += c1_part[i]; - c2 += c2_part[i]; - c3 += c3_part[i]; - c4 += c4_part[i]; - c5 += c5_part[i]; + // den = 4.0f * c0 * c2 - c4 * c4; + W_tmp = W_sub( W_shl( W_mult0_32_32( c0, c2 ), 2 ), W_mult0_32_32( c4, c4 ) ); + den_e = 63; + move16(); + shift = W_norm( W_tmp ); + den = W_extract_h( W_shl( W_tmp, shift ) ); + den_e = sub( den_e, shift ); + + IF( den == 0 ) + { + den = 1; + move32(); + den_e = 31; + move16(); } - den = 4.0f * c0 * c2 - c4 * c4; - g1 = ( c3 * c4 - 2 * c1 * c2 ) / den; - g2 = ( c1 * c4 - 2 * c0 * c3 ) / den; + // g1 = ( c3 * c4 - 2 * c1 * c2 ) / den; + W_tmp = W_sub( W_mult0_32_32( c3, c4 ), W_shl( W_mult0_32_32( c1, c2 ), 1 ) ); + g1_e = 63; + move16(); + shift = W_norm( W_tmp ); + L_tmp = W_extract_h( W_shl( W_tmp, shift ) ); + g1_e = sub( g1_e, shift ); - *Env_error = 0.0f; + g1 = BASOP_Util_Divide3232_Scale( L_tmp, den, &tmp_e ); + g1_e = sub( add( tmp_e, g1_e ), den_e ); + + // g2 = ( c1 * c4 - 2 * c0 * c3 ) / den; + W_tmp = W_sub( W_mult0_32_32( c1, c4 ), W_shl( W_mult0_32_32( c0, c3 ), 1 ) ); + g2_e = 63; + move16(); + shift = W_norm( W_tmp ); + L_tmp = W_extract_h( W_shl( W_tmp, shift ) ); + g2_e = sub( g2_e, shift ); + + g2 = BASOP_Util_Divide3232_Scale( L_tmp, den, &tmp_e ); + g2_e = sub( add( tmp_e, g2_e ), den_e ); + + // *Env_error = 0.0f; + *Env_error = 0; + move16(); flag_plosive = 0; - for ( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { - Env_error_part[i] = c5_part[i] + g1 * g1 * c0_part[i] + g1 * c1_part[i] + g2 * g2 * c2_part[i] + g2 * c3_part[i] + g1 * g2 * c4_part[i]; - *Env_error += Env_error_part[i]; + // Env_error_part[i] = c5_part[i] + g1 * g1 * c0_part[i] + g1 * c1_part[i] + g2 * g2 * c2_part[i] + g2 * c3_part[i] + g1 * g2 * c4_part[i]; + L_tmp = BASOP_Util_Add_Mant32Exp( c5_part[i], 31, Mpy_32_32( L_mult( g1, g1 ), c0_part[i] ), add( shl( g1_e, 1 ), 31 ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_16_1( c1_part[i], g1 ), add( 31, g1_e ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_32( L_mult( g2, g2 ), c2_part[i] ), add( shl( g2_e, 1 ), 31 ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_16_1( c3_part[i], g2 ), add( 31, g2_e ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_32( L_mult( g1, g2 ), c4_part[i] ), add( add( g1_e, g2_e ), 31 ), &tmp_e ); + + // Env_error_part[i] = L_shr( L_tmp, 31 - tmp_e ); // Check Exponent + Env_error_part[i] = extract_h( L_shr_sat( L_tmp, sub( Q15, tmp_e ) ) ); /* Q0 */ + move16(); - if ( Env_error_part[i] > THR_ENV_ERROR_PLOSIVE ) + // *Env_error += Env_error_part[i]; + *Env_error = add_sat( *Env_error, Env_error_part[i] ); /* Q0 */ + move16(); + + if ( GT_16( Env_error_part[i], THR_ENV_ERROR_PLOSIVE_FX ) ) // Check which Q { /* envelope error is too high -> likely a plosive */ flag_plosive = 1; + move16(); } } - if ( flag_plosive ) + IF( flag_plosive ) { /* plosive detected -> set the mixing factor to 0 */ *vf_ind = 0; - mix_factor = 0.0f; + move16(); + mix_factor = 0; + move16(); } - else + ELSE { /* normalize gain */ - g = g2 / ( g1 + g2 ); + // g = g2 / ( g1 + g2 ); + tmp1_e = BASOP_Util_Add_MantExp( g1, g1_e, g2, g2_e, &tmp ); + IF( tmp == 0 ) + { + tmp = 1; + move16(); + tmp1_e = 15; + move16(); + } + g = BASOP_Util_Divide1616_Scale( g2, tmp, &tmp_e ); + g_e = sub( add( tmp_e, g2_e ), tmp1_e ); /* quantization of the mixing factor */ cbsize = 1 << NUM_BITS_SHB_VF; - delta = 1.0f / ( cbsize - 1 ); - if ( g > 1.0f ) + move16(); + // delta = 1.0f / ( cbsize - 1 ); + delta = 2341; /* Q14 */ + move16(); + // if ( g > 1.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( g, add( 16, g_e ), ONE_IN_Q31, 0 ) > 0 ) { - g = 1.0f; + // g = 1.0f; + g = MAX16B; /* Q15 */ } - else if ( g < delta ) + // else if ( g < shl( delta, ( 15 - g_e ) - 14 ) ) + ELSE IF( BASOP_Util_Cmp_Mant32Exp( g, add( 16, g_e ), delta, 17 ) < 0 ) { /* prevent low gains to be quantized to 0 as this is reserved for plosives */ - g = delta; + // g = delta; + g = shl( delta, 1 ); /* Q15 */ } - *vf_ind = usquant( g, &mix_factor, 0.0f, 1.0f / ( cbsize - 1 ), cbsize ); + *vf_ind = usquant_fx( g, &mix_factor, 0, delta, cbsize ); + move16(); } } - else + ELSE #else UNUSED_PARAM( Env_error_part ); UNUSED_PARAM( Env_error ); @@ -3815,18 +3942,16 @@ void GenSHBSynth_fx( /* CALLED FROM : RX */ /*==============================================================================*/ - void ScaleShapedSHB_fx( - const Word16 length, /* i : SHB overlap length */ - Word16 *synSHB, /* i/o : synthesized shb signal Q_bwe_exc/Qx */ - Word16 *overlap, /* i/o : buffer for overlap-add Q_bwe_exc/Qx */ - const Word16 *subgain, /* i : subframe gain Q15*/ - const Word32 frame_gain, /* i : frame gain Q18 */ - const Word16 *win, /* i : window Q15*/ - const Word16 *subwin, /* i : subframes window Q15*/ + const Word16 length, /* i : SHB overlap length */ + Word16 *synSHB, /* i/o : synthesized shb signal Q(Q_bwe_exc)/Q(Qx) */ + Word16 *overlap, /* i/o : buffer for overlap-add Q(Q_bwe_exc)/Q(Qx) */ + const Word16 *subgain, /* i : subframe gain Q15 */ + const Word32 frame_gain, /* i : frame gain Q18 */ + const Word16 *win, /* i : window Q15 */ + const Word16 *subwin, /* i : subframes window Q15 */ Word16 *Q_bwe_exc, - Word16 *Qx /* o : newly computed Q factor for synSHB */ - , + Word16 *Qx, /* o : newly computed Q factor for synSHB */ Word16 n_mem3, Word16 prev_Q_bwe_syn2 ) { @@ -3845,11 +3970,10 @@ void ScaleShapedSHB_fx( set32_fx( mod_syn, 0, L_FRAME16k + L_SHB_LAHEAD ); /* apply gain for each subframe, and store noise output signal using overlap-add */ - IF( length == SHB_OVERLAP_LEN / 2 ) + IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { /* WB Gain shape and gain frame application with overlap */ skip = skip_bands_WB_TBE; - move16(); l_frame = L_FRAME16k / 4; move16(); l_shb_lahead = L_SHB_LAHEAD / 4; @@ -3892,18 +4016,18 @@ void ScaleShapedSHB_fx( l_shb_lahead = L_SHB_LAHEAD; move16(); skip = skip_bands_SWB_TBE; - move16(); num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; move16(); join_length = i_mult2( num_join, length ); j = 0; + move16(); FOR( k = 0; k < length; k++ ) { sum_gain = mult_r( subwin[k + 1], subgain[0] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) @@ -3912,7 +4036,7 @@ void ScaleShapedSHB_fx( { mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) @@ -3923,21 +4047,21 @@ void ScaleShapedSHB_fx( sum_gain = round_fx( L_mac0( L_tmp, subwin[length - k - 1], subgain[i * num_join] ) ); /*Q14 */ mod_syn[j] = L_shl( L_mult( sum_gain, synSHB[j] ), 1 ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } } FOR( k = 0; k < join_length - length; k++ ) { mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) { sum_gain = mult_r( subwin[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } } @@ -3954,7 +4078,9 @@ void ScaleShapedSHB_fx( = (Q_gFr_norm + 2) */ *Q_bwe_exc = add( *Q_bwe_exc, Q_gFr_norm ); /* compensate for the exp shift */ - *Q_bwe_exc = sub( *Q_bwe_exc, 13 ); /* Keep Q-fac at => (Q_bwe_exc + Q_gFr_norm - 13) */ + move16(); + *Q_bwe_exc = sub( *Q_bwe_exc, 13 ); /* Keep Q-fac at => (Q_bwe_exc + Q_gFr_norm - 13) */ + move16(); /* check for headroom of previous buff memories: overlap, Hilbert, and interp all-pass mem */ tmpQ15 = add( prev_Q_bwe_syn2, n_mem3 ); @@ -3977,15 +4103,15 @@ void ScaleShapedSHB_fx( move16(); } temp1 = abs_s( overlap[i] ); - temp1 = shl( temp1, ( *Q_bwe_exc - prev_Q_bwe_syn2 ) ); - move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ + temp1 = shl( temp1, sub( *Q_bwe_exc, prev_Q_bwe_syn2 ) ); overlap[i] = i_mult( temp1, temp2 ); + move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ } FOR( i = 0; i < l_shb_lahead; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - L_tmp2 = Mult_32_16( L_tmp, win[i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp2 = Mpy_32_16_1( L_tmp, win[i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ synSHB[i] = mac_r( L_tmp2, overlap[i], MAX_16 ); move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ synSHB[i + l_shb_lahead] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ @@ -3994,21 +4120,23 @@ void ScaleShapedSHB_fx( FOR( ; i < l_frame; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - synSHB[i] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + synSHB[i] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ move16(); } l_frame_tmp = add( l_frame, l_shb_lahead ); FOR( ; i < l_frame_tmp; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - L_tmp = Mult_32_16( L_tmp, win[l_frame + l_shb_lahead - 1 - i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ - overlap[i - l_frame] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp = Mpy_32_16_1( L_tmp, win[l_frame + l_shb_lahead - 1 - i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + overlap[i - l_frame] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + move16(); } return; } + /*-------------------------------------------------------------------* * ScaleShapedWB() * @@ -5242,9 +5370,9 @@ void wb_tbe_extras_reset_synth_fx( *-------------------------------------------------------------------*/ void elliptic_bpf_48k_generic_fx( - const Word16 input_fx[], /* i : input signal */ + const Word16 input_fx[], /* i : input signal Q_input_fx*/ Word16 *Q_input_fx, - Word16 output_fx[], /* o : output signal */ + Word16 output_fx[], /* o : output signal memory_fx_Q */ Word32 memory_fx2[][4], /* i/o: 4 arrays of 4 for memory */ Word16 memory_fx_Q[], const Word16 full_band_bpf_fx[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ diff --git a/lib_com/tcx_utils_fx.c b/lib_com/tcx_utils_fx.c index 19082fe248dfe07482fe38c342437d8e17495920..1d3ddc310bf3ecc764f550ed84ab3bf4adee2fd8 100644 --- a/lib_com/tcx_utils_fx.c +++ b/lib_com/tcx_utils_fx.c @@ -39,7 +39,7 @@ Word16 getInvFrameLen( /* returns 1/L_frame in Q21 format */ * * * ------------------------------------------------------------------ - */ -static void tcx_get_windows( +void tcx_get_windows( TCX_CONFIG_HANDLE hTcxCfg, /* i : TCX configuration */ const Word16 left_mode, /* i: overlap mode of left window half */ const Word16 right_mode, /* i: overlap mode of right window half */ diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index 6ec06b3aaba578b770cc3f48f14cb705504cddd0..e0fd2308244015abb52f232292b8a6bb86a17d66 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -578,7 +578,7 @@ Word16 ITF_Detect_fx( assert( n < (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) ); FOR( i = 0; i < n; i++ ) { - tmpbuf[i] = round_fx( L_shl( pSpectrum[iStartLine + i - IGF_START_MN], shift ) ); + tmpbuf[i] = round_fx_sat( L_shl_sat( pSpectrum[iStartLine + i - IGF_START_MN], shift ) ); move16(); } diff --git a/lib_com/tools.c b/lib_com/tools.c index bdaacdf982e633a33ad2df2895a329fa0011c93a..0222d6cc48fb0dcb8a476cda512b765fddb44f7a 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -250,6 +250,35 @@ float sum2_f( } #ifdef IVAS_FLOAT_FIXED +Word32 sum2_16_exp_fx( + const Word16 *vec, /* i : input vector Q(15 - exp) */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +) +{ + Word16 i, s; + Word32 L_tmp, var_a; + + L_tmp = 0; + move32(); + var_a = 0; + move32(); + FOR( i = 0; i < lvec; i++ ) + { + var_a = L_mult0( vec[i], vec[i] ); /* 2 * Q(15 - exp) */ + L_tmp = L_add( L_tmp, L_shr( var_a, gb ) ); /* 2 * Q(15 - exp) - gb */ + } + + s = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, s ); /* 2 * Q(15 - exp) - gb + s */ + + *exp = add( sub( add( shl( *exp, 1 ), gb ), s ), 1 ); + move16(); + + return L_tmp; +} + Word32 sum2_32_exp_fx( const Word32 *vec, /* i : input vector, Qx */ const Word16 lvec, /* i : length of input vector */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index d0b3dd0dda542f06c4a4f11ffb945bf1a6e0998c..92b4048d4477bfc7d0a1b703555ddefd25c9b9a2 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -418,6 +418,29 @@ Word32 sum2_fx( /* o : sum of all squared vector elements return L_tmp; } +Word32 sum_32_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 *e ) +{ + Word16 i, shift; + Word64 tmp = 0; + move64(); + Word32 ans; + + FOR( i = 0; i < lvec; i++ ) + { + tmp = W_add( tmp, vec[i] ); // e + } + shift = W_norm( tmp ); + tmp = W_shl( tmp, shift ); // shift + (31 - e) + ans = W_extract_h( tmp ); // shift + (31 - e) - 32 + *e = add( sub( *e, shift ), 32 ); + move16(); + + return ans; +} + Word32 sum2_fx_mod( /* o : sum of all squared vector elements Q(2x+1 -5)*/ const Word16 *vec, /* i : input vector Qx*/ const Word16 lvec /* i : length of input vector */ @@ -958,6 +981,24 @@ Word16 mean_fx( /* o : mean of vector return tmp; } + +Word16 mean_no_sat_fx( /* o : mean of vector Qx */ + const Word16 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp = 0; + move32(); + FOR( i = 0; i < lvec_fx; ++i ) + { + L_tmp = L_add( L_tmp, vec_fx[i] ); + } + L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx */ + + return extract_l( L_tmp ); +} + /*-------------------------------------------------------------------* * Vr_add * @@ -1197,8 +1238,10 @@ Word16 minimum_32_fx( /* o : index of the minimum value i } tmp = L_min( tmp, vec_fx[j] ); } - - *min_fx = tmp; + if ( min_fx != NULL ) + { + *min_fx = tmp; + } move32(); return ind; @@ -1232,7 +1275,10 @@ Word16 maximum_32_fx( /* o : index of the maximum value in t } tmp = L_max( tmp, vec[j] ); } - *max_val = tmp; + if ( max_val != NULL ) + { + *max_val = tmp; + } move32(); return ind; @@ -1633,13 +1679,14 @@ void Vr_subt( * Searches a given codebook to find the nearest neighbour in Euclidean space. * Index of the winning codevector and the winning vector itself are returned. *-------------------------------------------------------------------*/ -Word16 vquant_fx( /* o: index of the winning codevector */ - Word16 x[], /* i: vector to quantize Q13 */ - const Word16 x_mean[], /* i: vector mean to subtract (0 if none)Q13*/ - Word16 xq[], /* o: quantized vector Q13 */ - const Word16 cb[], /* i: codebook Q13 */ - const Word16 dim, /* i: dimension of codebook vectors */ - const Word16 cbsize /* i: codebook size */ + +Word16 vquant_fx( /* o: index of the winning codevector */ + Word16 x[], /* i: vector to quantize Q13 */ + const Word16 x_mean[], /* i: vector mean to subtract (0 if none) Q13 */ + Word16 xq[], /* o: quantized vector Q13 */ + const Word16 cb[], /* i: codebook Q13 */ + const Word16 dim, /* i: dimension of codebook vectors */ + const Word16 cbsize /* i: codebook size */ ) { Word16 tmp; @@ -1649,7 +1696,7 @@ Word16 vquant_fx( /* o: index of the winning codevector idx = 0; move16(); L_mindist = MAX_32; - move16(); + move32(); IF( x_mean != 0 ) { FOR( d = 0; d < dim; d++ ) @@ -1679,7 +1726,7 @@ Word16 vquant_fx( /* o: index of the winning codevector } L_mindist = L_min( L_mindist, L_dist ); } - if ( xq == 0 ) + IF( xq == 0 ) { return idx; } @@ -2351,9 +2398,9 @@ Word32 root_a_fx( Word32 root_a_over_b_fx( - Word32 a, + Word32 a, /* Q(Q_a) */ Word16 Q_a, - Word32 b, + Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ) { @@ -2654,6 +2701,37 @@ Word16 squant_fx( /* o: index of the winning codeword */ return idx; } +/*! r: index of the winning codeword */ +Word16 squant_int_fx( + UWord8 x, /* i : scalar value to quantize */ + UWord8 *xq, /* o : quantized value */ + const UWord8 *cb, /* i : codebook */ + const Word16 cbsize /* i : codebook size */ +) +{ + Word16 i, idx; + Word32 mindist, d; + + idx = 0; + move16(); + mindist = 10000000; // Q0 + move32(); + FOR( i = 0; i < cbsize; i++ ) + { + d = L_mult0( sub( x, cb[i] ), sub( x, cb[i] ) ); + IF( LT_32( d, mindist ) ) + { + mindist = d; + move32(); + idx = i; + move16(); + } + } + *xq = cb[idx]; + move16(); + + return idx; +} /*===================================================================*/ /* FUNCTION : pz_filter_dp_fx () */ @@ -2738,6 +2816,60 @@ void pz_filter_dp_fx( } } +/*-------------------------------------------------------------------* + * Copy_Scale_sig + * + * Up/down scale a 16 bits vector x and move it into y + *-------------------------------------------------------------------*/ +void Copy_Scale_sig32( + const Word32 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word32 L_tmp; + Word16 tmp = exp0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = x[i]; + move32(); + } + return; + } + IF( exp0 < 0 ) + { + FOR( i = 0; i < lg; i++ ) + { +#ifdef BASOP_NOGLOB + y[i] = L_shl_o( x[i], tmp, &Overflow ); +#else + y[i] = L_shl( x[i], tmp ); +#endif + move16(); + } + return; + } +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); +#else + tmp = shl( 1, exp0 ); +#endif + FOR( i = 0; i < lg; i++ ) + { + y[i] = W_extract_l( W_mult_32_32( L_tmp, x[i] ) ); + move32(); /* saturation can occur here */ + } +} + + /*-------------------------------------------------------------------* * Copy_Scale_sig32_16 * @@ -3418,7 +3550,7 @@ Word16 erb_diff_search_fx( Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif Lacc = L_deposit_l( 0 ); FOR( i = 0; i < cb_dim; i++ ) { - IF( add( cb_fx[j * cb_dim + i], prev_erb[i + offset] ) < 0 ) + IF( add_sat( cb_fx[j * cb_dim + i], prev_erb[i + offset] ) < 0 ) { Ltemp1 = L_mult( curr_erb[i + offset], curr_erb[i + offset] ); /* Q27 */ dh = extract_h( Ltemp1 ); @@ -4347,6 +4479,32 @@ Word32 dotp_fixed_guarded( return suma; } #endif + + +Word32 dotp_fixed_ivas_fx( + const Word32 x[], /* i : vector x[] */ + Word16 x_e, + const Word32 y[], /* i : vector y[] */ + Word16 y_e, + const Word16 n, /* i : vector length */ + Word16 *out_e ) +{ + Word16 i, exp; + Word32 suma = 0; + + exp = 31; + move16(); + + FOR( i = 0; i < n; i++ ) + { + suma = BASOP_Util_Add_Mant32Exp( suma, exp, Mpy_32_32( x[i], y[i] ), x_e + y_e, &exp ); + } + + *out_e = exp; + move16(); + return suma; +} + /*-------------------------------------------------------------------* * v_mult() * diff --git a/lib_com/wtda_fx.c b/lib_com/wtda_fx.c index b20771f8cec8d7bb6f612290256471ea1d07161e..e94789a6a8cbb08eba68d35fd04d2758a86aa042 100644 --- a/lib_com/wtda_fx.c +++ b/lib_com/wtda_fx.c @@ -411,100 +411,360 @@ void wtda_fx( } return; } -#ifdef IVAS_CODE - -void wtda_ext( - const float *new_audio, /* i : input audio */ - float *wtda_audio, /* o : windowed audio */ - const int16_t left_mode, /* i : window overlap of previous frame (0: full, 2: none, or 3: half) */ - const int16_t right_mode, /* i : window overlap of current frame (0: full, 2: none, or 3: half) */ - const int16_t L, /* i : length */ - const uint16_t kernel_type /* i : transform kernel type (0 - 3) */ + + +#ifdef IVAS_FLOAT_FIXED +void wtda_ivas_fx( + Word16 *new_audio, /* i : input audio Q0 */ + Word16 *Q, /* i/o : Q of input/Output Audio */ + Word16 *wtda_audio, /* o : windowed audio Qout */ + Word16 *old_wtda, /* i/o: windowed audio from previous frame Qout */ + Word16 *Qold_wtda, + const Word16 left_mode, /* i : window overlap of previous frame (0: full, 2: none, or 3: half) */ + const Word16 right_mode, /* i : window overlap of current frame (0: full, 2: none, or 3: half) */ + const Word16 L /* i : length */ ) { - const float sign_left = ( kernel_type >= 2 ? -1.f : 1.f ); - const float sign_right = ( kernel_type & 1 ? 1.f : -1.f ); - int16_t i, decimate, decay; - int16_t n, windecay48, windecay16; - const float *allsig_l, *allsig_r; - float win_right[R2_48]; - float win_int_left[R1_16]; - float win_left[R1_48]; - float win_int_right[R2_16]; + Word16 i, decimate, decay; + Word16 n, windecay48, windecay16; + const Word16 *allsig_l, *allsig_r; + Word16 win_right[R2_48]; + Word16 win_int_left[R1_16]; + Word16 win_left[R1_48]; + Word16 win_int_right[R2_16]; tcx_get_windows_mode1( left_mode, right_mode, win_left, win_right, win_int_left, win_int_right, L ); - decimate = 1; /* L_FRAME 48k */ + decimate = 1; /* L_FRAME48k */ + move16(); decay = 0; - windecay48 = (int16_t) ( 2 * ( (float) L_FRAME48k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_48; + move16(); + windecay48 = ( 2 * ( (Word64) L_FRAME48k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_48; + move16(); - if ( L == L_FRAME32k || L == L_FRAME16k ) + test(); + IF( EQ_16( L, L_FRAME32k ) || EQ_16( L, L_FRAME16k ) ) { decimate = 3; + move16(); decay = 1; + move16(); } - else if ( L == L_FRAME8k ) + ELSE IF( EQ_16( L, L_FRAME8k ) ) { decimate = 6; + move16(); decay = 2; + move16(); } - n = (int16_t) ( (float) L * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + n = extract_l( Mpy_32_32( L, 603979776 /* N_ZERO_MDCT_NS / FRAME_SIZE_NS in Q31 */ ) ); + + windecay16 = ( 2 * ( L_FRAME16k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_16; + move16(); - windecay16 = (int16_t) ( 2 * ( (float) L_FRAME16k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_16; + /* algorithmic delay reduction */ + i = 0; + move16(); - allsig_r = new_audio + n; - allsig_l = new_audio + n - L; + IF( old_wtda == NULL ) + { + allsig_r = new_audio + n; + allsig_l = new_audio + n - L; + } + ELSE + { + /* Rescale signals if Q are not identical */ + IF( GT_16( *Qold_wtda, *Q ) ) + { + Copy_Scale_sig( old_wtda, old_wtda, L, sub( *Q, *Qold_wtda ) ); + *Qold_wtda = *Q; + move16(); + } + ELSE IF( LT_16( *Qold_wtda, *Q ) ) + { + Copy_Scale_sig( new_audio, new_audio, L, sub( *Qold_wtda, *Q ) ); + *Q = *Qold_wtda; + move16(); + } - if ( L == L_FRAME32k ) + allsig_r = new_audio + n; + allsig_l = old_wtda + n; + } + + IF( EQ_16( L, L_FRAME32k ) ) { - for ( i = 0; i < L / 2 - n; i += 2 ) + FOR( i = 0; i < L / 2 - n; i += 2 ) { - wtda_audio[i] = -allsig_r[L / 2 - i - 1] * win_int_right[3 * L_FRAME16k / 2 - i / 2 - 1 - windecay16] + sign_right * allsig_r[L / 2 + i] * win_int_right[3 * L_FRAME16k / 2 + i / 2 - windecay16]; - wtda_audio[i + 1] = -allsig_r[L / 2 - ( i + 1 ) - 1] * win_right[( 3 * L_FRAME16k / 2 - i / 2 - 1 ) * decimate + decay - windecay48] + sign_right * allsig_r[L / 2 + i + 1] * win_right[( 3 * L_FRAME16k / 2 + 1 + i / 2 ) * decimate - decay - 1 - windecay48]; + wtda_audio[i] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_int_right[3 * L_FRAME16k / 2 - i / 2 - 1 - windecay16] ), + allsig_r[L / 2 + i], win_int_right[3 * L_FRAME16k / 2 + i / 2 - windecay16] ) ); + move16(); + wtda_audio[i + 1] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - ( i + 1 ) - 1] ), win_right[( 3 * L_FRAME16k / 2 - i / 2 - 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i + 1], win_right[( 3 * L_FRAME16k / 2 + 1 + i / 2 ) * decimate - decay - 1 - windecay48] ) ); + move16(); } - for ( i = L / 2 - n; i < L / 2; i += 2 ) + FOR( i = L / 2 - n; i < L / 2; i += 2 ) { - wtda_audio[i] = -allsig_r[L / 2 - i - 1]; - wtda_audio[i + 1] = -allsig_r[L / 2 - ( i + 1 ) - 1]; + wtda_audio[i] = shr( negate( allsig_r[L / 2 - i - 1] ), 1 ); + move16(); + wtda_audio[i + 1] = shr( negate( allsig_r[L / 2 - ( i + 1 ) - 1] ), 1 ); + move16(); } - for ( i = 0; i < n; i += 2 ) + + FOR( i = 0; i < n; i += 2 ) { - wtda_audio[i + L / 2] = sign_left * allsig_l[i] * win_left[( i / 2 ) * decimate + decay] - new_audio[n - i - 1]; - wtda_audio[i + L / 2 + 1] = sign_left * allsig_l[i + 1] * win_int_left[i / 2] - new_audio[n - ( i + 1 ) - 1]; + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[( i / 2 ) * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( allsig_l[i + 1], win_int_left[i / 2] ), + new_audio[n - ( i + 1 ) - 1], MAX16B ) ); + move16(); } - for ( i = n; i < L / 2; i += 2 ) + FOR( i = n; i < L / 2; i += 2 ) { - wtda_audio[i + L / 2] = sign_left * allsig_l[i] * win_left[( i / 2 ) * decimate + decay] - allsig_l[L - i - 1] * win_left[( L / 2 - i / 2 ) * decimate - 1 - decay]; - wtda_audio[i + L / 2 + 1] = sign_left * allsig_l[i + 1] * win_int_left[i / 2] - allsig_l[L - ( i + 1 ) - 1] * win_int_left[L / 2 - i / 2 - 1]; + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[( i / 2 ) * decimate + decay] ), + allsig_l[L - i - 1], win_left[( L / 2 - i / 2 ) * decimate - 1 - decay] ) ); + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( allsig_l[i + 1], win_int_left[i / 2] ), + allsig_l[L - ( i + 1 ) - 1], win_int_left[L / 2 - i / 2 - 1] ) ); + move16(); } } - else + ELSE { - for ( i = 0; i < L / 2 - n; i++ ) + FOR( i = 0; i < L / 2 - n; i++ ) { - wtda_audio[i] = -allsig_r[L / 2 - i - 1] * win_right[3 * L / 2 * decimate - ( i + 1 ) * decimate + decay - windecay48] + sign_right * allsig_r[L / 2 + i] * win_right[3 * L / 2 * decimate - 1 + ( i + 1 ) * decimate - decay - windecay48]; + wtda_audio[i] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_right[3 * L / 2 * decimate - ( i + 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i], win_right[3 * L / 2 * decimate - 1 + ( i + 1 ) * decimate - decay - windecay48] ) ); + move16(); } - for ( i = L / 2 - n; i < L / 2; i++ ) + FOR( i = L / 2 - n; i < L / 2; i++ ) { - wtda_audio[i] = -allsig_r[L / 2 - i - 1]; + wtda_audio[i] = shr( negate( allsig_r[L / 2 - i - 1] ), 1 ); + move16(); } - for ( i = 0; i < n; i++ ) + FOR( i = 0; i < n; i++ ) { - wtda_audio[i + L / 2] = sign_left * allsig_l[i] * win_left[i * decimate + decay] - new_audio[n - i - 1]; + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[i * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); + move16(); } - for ( i = n; i < L / 2; i++ ) + FOR( i = n; i < L / 2; i++ ) { - wtda_audio[i + L / 2] = sign_left * allsig_l[i] * win_left[i * decimate + decay] - allsig_l[L - i - 1] * win_left[L * decimate - i * decimate - 1 - decay]; + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[i * decimate + decay] ), + allsig_l[L - i - 1], win_left[L * decimate - i * decimate - 1 - decay] ) ); + move16(); } } + IF( old_wtda != NULL ) + { + Copy( new_audio, old_wtda, L ); + } + return; } +#endif + + +#ifdef IVAS_FLOAT_FIXED +void wtda_ext_fx( + const Word16 *new_audio, /* i : input audio (Q_in) */ + Word16 *wtda_audio, /* o : windowed audio (Q_in) */ + const Word16 left_mode, /* i : window overlap of previous frame (0: full, 2: none, or 3: half) */ + const Word16 right_mode, /* i : window overlap of current frame (0: full, 2: none, or 3: half) */ + const Word16 L, /* i : length */ + const UWord16 kernel_type /* i : transform kernel type (0 - 3) */ +) +{ + Word16 i, decimate, decay; + Word16 n, windecay48, windecay16; + const Word16 *allsig_l, *allsig_r; + Word16 win_right[R2_48]; + Word16 win_int_left[R1_16]; + Word16 win_left[R1_48]; + Word16 win_int_right[R2_16]; + + tcx_get_windows_mode1( left_mode, right_mode, win_left, win_right, win_int_left, win_int_right, L ); + + decimate = 1; /* L_FRAME48k */ + move16(); + decay = 0; + move16(); + windecay48 = ( 2 * ( (Word64) L_FRAME48k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_48; + move16(); + + test(); + IF( EQ_16( L, L_FRAME32k ) || EQ_16( L, L_FRAME16k ) ) + { + decimate = 3; + move16(); + decay = 1; + move16(); + } + ELSE IF( EQ_16( L, L_FRAME8k ) ) + { + decimate = 6; + move16(); + decay = 2; + move16(); + } + + n = extract_l( Mpy_32_32( L, 603979776 /* N_ZERO_MDCT_NS / FRAME_SIZE_NS in Q31 */ ) ); + move16(); + + windecay16 = ( 2 * ( L_FRAME16k * N_ZERO_MDCT_NS / FRAME_SIZE_NS ) ) + R1_16; + move16(); + + allsig_r = new_audio + n; + allsig_l = new_audio + n - L; + + IF( EQ_16( L, L_FRAME32k ) ) + { + IF( UL_and( kernel_type, 1 ) ) + { + FOR( i = 0; i < L / 2 - n; i += 2 ) + { + wtda_audio[i] = round_fx( L_mac0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_int_right[3 * L_FRAME16k / 2 - i / 2 - 1 - windecay16] ), + allsig_r[L / 2 + i], win_int_right[3 * L_FRAME16k / 2 + i / 2 - windecay16] ) ); // q_in + move16(); + wtda_audio[i + 1] = round_fx( L_mac0( L_mult0( negate( allsig_r[L / 2 - ( i + 1 ) - 1] ), win_right[( 3 * L_FRAME16k / 2 - i / 2 - 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i + 1], win_right[( 3 * L_FRAME16k / 2 + 1 + i / 2 ) * decimate - decay - 1 - windecay48] ) ); // q_in + move16(); + } + } + ELSE + { + FOR( i = 0; i < L / 2 - n; i += 2 ) + { + wtda_audio[i] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_int_right[3 * L_FRAME16k / 2 - i / 2 - 1 - windecay16] ), + allsig_r[L / 2 + i], win_int_right[3 * L_FRAME16k / 2 + i / 2 - windecay16] ) ); // q_in + move16(); + wtda_audio[i + 1] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - ( i + 1 ) - 1] ), win_right[( 3 * L_FRAME16k / 2 - i / 2 - 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i + 1], win_right[( 3 * L_FRAME16k / 2 + 1 + i / 2 ) * decimate - decay - 1 - windecay48] ) ); // q_in + move16(); + } + } + + FOR( i = L / 2 - n; i < L / 2; i += 2 ) + { + wtda_audio[i] = shr( negate( allsig_r[L / 2 - i - 1] ), 1 ); // q_in + move16(); + wtda_audio[i + 1] = shr( negate( allsig_r[L / 2 - ( i + 1 ) - 1] ), 1 ); // q_in + move16(); + } + + IF( GE_32( kernel_type, 2 ) ) + { + FOR( i = 0; i < n; i += 2 ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( negate( allsig_l[i] ), win_left[( i / 2 ) * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); // q_in + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( negate( allsig_l[i + 1] ), win_int_left[i / 2] ), + new_audio[n - ( i + 1 ) - 1], MAX16B ) ); // q_in + move16(); + } + + FOR( i = n; i < L / 2; i += 2 ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( negate( allsig_l[i] ), win_left[( i / 2 ) * decimate + decay] ), + allsig_l[L - i - 1], win_left[( L / 2 - i / 2 ) * decimate - 1 - decay] ) ); // q_in + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( negate( allsig_l[i + 1] ), win_int_left[i / 2] ), + allsig_l[L - ( i + 1 ) - 1], win_int_left[L / 2 - i / 2 - 1] ) ); // q_in + move16(); + } + } + ELSE + { + FOR( i = 0; i < n; i += 2 ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[( i / 2 ) * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); // q_in + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( allsig_l[i + 1], win_int_left[i / 2] ), + new_audio[n - ( i + 1 ) - 1], MAX16B ) ); // q_in + move16(); + } + + FOR( i = n; i < L / 2; i += 2 ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[( i / 2 ) * decimate + decay] ), + allsig_l[L - i - 1], win_left[( L / 2 - i / 2 ) * decimate - 1 - decay] ) ); // q_in + move16(); + wtda_audio[i + L / 2 + 1] = round_fx( L_msu0( L_mult0( allsig_l[i + 1], win_int_left[i / 2] ), + allsig_l[L - ( i + 1 ) - 1], win_int_left[L / 2 - i / 2 - 1] ) ); // q_in + move16(); + } + } + } + ELSE + { + IF( UL_and( kernel_type, 1 ) ) + { + FOR( i = 0; i < L / 2 - n; i++ ) + { + wtda_audio[i] = round_fx( L_mac0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_right[3 * L / 2 * decimate - ( i + 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i], win_right[3 * L / 2 * decimate - 1 + ( i + 1 ) * decimate - decay - windecay48] ) ); // q_in + move16(); + } + } + ELSE + { + FOR( i = 0; i < L / 2 - n; i++ ) + { + wtda_audio[i] = round_fx( L_msu0( L_mult0( negate( allsig_r[L / 2 - i - 1] ), win_right[3 * L / 2 * decimate - ( i + 1 ) * decimate + decay - windecay48] ), + allsig_r[L / 2 + i], win_right[3 * L / 2 * decimate - 1 + ( i + 1 ) * decimate - decay - windecay48] ) ); // q_in + move16(); + } + } + + FOR( i = L / 2 - n; i < L / 2; i++ ) + { + wtda_audio[i] = shr( negate( allsig_r[L / 2 - i - 1] ), 1 ); // q_in + move16(); + } + IF( GE_32( kernel_type, 2 ) ) + { + FOR( i = 0; i < n; i++ ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( negate( allsig_l[i] ), win_left[i * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); // q_in + move16(); + } + + FOR( i = n; i < L / 2; i++ ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( negate( allsig_l[i] ), win_left[i * decimate + decay] ), + allsig_l[L - i - 1], win_left[L * decimate - i * decimate - 1 - decay] ) ); // q_in + move16(); + } + } + ELSE + { + FOR( i = 0; i < n; i++ ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[i * decimate + decay] ), + new_audio[n - i - 1], MAX16B ) ); // q_in + move16(); + } + + FOR( i = n; i < L / 2; i++ ) + { + wtda_audio[i + L / 2] = round_fx( L_msu0( L_mult0( allsig_l[i], win_left[i * decimate + decay] ), + allsig_l[L - i - 1], win_left[L * decimate - i * decimate - 1 - decay] ) ); // q_in + move16(); + } + } + } + + return; +} #endif diff --git a/lib_dec/TonalComponentDetection_fx.c b/lib_dec/TonalComponentDetection_fx.c index 2c182f6c8ebba6a4e463b0851cac2a6ccd487e9f..1c84c1d75a506f6d1811e8b2dbfbd921818484f0 100644 --- a/lib_dec/TonalComponentDetection_fx.c +++ b/lib_dec/TonalComponentDetection_fx.c @@ -565,7 +565,7 @@ static void GetF0( /**pF0 = nSamplesCore/tmpPitchLag;*/ BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/ move16(); - *pF0 = shr( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/ + *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/ move16(); *pOrigF0 = *pF0; /*Q10*/ move16(); diff --git a/lib_dec/acelp_core_dec_ivas_fx.c b/lib_dec/acelp_core_dec_ivas_fx.c index 1db6d1dd19372195e0254ac875f204581d6ce954..ef8670388ba9cb29199ca589b244e93c60934b6a 100644 --- a/lib_dec/acelp_core_dec_ivas_fx.c +++ b/lib_dec/acelp_core_dec_ivas_fx.c @@ -1887,7 +1887,11 @@ ivas_error acelp_core_dec_ivas_fx( scale_sig32( realBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_real ); scale_sig32( imagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_imag ); } - scale_sig32( st->cldfbSynHB->cldfb_state_fx, st->cldfbSynHB->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); // (Q_real-1) +#ifdef FIX_882_LOW_LEVEL_DISCONTINUITIES + scale_sig32_r( st->cldfbSynHB->cldfb_state_fx, st->cldfbSynHB->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); // (Q_real-1) +#else + scale_sig32( st->cldfbSynHB->cldfb_state_fx, st->cldfbSynHB->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); // (Q_real-1) +#endif st->cldfbSynHB->Q_cldfb_state = sub( Q_real, 1 ); move16(); Scale_sig32( save_hb_synth_fx, L_FRAME48k, sub( Q_real, 1 ) ); @@ -1966,7 +1970,11 @@ ivas_error acelp_core_dec_ivas_fx( scale_sig32( realBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_real ); scale_sig32( imagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_real ); } - scale_sig32( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); //(Q_real - 1) +#ifdef FIX_882_LOW_LEVEL_DISCONTINUITIES + scale_sig32_r( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); //(Q_real - 1) +#else + scale_sig32( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); //(Q_real - 1) +#endif st->cldfbSyn->Q_cldfb_state = sub( Q_real, 1 ); move16(); #ifndef MSAN_FIX @@ -2069,7 +2077,11 @@ ivas_error acelp_core_dec_ivas_fx( scale_sig32( realBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_real ); scale_sig32( imagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, Q_real ); } +#ifdef FIX_882_LOW_LEVEL_DISCONTINUITIES + scale_sig32_r( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); //(Q_real - 1) +#else scale_sig32( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->p_filter_length, sub( sub( Q_real, 1 ), Q10 ) ); //(Q_real - 1) +#endif #ifndef MSAN_FIX Scale_sig32( synth_fx, L_FRAME48k, Q_real - 1 ); #endif diff --git a/lib_dec/amr_wb_dec.c b/lib_dec/amr_wb_dec.c index 09242c2a3cbdc2e2ffbc3494a7ffc80d4d6a2cf6..7a5baa92c1d314a1deaf9e8ae824c8571c38ad34 100644 --- a/lib_dec/amr_wb_dec.c +++ b/lib_dec/amr_wb_dec.c @@ -101,6 +101,8 @@ ivas_error amr_wb_dec( TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec; ivas_error error; + push_wmops( "amr_wb_dec" ); + error = IVAS_ERR_OK; /*------------------------------------------------------------------* @@ -810,6 +812,7 @@ ivas_error amr_wb_dec( /* final output of synthesis signal */ mvr2r( synth_out, output, output_frame ); + pop_wmops(); return error; } diff --git a/lib_dec/amr_wb_dec_fx.c b/lib_dec/amr_wb_dec_fx.c index f2acdde1aa2fa8058a2e4ca5779134cbe78a44b6..ef5b4299e888f86b5ad07a1f8c20a62168346af8 100644 --- a/lib_dec/amr_wb_dec_fx.c +++ b/lib_dec/amr_wb_dec_fx.c @@ -88,10 +88,13 @@ ivas_error amr_wb_dec_fx( hTcxLtpDec = st_fx->hTcxLtpDec; hTcxDec = st_fx->hTcxDec; + push_wmops( "amr_wb_dec_fx" ); + error = IVAS_ERR_OK; st_fx->idchan = 0; move16(); move16(); + /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ @@ -1111,6 +1114,7 @@ ivas_error amr_wb_dec_fx( /* final output of synthesis signal */ syn_output_fx( st_fx->codec_mode, synth_out_fx, output_frame, output_sp, st_fx->Q_syn2 ); + pop_wmops(); return error; } diff --git a/lib_dec/bass_psfilter.c b/lib_dec/bass_psfilter.c index 3b161b7822840ce7c124c3ddb724414c3108f42e..47ca645bc800f7b3e21c4bc64d4b06c7f365dd7c 100644 --- a/lib_dec/bass_psfilter.c +++ b/lib_dec/bass_psfilter.c @@ -684,8 +684,8 @@ int16_t res_bpf_adapt( Word16 res_bpf_adapt_ivas_fx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo decoder handle */ const Word32 *bpf_error_signal_8k, /* i : BPF modification signal */ - Word32 res_buf[STEREO_DFT_N_8k] /* i : residual buffer Q12 */ -) + Word32 res_buf[STEREO_DFT_N_8k], /* i : residual buffer Q12 */ + Word16 q_res ) { Word32 error_nrg; Word32 tmp; @@ -696,7 +696,6 @@ Word16 res_bpf_adapt_ivas_fx( Word16 i_start; Word16 i_end; Word16 bw_inv; - Word16 shift; Word64 W_tmp; IF( EQ_16( hStereoDft->res_cod_band_max, 6 ) ) @@ -726,10 +725,7 @@ Word16 res_bpf_adapt_ivas_fx( W_tmp = W_add_nosat( W_tmp, W_mult0_32_32( res_buf[i], res_buf[i] ) ); } - shift = W_norm( W_tmp ); - W_tmp = W_shl( W_tmp, shift ); - res_hb_nrg = W_extract_h( W_tmp ); - res_hb_nrg = L_shr( res_hb_nrg, sub( add( Q24, shift ), 32 ) ); // Q0 + res_hb_nrg = (Word32) W_shr( W_tmp, shl( q_res, 1 ) ); // Q0 res_hb_nrg = Mpy_32_16_1( res_hb_nrg, bw_inv ); res_hb_nrg = L_add( Mpy_32_16_1( res_hb_nrg, STEREO_DFT_BPF_ADAPT_ALPHA_FX ), Mpy_32_16_1( hStereoDft->res_hb_nrg_mem_fx, sub( MAX_16, STEREO_DFT_BPF_ADAPT_ALPHA_FX ) ) ); hStereoDft->res_hb_nrg_mem_fx = res_hb_nrg; diff --git a/lib_dec/evs_dec_fx.c b/lib_dec/evs_dec_fx.c index ba94c988a1b4fef895855f96612d021830f7e542..eb44da8c98e245a8b2925dfd1ef72c446865bfac 100644 --- a/lib_dec/evs_dec_fx.c +++ b/lib_dec/evs_dec_fx.c @@ -67,6 +67,9 @@ ivas_error evs_dec_fx( TCX_LTP_DEC_HANDLE hTcxLtpDec; TCX_DEC_HANDLE hTcxDec; ivas_error error; + + push_wmops( "evs_dec_fx" ); + #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; move16(); @@ -1502,6 +1505,9 @@ ivas_error evs_dec_fx( } updt_dec_common_fx( st_fx, hq_core_type, concealWholeFrameTmp, output_sp, Qpostd ); } + + pop_wmops(); + return IVAS_ERR_OK; } #endif diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 4055bde4c8cecf7530f0c1d69819ad44ad65135f..4575cf543928342a86540aee792b2d0767bed53b 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1339,7 +1339,7 @@ typedef struct ivas_masa_decoder_data_struct #ifndef IVAS_FLOAT_FIXED float dir_decode_quality; #else - Word16 dir_decode_quality_fx; /* Q15 */ + Word16 dir_decode_quality_fx; /* Q15 */ #endif } MASA_DECODER_DATA; @@ -1361,8 +1361,8 @@ typedef struct ivas_masa_ism_data_structure float energy_ratio_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; #else - Word32 energy_ratio_ism_fx[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; /* Q30 */ - Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /* Q30 */ + Word32 energy_ratio_ism_fx[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; /* Q30 */ + Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /* Q30 */ #endif int16_t azimuth_ism_edited[MAX_NUM_OBJECTS]; @@ -1377,14 +1377,14 @@ typedef struct ivas_masa_ism_data_structure float q_azimuth_old[MAX_NUM_OBJECTS]; float q_elevation_old[MAX_NUM_OBJECTS]; #else - Word32 q_azimuth_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ - Word32 q_elevation_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ + Word32 q_azimuth_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ + Word32 q_elevation_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ #endif #ifndef IVAS_FLOAT_FIXED float ismPreprocMatrix[2][2][CLDFB_NO_CHANNELS_MAX]; #else - Word16 ismPreprocMatrix_fx[2][2][CLDFB_NO_CHANNELS_MAX]; /* Q15 */ + Word16 ismPreprocMatrix_fx[2][2][CLDFB_NO_CHANNELS_MAX]; /* Q15 */ #endif uint8_t objectsMoved; #ifndef IVAS_FLOAT_FIXED @@ -1393,10 +1393,10 @@ typedef struct ivas_masa_ism_data_structure float preprocEneTarget[CLDFB_NO_CHANNELS_MAX]; float preprocEneRealized[CLDFB_NO_CHANNELS_MAX]; #else - Word32 eneMoveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; - Word32 enePreserveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; - Word32 preprocEneTarget_fx[CLDFB_NO_CHANNELS_MAX]; - Word32 preprocEneRealized_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 eneMoveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; /*Q-22*/ + Word32 enePreserveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; /*Q-22*/ + Word32 preprocEneTarget_fx[CLDFB_NO_CHANNELS_MAX]; /*Q-19*/ + Word32 preprocEneRealized_fx[CLDFB_NO_CHANNELS_MAX]; /*Q-19*/ #endif #ifndef IVAS_FLOAT_FIXED diff --git a/lib_dec/ivas_stereo_dft_dec_fx.c b/lib_dec/ivas_stereo_dft_dec_fx.c index 19973a3df292d8cb1dba29c7bb96646eda35db12..87cc8fc2c5ed46753a4d5e515ced74668750874b 100644 --- a/lib_dec/ivas_stereo_dft_dec_fx.c +++ b/lib_dec/ivas_stereo_dft_dec_fx.c @@ -1403,7 +1403,7 @@ void stereo_dft_dec_res_fx( bass_psfilter_fx( hCPE->hStereoDft->hBpf, hCPE->hCoreCoder[0]->Opt_AMR_WB, out_16, L_FRAME8k, hCPE->hCoreCoder[0]->old_pitch_buf_16_fx + ( L_FRAME8k / STEREO_DFT_L_SUBFR_8k ), hCPE->hCoreCoder[0]->bpf_off, hCPE->hCoreCoder[0]->stab_fac_fx, &hCPE->hStereoDft->stab_fac_smooth_res_fx, hCPE->hCoreCoder[0]->last_coder_type, 0, bpf_error_signal_8k_16 ); Copy_Scale_sig_16_32( bpf_error_signal_8k_16, bpf_error_signal_8k, L_FRAME8k, Q15 ); - res_bpf_flag = res_bpf_adapt_ivas_fx( hCPE->hStereoDft, bpf_error_signal_8k, res_buf ); + res_bpf_flag = res_bpf_adapt_ivas_fx( hCPE->hStereoDft, bpf_error_signal_8k, res_buf, q_res ); IF( prev_bfi ) { diff --git a/lib_dec/ivas_stereo_dft_plc_fx.c b/lib_dec/ivas_stereo_dft_plc_fx.c index d46c25879334a2e75b976875a27b99a722b31c6a..de5dae9ecb6c0d8fc9ba80fd3ab24bfbc5aded2c 100644 --- a/lib_dec/ivas_stereo_dft_plc_fx.c +++ b/lib_dec/ivas_stereo_dft_plc_fx.c @@ -655,12 +655,12 @@ void stereo_dft_res_subst_spec_fx( Word32 op; Word16 q_div, q_shift; /* For 1st subframe, apply reversed time ECU to get correct analysis window */ - f_frac = extract_l( L_shr( L_sub( plocsi[i], L_shl( plocs[i], Q16 ) ), 1 ) ); - peak_phase = BASOP_util_atan2( p_mem[2 * plocs[i] + 1], p_mem[2 * plocs[i]], 0 ); - phase_tmp = L_sub( peak_phase, mult( f_frac, STEREO_DFT_PLC_PH_C_FX ) ); - phase = L_sub( phase_tmp, mult( f_frac, EVS_PI_FX ) ); - op = L_negate( L_shl( phase, 1 ) ); - corr_phase = L_add( L_add( STEREO_DFT_PLC_STEP21, L_ana ), time_offs ); + f_frac = extract_l( L_shr( L_sub( plocsi[i], L_shl( plocs[i], Q16 ) ), 1 ) ); // Q15 + peak_phase = BASOP_util_atan2( p_mem[2 * plocs[i] + 1], p_mem[2 * plocs[i]], 0 ); // Q13 + phase_tmp = L_sub( peak_phase, mult( f_frac, STEREO_DFT_PLC_PH_C_FX ) ); // Q13 + phase = L_sub( phase_tmp, mult( f_frac, EVS_PI_FX ) ); // Q13 + op = L_negate( L_shl( phase, 1 ) ); // Q13 + corr_phase = L_add( L_add( STEREO_DFT_PLC_STEP21, L_ana ), time_offs ); // Q0 q_shift = norm_l( corr_phase ); corr_phase = Mpy_32_32( L_shl( corr_phase, q_shift ), plocsi[i] ); corr_phase = L_deposit_l( BASOP_Util_Divide3232_Scale( corr_phase, L_ana, &q_div ) ); @@ -680,13 +680,23 @@ void stereo_dft_res_subst_spec_fx( } ELSE { + /* corr_phase = PI2 * ( L_ana + time_offs ) * ( plocsi[i] / L_ana ); */ Word32 op = L_add( L_ana, time_offs ); Word16 q_div; op = Mpy_32_32( L_shl( op, Q15 ), plocsi[i] ); corr_phase = BASOP_Util_Divide3232_Scale( op, L_ana, &q_div ); corr_phase = extract_l( L_and( L_shl( corr_phase, q_div ), MAX_16 ) ); /* For 2nd subframe, do regular phase shift */ - corr_phase = L_negate( L_shr( L_mult0( extract_l( corr_phase ), EVS_PI_FX ), Q14 ) ); + /* Multiplying only with EVS_PI_Fx and taking care of 2 in shift */ + corr_phase = ( L_shr( L_mult0( extract_l( corr_phase ), EVS_PI_FX ), Q14 /* Q13 + Q1*/ ) ); + WHILE( LT_32( corr_phase, -EVS_PI_FX ) ) + { + corr_phase = L_add( L_add( corr_phase, EVS_PI_FX ), EVS_PI_FX ); + } + WHILE( GT_32( corr_phase, EVS_PI_FX ) ) + { + corr_phase = L_sub( L_sub( corr_phase, EVS_PI_FX ), EVS_PI_FX ); + } conj_sign = MAX_32; move32(); } diff --git a/lib_dec/ivas_stereo_icbwe_dec.c b/lib_dec/ivas_stereo_icbwe_dec.c index 2859edb3b1f240a62ada8e717138b84197421181..5540db7a3f81abc948f062e50c9f106c273719f9 100644 --- a/lib_dec/ivas_stereo_icbwe_dec.c +++ b/lib_dec/ivas_stereo_icbwe_dec.c @@ -1392,7 +1392,7 @@ void stereo_icBWE_dec_fx( tmp = shl( tmp, 2 ); icbweM2Ref_fx = Sqrt16( sub( 16384, tmp ), &temp1_fx ); icbweM2Ref_fx = BASOP_Util_Divide1616_Scale( icbweM2Ref_fx, ratio_L_fx, &temp2_fx ); - icbweM2Ref_fx = shl( icbweM2Ref_fx, add( temp1_fx, sub( temp2_fx, 1 ) ) ); // Q14 + icbweM2Ref_fx = shl_sat( icbweM2Ref_fx, add( temp1_fx, sub( temp2_fx, 1 ) ) ); // Q14 } ELSE { @@ -1421,7 +1421,7 @@ void stereo_icBWE_dec_fx( tmp = shl( tmp, 2 ); icbweM2Ref_fx = Sqrt16( sub( 16384, tmp ), &temp1_fx ); icbweM2Ref_fx = BASOP_Util_Divide1616_Scale( icbweM2Ref_fx, sub( 32767, ratio_L_fx ), &temp2_fx ); - icbweM2Ref_fx = shl( icbweM2Ref_fx, add( temp2_fx, sub( temp1_fx, 1 ) ) ); // Q14 + icbweM2Ref_fx = shl_sat( icbweM2Ref_fx, add( temp2_fx, sub( temp1_fx, 1 ) ) ); // Q14 } ELSE { diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 212183213f564146772e06d2862e5f9c7b8c914d..b6d153746284057284761583ac8f194e9f65fd4d 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -2279,7 +2279,7 @@ typedef struct Decoder_State int16_t bfi_pitch_frame; /* FEC - frame length when pitch for FEC is saved */ - Word16 old_pitch_buf_16_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ + Word16 old_pitch_buf_16_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values Q6 */ Word32 old_pitch_buf_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ int16_t upd_cnt; /* FEC - counter of frames since last update */ diff --git a/lib_dec/swb_tbe_dec_fx.c b/lib_dec/swb_tbe_dec_fx.c index d7c63d3fbcca036fdc11892ed6f73ee772716a96..1701bfdbf4bff9344243d9cae7d8869e6c63e424 100644 --- a/lib_dec/swb_tbe_dec_fx.c +++ b/lib_dec/swb_tbe_dec_fx.c @@ -968,8 +968,12 @@ void ivas_wb_tbe_dec_fx( FOR( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) { - L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ - shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ +#ifdef BASOP_NOGLOB + shaped_wb_excitation[i] = round_fx_sat( L_shl_sat( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#else + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#endif move16(); } Lscale = root_a_fx( Lscale, sub( 31, exp ), &exp ); diff --git a/lib_dec/updt_dec_fx.c b/lib_dec/updt_dec_fx.c index a4ec5e127164bd81514b65d6e744174316c2c58b..4c8df08998c6a0dccbf44138b33fe5c6642ad9d4 100644 --- a/lib_dec/updt_dec_fx.c +++ b/lib_dec/updt_dec_fx.c @@ -833,7 +833,7 @@ void ivas_updt_dec_common_fx( Decoder_State *st_fx, /* i/o: decoder state structure */ Word16 hq_core_type_fx, /* i : HQ core type */ const Word16 concealWholeFrameTmp, /* i : concealWholeFrameTmp flag */ - const Word32 *synth, /* i : decoded synthesis */ + const Word32 *synth, /* i : decoded synthesis Q(Qpostd) */ const Word16 Qpostd /* i : Synthesis Q value */ ) diff --git a/lib_enc/FEC_enc.c b/lib_enc/FEC_enc.c index 308c3b02decc1443acd5cf7e5a45ddd3394bf643..fe61b552d52fbf9c35c2988c78e592f14ca22322 100644 --- a/lib_enc/FEC_enc.c +++ b/lib_enc/FEC_enc.c @@ -42,12 +42,182 @@ #include "rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#include "prot_fx.h" +#endif + /*-------------------------------------------------------------------* * FEC_encode() * * Encoder supplementary information for FEC *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void FEC_encode_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const ACELP_config acelp_cfg, /* i/o: configuration of the ACELP */ + const Word16 *synth, /* i : pointer to synthesized speech for E computation */ + const Word16 coder_type, /* i : type of coder */ + Word16 clas, /* i : signal clas for current frame */ + const Word16 *fpit, /* i : close loop fractional pitch buffer Q6 */ + const Word16 *res, /* i : LP residual signal frame */ + Word16 *last_pulse_pos, /* i/o: Position of the last pulse */ + const Word16 L_frame, /* i : Frame length */ + const Word32 total_brate, /* i : total codec bitrate */ + const Word16 Q_synth /* i : input scaling */ +) +{ + Word16 tmpS, index; + Word16 maxi, sign, tmp_FER_pitch; + Word32 enr_q, Ltmp; + Word16 exp_enrq; + + tmpS = 0; + move16(); + enr_q = 1; + move16(); + sign = 0; + move16(); + test(); + test(); + IF( GT_16( coder_type, UNVOICED ) && LT_16( coder_type, AUDIO ) && acelp_cfg.FEC_mode > 0 ) + { + /*-----------------------------------------------------------------* + * encode signal class (not needed for VC mode since it is clearly voiced) (2 bits) + *-----------------------------------------------------------------*/ + IF( NE_16( coder_type, VOICED ) ) + { + /* encode signal clas with 2 bits */ + test(); + IF( EQ_16( clas, UNVOICED_CLAS ) ) + { + index = 0; + move16(); + } + ELSE IF( EQ_16( clas, VOICED_TRANSITION ) || EQ_16( clas, UNVOICED_TRANSITION ) ) + { + index = 1; + move16(); + } + ELSE IF( EQ_16( clas, VOICED_CLAS ) ) + { + index = 2; + move16(); + } + ELSE + { + index = 3; + move16(); + } + push_indice( hBstr, IND_FEC_CLAS, index, FEC_BITS_CLS ); + } + + /*-----------------------------------------------------------------* + * encode frame energy (5 bits) + *-----------------------------------------------------------------*/ + test(); + IF( GT_16( acelp_cfg.FEC_mode, 1 ) ) /* GENERIC and VOICED frames */ + { + /* frame energy (maximum energy per pitch period for voiced frames or mean energy per sample over 2nd halframe for unvoiced frames) */ + /*frame_ener( L_frame, clas, synth, fpit[(L_frame>>6)-1], &enr_q, 0 );*/ + Word32 synth32[L_FRAME16k]; + Copy_Scale_sig_16_32( synth, synth32, L_FRAME16k, 0 ); + fer_energy_fx( L_frame, clas, synth32, Q_synth, shr_r( fpit[sub( shr( L_frame, 6 ), 1 )], 6 ), &enr_q, L_frame ); + exp_enrq = sub( 31, shl( Q_synth, 1 ) ); + IF( EQ_16( clas, VOICED_CLAS ) || EQ_16( clas, ONSET ) || EQ_16( clas, SIN_ONSET ) ) /* Voiced or Onset current frame */ + { + exp_enrq = 31; + move16(); + } + /* linearly quantize the energy in the range 0 : FEC_ENR_STEP : 96 dB */ + /*tmpS = (short)( 10.0 * log10( enr_q + 0.001f ) / FEC_ENR_STEP )*/ /*To be converted fl_2_fx*/ + + Ltmp = Mpy_32_32( BASOP_Util_Log10( enr_q, exp_enrq ), 894784853 /* 10 / FEC_ENR_STEP Q28 */ ); // Q 25 + 28 - 31 = Q22 + IF( Ltmp < 0 ) + { + tmpS = extract_l( L_negate( L_shr( L_negate( Ltmp ), Q22 ) ) ); + } + ELSE + { + tmpS = extract_l( L_shr( Ltmp, Q22 ) ); + } + + tmpS = s_min( tmpS, FEC_ENR_QLIMIT ); + tmpS = s_max( tmpS, 0 ); + + push_indice( hBstr, IND_FEC_ENR, tmpS, FEC_BITS_ENR ); + } + /*-----------------------------------------------------------------* + * Encode last glottal pulse position (8 bits) + *-----------------------------------------------------------------*/ + test(); + IF( GT_16( acelp_cfg.FEC_mode, 2 ) ) /* GENERIC frames */ + { + /* retrieve the last glottal pulse position of the previous frame */ + /* use the current pitch information to scale or not the quantization */ + tmp_FER_pitch = shr( fpit[0], 6 ); /* take the 1st subframe pit, since it is easier to get on decoder side */ + sign = 0; + move16(); + maxi = *last_pulse_pos; + move16(); + IF( maxi < 0 ) + { + sign = 1; + move16(); + /*maxi = -maxi; */ + maxi = negate( maxi ); + } + + if ( GE_16( tmp_FER_pitch, 128 ) ) + { + maxi = shr( maxi, 1 ); + } + + if ( GT_16( maxi, 127 ) ) + { + /* better not use the glottal pulse position at all instead of using a wrong pulse */ + /* can happen only with pitch > 254 and max pit = 289 and should happen very rarely */ + maxi = 0; + move16(); + } + + if ( EQ_16( sign, 1 ) ) + { + maxi = add( maxi, 128 ); /* use 8 bits (MSB represent the sign of the pulse) */ + } + + push_indice( hBstr, IND_FEC_POS, maxi, FEC_BITS_POS ); + } + maxi = 0; + move16(); + + /* If bitrate < 24k4, then the pitch + is not represented in the same domain (12.k instead of 16k) */ + test(); + IF( GE_16( clas, VOICED_CLAS ) && GE_32( total_brate, ACELP_24k40 ) ) + { + /*maxi = findpulse( L_frame, res, (short)(fpit[(L_frame>>6)-1]), 0, &sign ); */ + maxi = findpulse_fx( L_frame, res, shr_r( fpit[sub( shr( L_frame, 6 ), 1 )], 6 ), 0, &sign ); + if ( EQ_16( sign, 1 ) ) + { + /*maxi = -maxi;*/ + maxi = negate( maxi ); + } + } + + *last_pulse_pos = maxi; + move16(); + } + ELSE + { + *last_pulse_pos = 0; + move16(); + } + + return; +} +#endif void FEC_encode( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const ACELP_config acelp_cfg, /* i/o: configuration of the ACELP */ @@ -181,7 +351,6 @@ void FEC_encode( return; } - /*-------------------------------------------------------------------* * FEC_lsf_estim_enc() * diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index b573bc5a9b82d8f698efc54fcf88938d2dc9983a..e45d7a974e05aee643384065c8e291810f027815 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -43,12 +43,18 @@ #include "prot.h" #include "ivas_cnst.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "prot_fx.h" #include "prot_fx_enc.h" #include "ivas_rom_com.h" #include "wmc_auto.h" #include "options_warnings.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#endif + /*-------------------------------------------------------------------* * acelp_core_enc() * @@ -56,9 +62,9 @@ *--------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED ivas_error acelp_core_enc( - Encoder_State *st, /* i/o: encoder state structure */ - /*const*/ float inp[], /* i : input signal of the current frame */ - const float ener, /* i : residual energy from Levinson-Durbin*/ + Encoder_State *st, /* i/o: encoder state structure */ + /*const*/ float inp[], /* i : input signal of the current frame */ + // const float ener, /* i : residual energy from Levinson-Durbin*/ float A[NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes*/ float Aw[NB_SUBFR16k * ( M + 1 )], /* i : weighted A(z) unquant. for subframes*/ const float epsP[M + 1], /* i : LP prediction errors */ @@ -75,13 +81,21 @@ ivas_error acelp_core_enc( float tdm_lsfQ_PCh[M] /* i : Q LSFs for primary channel */ ) { - Word16 i, nBits; /* reserved bits */ - LPD_state_HANDLE hLPDmem; /* i/o: acelp memories */ - float old_exc_flt[L_EXC], *exc; /* excitation signal buffer */ - float lsf_new[M]; /* ISFs at the end of the frame */ - float Aq[NB_SUBFR16k * ( M + 1 )]; /* A(z) quantized for the 4 subframes */ - float syn[L_FRAME16k]; /* synthesis signal buffer */ - float res[L_FRAME16k]; /* Residual signal for FER protection */ + Word16 i, nBits; /* reserved bits */ + LPD_state_HANDLE hLPDmem; /* i/o: acelp memories */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fixed converstions + float old_exc_flt[L_EXC] = { 0 }, *exc; /* excitation signal buffer */ + float lsf_new[M] = { 0 }; /* ISFs at the end of the frame */ + float Aq[NB_SUBFR16k * ( M + 1 )] = { 0 }; /* A(z) quantized for the 4 subframes */ + float syn[L_FRAME16k] = { 0 }; /* synthesis signal buffer */ + float res[L_FRAME16k] = { 0 }; /* Residual signal for FER protection */ +#else + float old_exc_flt[L_EXC], *exc; /* excitation signal buffer */ + float lsf_new[M]; /* ISFs at the end of the frame */ + float Aq[NB_SUBFR16k * ( M + 1 )]; /* A(z) quantized for the 4 subframes */ + float syn[L_FRAME16k]; /* synthesis signal buffer */ + float res[L_FRAME16k]; /* Residual signal for FER protection */ +#endif // IVAS_FLOAT_FIXED_CONVERSIONS float exc2[L_FRAME16k]; /* enhanced excitation */ float Es_pred; /* predicited scaled innovation energy */ float tmp_noise; /* NB post-filter long-term noise energy*/ @@ -90,26 +104,21 @@ ivas_error acelp_core_enc( float *bwe_exc; /* excitation for SWB TBE */ Word16 allow_cn_step; Word32 int_fs; - float att; Word16 nb_bits; /* parameters handling */ /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */ Word16 pstreaklen; float mem_MA[M], mem_AR[M], Bin_E[L_FFT], Bin_E_old[L_FFT / 2], lsp_new_bck[M], lsp_mid_bck[M], mem_syn_bck[M]; - float clip_var, mem_w0_bck, streaklimit; float q_env[NUM_ENV_CNG]; Word16 sid_bw = -1; float exc3[L_FRAME16k]; float syn1[L_FRAME16k]; - float tilt_code_bck; - float gc_threshold_bck; - float clip_var_bck[6]; Word16 next_force_sf_bck; Word16 uc_two_stage_flag; Word16 position; - float tmpF; + // float tmpF; Word16 ppp_mode, nelp_mode; Word16 tdm_lp_reuse_flag, tdm_low_rate_mode, tdm_Pitch_reuse_flag; float *tdm_Pri_pitch_buf; @@ -125,9 +134,10 @@ ivas_error acelp_core_enc( Word16 Aq_fx[NB_SUBFR16k * ( M + 1 )]; /* A(z) quantized for the 4 subframes */ Word16 syn_fx[L_FRAME16k]; /* synthesis vector */ Word16 res_fx[L_FRAME16k]; /* Residual signal for FER protection */ - // Word16 exc2_fx[L_FRAME16k]; /* enhanced excitation */ - Word16 Es_pred_fx; /* predicited scaled innovation energy */ - Word16 tmp_noise_fx; /* NB post-filter long-term noise energy*/ + Word16 exc2_fx[L_FRAME16k]; /* enhanced excitation */ + Word16 Es_pred_fx; /* predicited scaled innovation energy */ + Word16 tmp_noise_fx; /* NB post-filter long-term noise energy*/ + // Word16 tc_subfr_fx; /* TC sub-frame indication */ Word16 old_bwe_exc_fx[( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2]; /* excitation buffer */ Word16 Q_old_bwe_exc; @@ -156,11 +166,13 @@ ivas_error acelp_core_enc( Word32 gc_threshold_bck_fx; Word16 clip_var_bck_fx[6]; // Word16 next_force_sf_bck_fx; - // Word32 q_env_fx[NUM_ENV_CNG]; + Word32 q_env_fx[NUM_ENV_CNG]; // Word16 coder_type; - // Word16 exc3_fx[L_FRAME16k]; - // Word16 syn1_fx[L_FRAME16k]; - // Word16* tdm_Pri_pitch_buf_fx; + + Word16 exc3_fx[L_FRAME16k]; + Word16 syn1_fx[L_FRAME16k]; + Word16 *tdm_Pri_pitch_buf_fx; + Word16 att_fx; Word16 lsp_new_fx[M]; /* i : LSPs at the end of the frame */ @@ -169,6 +181,8 @@ ivas_error acelp_core_enc( Word16 tmpF_fx; #endif #ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 pitch_buf_fx[NB_SUBFR16k]; /* To be removed once this is taken as input arg of function */ + Word16 voice_factors_fx[NB_SUBFR16k]; /* To be removed once this is taken as input arg of function */ Word16 tmp; set_zero( old_bwe_exc, 1380 ); for ( i = 0; i < NB_SUBFR16k; i++ ) @@ -209,14 +223,19 @@ ivas_error acelp_core_enc( Word16 inp_buff[L_FRAME16k + M + 1]; Word16 *inp_fx; inp_fx = &inp_buff[M + 1]; - Word16 e_mem_w0 = 0, q_comm_Bin, Q_new /* Q_new will be later passed from parent function as arg */; + Word16 q_comm_Bin, Q_new /* Q_new will be later passed from parent function as arg */; q_comm_Bin = s_min( Q_factor_arrL( st->Bin_E_old, 128 ), Q_factor_arrL( st->Bin_E, 256 ) ); Q_new = Q_factor_arr( &inp[-M - 1], L_FRAME16k + M + 1 ); - floatToFixed_arr( &inp[-M - 1], &inp_fx[-M - 1], Q_new, L_FRAME16k + M + 1 ); Q_new = s_min( Q_new, q_comm_Bin - ( QSCALE - 2 ) ); + Q_new = s_min( Q_new, 5 ); + floatToFixed_arr( &inp[-M - 1], &inp_fx[-M - 1], Q_new, L_FRAME16k + M + 1 ); floatToFixed_arrL( st->Bin_E_old, st->Bin_E_old_fx, Q_new + Q_SCALE - 2, 128 ); floatToFixed_arrL( st->Bin_E, st->Bin_E_fx, Q_new + Q_SCALE - 2, 256 ); st->stab_fac_fx = float_to_fix16( st->stab_fac, Q15 ); + IF( hStereoTD ) + { + floatToFixed_arr( hStereoTD->tdm_Pri_pitch_buf, hStereoTD->tdm_Pri_pitch_buf_fx, Q6, 4 ); + } #endif ivas_error error; @@ -301,6 +320,8 @@ ivas_error acelp_core_enc( } tmp_noise = 0; + tmp_noise_fx = 0; + move16(); tc_subfr = -1; move16(); position = -1; @@ -309,13 +330,10 @@ ivas_error acelp_core_enc( /* SC-VBR temporary variables */ pstreaklen = 0; move16(); - clip_var = 0; clip_var_fx = 0; move16(); - mem_w0_bck = 0; mem_w0_bck_fx = 0; move16(); - streaklimit = 0; streaklimit_fx = 0; move16(); @@ -344,6 +362,7 @@ ivas_error acelp_core_enc( tdm_low_rate_mode = hStereoTD->tdm_low_rate_mode; tdm_Pitch_reuse_flag = hStereoTD->tdm_Pitch_reuse_flag; tdm_Pri_pitch_buf = hStereoTD->tdm_Pri_pitch_buf; + tdm_Pri_pitch_buf_fx = hStereoTD->tdm_Pri_pitch_buf_fx; } ELSE { @@ -357,6 +376,7 @@ ivas_error acelp_core_enc( } tdm_Pitch_reuse_flag = 0; tdm_Pri_pitch_buf = NULL; + tdm_Pri_pitch_buf_fx = NULL; } move16(); move16(); @@ -369,8 +389,6 @@ ivas_error acelp_core_enc( test(); test(); - UNUSED_PARAM( bwe_exc_fx ); - UNUSED_PARAM( exc_fx ); IF( NE_16( st->last_L_frame, st->L_frame ) && ( st->last_core == ACELP_CORE || EQ_16( st->last_core, AMR_WB_CORE ) ) ) { /* in case of switching, do not apply BPF (flag employed also in updt_enc()) */ @@ -467,7 +485,7 @@ ivas_error acelp_core_enc( if ( st->cng_type == LP_CNG ) { /* Run CNG post parameter update */ -#if 1 +#ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS FOR( Word16 ii = 0; ii < HO_HIST_SIZE; ii++ ) { @@ -478,17 +496,106 @@ ivas_error acelp_core_enc( #endif cng_params_postupd_ivas_fx( st->hTdCngEnc->ho_circ_ptr, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf, st->hTdCngEnc->cng_Qexc_buf, st->hTdCngEnc->cng_brate_buf, st->hTdCngEnc->ho_env_circ_fx, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_inp; + floatToFixed_arr( Aq, Aq_fx, NB_SUBFR16k * ( M + 1 ), Q12 ); + q_inp = Q_factor_arr( inp, st->L_frame ); + floatToFixed_arr( inp, inp_fx, q_inp, st->L_frame ); + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + floatToFixed_arr( st->hTdCngEnc->ho_lsp_hist, st->hTdCngEnc->ho_lsp_hist_fx, Q15, HO_HIST_SIZE * M ); + floatToFixed_arr( st->hTdCngEnc->ho_lsp_circ, st->hTdCngEnc->ho_lsp_circ_fx, Q15, HO_HIST_SIZE * M ); + floatToFixed_arr( st->hTdCngEnc->ho_lsp_circ2, st->hTdCngEnc->ho_lsp_circ2_fx, Q15, HO_HIST_SIZE * M ); + floatToFixed_arrL( st->hTdCngEnc->ho_ener_hist, st->hTdCngEnc->ho_ener_hist_fx, Q6, HO_HIST_SIZE ); + floatToFixed_arrL( st->hTdCngEnc->ho_ener_circ, st->hTdCngEnc->ho_ener_circ_fx, Q6, HO_HIST_SIZE ); + floatToFixed_arr( st->hTdCngEnc->cng_ener_hist, st->hTdCngEnc->cng_ener_hist_fx, Q8, DTX_HIST_SIZE ); + floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); + floatToFixed_arrL( st->hTdCngEnc->cng_res_env, st->hTdCngEnc->cng_res_env_fx, Q6, NUM_ENV_CNG * HO_HIST_SIZE ); + floatToFixed_arr( st->hTdCngEnc->cng_lsp_hist, st->hTdCngEnc->cng_lsp_hist_fx, Q15, DTX_HIST_SIZE * M ); + floatToFixed_arrL( st->hTdCngEnc->lp_env, st->hTdCngEnc->lp_env_fx, Q6, NUM_ENV_CNG ); + floatToFixed_arrL( st->hTdCngEnc->ho_env_hist, st->hTdCngEnc->ho_env_hist_fx, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); + floatToFixed_arr( st->hTdCngEnc->exc_mem2, st->hTdCngEnc->exc_mem2_fx, q_inp, 30 ); + st->hTdCngEnc->lp_ener_fx = float_to_fix( st->hTdCngEnc->lp_ener, Q6 ); + st->hTdCngEnc->Enew_fx = float_to_fix( st->hTdCngEnc->Enew, Q6 ); + st->hTdCngEnc->lp_sp_enr_fx = float_to_fix16( st->hTdCngEnc->lp_sp_enr, Q8 ); + for ( i = 0; i < M; i++ ) + { + lsf_new_fx[i] = (Word16) ( lsf_new[i] * 2.56f ); + st->lsf_old_fx[i] = (Word16) ( st->lsf_old[i] * 2.56f ); + } +#endif + /* encode CNG parameters */ + CNG_enc_ivas_fx( st, Aq_fx, inp_fx, /*ener_fx,*/ lsp_mid_fx, lsp_new_fx, lsf_new_fx, &allow_cn_step, q_inp, q_env_fx, &sid_bw ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( Aq_fx, Aq, Q12, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arrL32( q_env_fx, q_env, Q6, NUM_ENV_CNG ); + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + fixedToFloat_arr( st->hDtxEnc->lspCNG_fx, st->hDtxEnc->lspCNG, Q15, M ); + fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ_fx, st->hTdCngEnc->ho_lsp_circ, Q15, HO_HIST_SIZE * M ); + fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ2_fx, st->hTdCngEnc->ho_lsp_circ2, Q15, HO_HIST_SIZE * M ); + fixedToFloat_arr( st->hTdCngEnc->ho_lsp_hist_fx, st->hTdCngEnc->ho_lsp_hist, Q15, HO_HIST_SIZE * M ); fixedToFloat_arrL( st->hTdCngEnc->ho_env_circ_fx, st->hTdCngEnc->ho_env_circ, Q6, 160 ); + fixedToFloat_arrL( st->hTdCngEnc->cng_res_env_fx, st->hTdCngEnc->cng_res_env, Q6, NUM_ENV_CNG * HO_HIST_SIZE ); + fixedToFloat_arr( st->hTdCngEnc->cng_ener_hist_fx, st->hTdCngEnc->cng_ener_hist, Q8, DTX_HIST_SIZE ); + fixedToFloat_arrL( st->hTdCngEnc->ho_ener_hist_fx, st->hTdCngEnc->ho_ener_hist, Q6, HO_HIST_SIZE ); + fixedToFloat_arrL( st->hTdCngEnc->ho_ener_circ_fx, st->hTdCngEnc->ho_ener_circ, Q6, HO_HIST_SIZE ); + fixedToFloat_arr( st->hTdCngEnc->cng_lsp_hist_fx, st->hTdCngEnc->cng_lsp_hist, Q15, DTX_HIST_SIZE * M ); + fixedToFloat_arrL( st->hTdCngEnc->lp_env_fx, st->hTdCngEnc->lp_env, Q6, NUM_ENV_CNG ); + fixedToFloat_arrL( st->hTdCngEnc->ho_env_hist_fx, st->hTdCngEnc->ho_env_hist, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); + fixedToFloat_arr( st->hTdCngEnc->exc_mem2_fx, st->hTdCngEnc->exc_mem2, q_inp, 30 ); + st->hTdCngEnc->lp_sp_enr = fix16_to_float( st->hTdCngEnc->lp_sp_enr_fx, Q8 ); + st->hTdCngEnc->lp_ener = fix_to_float( st->hTdCngEnc->lp_ener_fx, Q6 ); + st->hTdCngEnc->Enew = fix_to_float( st->hTdCngEnc->Enew_fx, Q6 ); + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + for ( i = 0; i < M; i++ ) + { + lsf_new[i] = ( (float) lsf_new_fx[i] / 2.56f ); + st->lsf_old[i] = ( (float) st->lsf_old_fx[i] / 2.56f ); + } #endif #else cng_params_postupd( st->hTdCngEnc->ho_circ_ptr, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hTdCngEnc->ho_env_circ, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); -#endif /* encode CNG parameters */ CNG_enc( st, Aq, inp, ener, lsp_mid, lsp_new, lsf_new, &allow_cn_step, q_env, &sid_bw ); +#endif + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTdCngEnc->Enew_fx = float_to_fix( st->hTdCngEnc->Enew, Q6 ); + st->hTdCngEnc->lp_ener_fx = float_to_fix( st->hTdCngEnc->lp_ener, Q6 ); + floatToFixed_arr32( q_env, q_env_fx, Q6, NUM_ENV_CNG ); + floatToFixed_arr32( st->hTdCngEnc->lp_env, st->hTdCngEnc->lp_env_fx, Q6, NUM_ENV_CNG ); + floatToFixed_arr32( st->hTdCngEnc->old_env, st->hTdCngEnc->old_env_fx, Q6, NUM_ENV_CNG ); + // Word16 Q_exc_l = Q_factor_arr( st->hTdCngEnc->exc_mem, 24 ); + // Word16 Q_exc1_l = Q_factor_arr( st->hTdCngEnc->exc_mem1, 30 ); + // Q_exc_l = min( Q_exc_l, Q_exc1_l ); + floatToFixed_arr( st->hTdCngEnc->exc_mem, st->hTdCngEnc->exc_mem_fx, Q_new, 24 ); + floatToFixed_arr( st->hTdCngEnc->exc_mem1, st->hTdCngEnc->exc_mem1_fx, Q_new, 30 ); +#endif /* comfort noise generation */ - CNG_exc( st->core_brate, st->L_frame, &st->hTdCngEnc->Enew, &st->hTdCngEnc->cng_seed, exc, exc2, &st->hTdCngEnc->lp_ener, st->last_core_brate, &st->hDtxEnc->first_CNG, &st->hTdCngEnc->cng_ener_seed, bwe_exc, allow_cn_step, &st->hTdCngEnc->last_allow_cn_step, st->hTdCngEnc->num_ho, q_env, st->hTdCngEnc->lp_env, st->hTdCngEnc->old_env, st->hTdCngEnc->exc_mem, st->hTdCngEnc->exc_mem1, &sid_bw, &st->hTdCngEnc->cng_ener_seed1, exc3, st->Opt_AMR_WB, EVS_MONO ); + // CNG_exc( st->core_brate, st->L_frame, &st->hTdCngEnc->Enew_fx, &st->hTdCngEnc->cng_seed, exc, exc2, &st->hTdCngEnc->lp_ener, st->last_core_brate, &st->hDtxEnc->first_CNG, + //&st->hTdCngEnc->cng_ener_seed, bwe_exc, allow_cn_step, &st->hTdCngEnc->last_allow_cn_step, st->hTdCngEnc->num_ho, q_env, st->hTdCngEnc->lp_env, st->hTdCngEnc->old_env, + // st->hTdCngEnc->exc_mem, st->hTdCngEnc->exc_mem1, &sid_bw, &st->hTdCngEnc->cng_ener_seed1, exc3, st->Opt_AMR_WB, EVS_MONO ); + CNG_exc_fx( st->core_brate, st->L_frame, &st->hTdCngEnc->Enew_fx, &st->hTdCngEnc->cng_seed, exc_fx, exc2_fx, &st->hTdCngEnc->lp_ener_fx, st->last_core_brate, + &st->hDtxEnc->first_CNG, &st->hTdCngEnc->cng_ener_seed, bwe_exc_fx, allow_cn_step, &st->hTdCngEnc->last_allow_cn_step, sub( st->prev_Q_new, 1 ), Q_new, st->hTdCngEnc->num_ho, + q_env_fx, st->hTdCngEnc->lp_env_fx, st->hTdCngEnc->old_env_fx, st->hTdCngEnc->exc_mem_fx, st->hTdCngEnc->exc_mem1_fx, &sid_bw, &st->hTdCngEnc->cng_ener_seed1, exc3_fx, st->Opt_AMR_WB, EVS_MONO ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTdCngEnc->Enew = fixedToFloat( st->hTdCngEnc->Enew_fx, Q6 ); + st->hTdCngEnc->lp_ener = fixedToFloat( st->hTdCngEnc->lp_ener_fx, Q6 ); + fixedToFloat_arrL( q_env_fx, q_env, Q6, NUM_ENV_CNG ); + fixedToFloat_arrL( st->hTdCngEnc->lp_env_fx, st->hTdCngEnc->lp_env, Q6, NUM_ENV_CNG ); + fixedToFloat_arrL( st->hTdCngEnc->old_env_fx, st->hTdCngEnc->old_env, Q6, NUM_ENV_CNG ); + fixedToFloat_arr( exc_fx, exc, Q_new, st->L_frame ); + fixedToFloat_arr( exc2_fx, exc2, Q_new, st->L_frame ); + fixedToFloat_arr( exc3_fx, exc3, Q_new, st->L_frame ); + fixedToFloat_arr( bwe_exc_fx, bwe_exc, Q_new, st->L_frame ); + fixedToFloat_arr( st->hTdCngEnc->exc_mem_fx, st->hTdCngEnc->exc_mem, Q_new, 24 ); + fixedToFloat_arr( st->hTdCngEnc->exc_mem1_fx, st->hTdCngEnc->exc_mem1, Q_new, 30 ); +#endif } else { @@ -498,19 +605,78 @@ ivas_error acelp_core_enc( st->hDtxEnc->last_CNG_L_frame = st->L_frame; } - generate_comfort_noise_enc( st ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_cngNoise = Q_factor_arrL( st->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, FFTCLDFBLEN ); + floatToFixed_arrL( st->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, st->hFdCngEnc->hFdCngCom->cngNoiseLevel, Q_cngNoise, FFTCLDFBLEN ); + st->hFdCngEnc->hFdCngCom->cngNoiseLevelExp = sub( 31, Q_cngNoise ); + IF( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif + // generate_comfort_noise_enc( st ); + generate_comfort_noise_enc_ivas_fx( st, Q_new, 1 ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->hFdCngEnc->hFdCngCom->exc_cng, st->hFdCngEnc->hFdCngCom->exc_cng_flt, Q_new, st->L_frame ); + fixedToFloat_arr( st->hFdCngEnc->hFdCngCom->olapBufferSynth, st->hFdCngEnc->hFdCngCom->olapBufferSynth_flt, st->hFdCngEnc->hFdCngCom->fftlenShift, FFTLEN ); + fixedToFloat_arr( st->hFdCngEnc->hFdCngCom->timeDomainBuffer, st->hFdCngEnc->hFdCngCom->timeDomainBuffer_flt, Q_new, st->hFdCngEnc->hFdCngCom->frameSize ); + fixedToFloat_arr( st->hTcxEnc->Txnq, st->hTcxEnc->Txnq_flt, Q_new, ( L_FRAME32k / 2 + 64 ) ); +#endif + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->A_cng_flt, st->hFdCngEnc->hFdCngCom->A_cng, Q12, ( M + 1 ) ); + // Word16 Q_exc_cng_l = Q_factor_arr( st->hFdCngEnc->hFdCngCom->exc_cng_flt, st->L_frame ); + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->exc_cng_flt, st->hFdCngEnc->hFdCngCom->exc_cng, Q_new, st->L_frame ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); +#endif + // FdCng_exc_flt( st->hFdCngEnc->hFdCngCom, &st->hDtxEnc->CNG_mode, st->L_frame, st->lsp_old, st->hDtxEnc->first_CNG, st->hDtxEnc->lspCNG, Aq, lsp_new, lsf_new, exc, exc2, bwe_exc ); + FdCng_exc( st->hFdCngEnc->hFdCngCom, &st->hDtxEnc->CNG_mode, st->L_frame, st->lsp_old_fx, st->hDtxEnc->first_CNG, st->hDtxEnc->lspCNG_fx, Aq_fx, lsp_new_fx, lsf_new_fx, exc_fx, exc2_fx, bwe_exc_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( Aq_fx, Aq, Q12, ( st->L_frame / L_SUBFR ) * ( M + 1 ) ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + for ( i = 0; i < M; i++ ) + { + lsf_new[i] = ( (float) lsf_new_fx[i] / 2.56f ); + } + + fixedToFloat_arr( st->hDtxEnc->lspCNG_fx, st->hDtxEnc->lspCNG, Q15, M ); + fixedToFloat_arr( exc_fx, exc, Q_new, st->L_frame ); + fixedToFloat_arr( exc2_fx, exc2, Q_new, st->L_frame ); + IF( st->hBWE_TD != NULL ) + { + fixedToFloat_arr( bwe_exc_fx, bwe_exc, Q_new, st->L_frame ); + } +#endif - FdCng_exc_flt( st->hFdCngEnc->hFdCngCom, &st->hDtxEnc->CNG_mode, st->L_frame, st->lsp_old, st->hDtxEnc->first_CNG, st->hDtxEnc->lspCNG, Aq, lsp_new, lsf_new, exc, exc2, bwe_exc ); mvr2r( exc2, exc3, st->L_frame ); if ( st->core_brate == SID_2k40 ) { if ( st->hTdCngEnc != NULL ) { - tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); - i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); - i = min( max( i, 0 ), 127 ); - st->hTdCngEnc->old_enr_index = i; + Word16 enr, enr_index; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + // Word16 Q_exc_l = Q_factor_arr( exc, st->L_frame ); + floatToFixed_arr( exc, exc_fx, Q_new, st->L_frame ); +#endif + // tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); + enr = cng_energy_ivas_fx( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att_fx, exc_fx, st->L_frame, Q_new ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // tmpF = fix16_to_float( tmpfx, Q8 ); +#endif + /* calculate the energy quantization index */ + enr_index = add( enr, 512 /* Q8(2.0) */ ); /* enr + 2.0 */ + enr_index = extract_l( L_shr( L_mult0( enr_index, STEP_SID_FX ), 12 + 8 ) ); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min( enr_index, 127 ); + enr_index = s_max( enr_index, 0 ); + st->hTdCngEnc->old_enr_index = enr_index; + move16(); } } } @@ -521,11 +687,32 @@ ivas_error acelp_core_enc( st->hTdCngEnc->burst_ho_cnt = 0; } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_syn_l, Q_exc_l; + + Q_exc_l = Q_factor_arr( exc3, st->L_frame ); + floatToFixed_arr( exc3, exc3_fx, Q_exc_l, st->L_frame ); + + Q_syn_l = Q_factor_arr( hLPDmem->mem_syn3_flt, M ); + floatToFixed_arr( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn3, Q_syn_l, M ); + + floatToFixed_arr( Aq, Aq_fx, NB_SUBFR16k * ( M + 1 ), Q12 ); +#endif /* synthesis at 12.8kHz sampling rate */ - syn_12k8( st->L_frame, Aq, exc3, syn1, hLPDmem->mem_syn3_flt, 1 ); + syn_12k8_fx( st->L_frame, Aq_fx, exc3_fx, syn1_fx, hLPDmem->mem_syn3, 1, Q_exc_l, Q_syn_l ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( Aq_fx, Aq, NB_SUBFR16k * ( M + 1 ), Q12 ); + fixedToFloat_arr( exc3_fx, exc, st->L_frame, Q_exc_l ); + fixedToFloat_arr( hLPDmem->mem_syn3, hLPDmem->mem_syn3_flt, Q_syn_l, M ); + fixedToFloat_arr( syn1_fx, syn1, Q_syn_l, st->L_frame ); +#endif /* reset the encoder */ - CNG_reset_enc( st, pitch_buf, voice_factors, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + CNG_reset_enc( st, pitch_buf, voice_factors, 0 ); /* To be removed once the function is completely fixed */ +#endif + CNG_reset_enc_fx( st, hLPDmem, pitch_buf_fx, voice_factors_fx, 0 ); /* update st->mem_syn1_flt for ACELP core switching */ mvr2r( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn1_flt, M ); @@ -539,11 +726,47 @@ ivas_error acelp_core_enc( /* save and delay synthesis to be used by SWB BWE */ if ( st->hBWE_FD != NULL ) { - save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 old_syn_12k8_16k_fx[L_FRAME16k]; + Word16 Q_syn1_l = Q_factor_arr( syn1, st->L_frame ); + Word16 Q_old_syn_l = Q_factor_arr( st->hBWE_FD->old_syn_12k8_16k, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + Q_syn1_l = min( Q_syn1_l, Q_old_syn_l ); + Word16 Q_deemph_l = Q_factor( st->hBWE_FD->mem_deemph_old_syn ); + Q_syn1_l = min( Q_syn1_l, Q_deemph_l ); + // Q_syn1_l = sub( Q_syn1_l, 1 ); + st->hBWE_FD->mem_deemph_old_syn_fx = float_to_fix16_thrld( st->hBWE_FD->mem_deemph_old_syn, Q_syn1_l ); + floatToFixed_arr( syn1, syn1_fx, Q_syn1_l, st->L_frame ); + floatToFixed_arr( st->hBWE_FD->old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k_fx, Q_syn1_l, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif + // save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + save_old_syn_fx( st->L_frame, syn1_fx, old_syn_12k8_16k_fx, st->hBWE_FD->old_syn_12k8_16k_fx, st->preemph_fac, &st->hBWE_FD->mem_deemph_old_syn_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn1_fx, syn1, Q_syn1_l, st->L_frame ); + fixedToFloat_arr( old_syn_12k8_16k_fx, old_syn_12k8_16k, Q_syn1_l, st->L_frame ); + st->hBWE_FD->mem_deemph_old_syn = fix16_to_float( st->hBWE_FD->mem_deemph_old_syn_fx, Q_syn1_l ); + fixedToFloat_arr( st->hBWE_FD->old_syn_12k8_16k_fx, st->hBWE_FD->old_syn_12k8_16k, Q_syn1_l, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + st->preemph_fac_flt = fix16_to_float( st->preemph_fac, Q15 ); +#endif } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 /* Q_syn_l, */ Q_lpd_syn_l; + Q_syn_l = Q_factor_arr( syn1, st->L_frame ); + Q_lpd_syn_l = Q_factor_arr( hLPDmem->syn_flt, ( M + 1 ) ); + Q_syn_l = min( Q_syn_l, Q_lpd_syn_l ); + + floatToFixed_arr( syn1, syn1_fx, Q_syn_l, st->L_frame ); + floatToFixed_arr( hLPDmem->syn_flt, hLPDmem->syn, Q_syn_l, ( M + 1 ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif /*Update MODE2 core switching memory*/ - deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + // deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + deemph_fx( syn1_fx, st->preemph_fac, st->L_frame, &( hLPDmem->syn[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn1_fx, syn1, Q_syn_l, st->L_frame ); + fixedToFloat_arr( hLPDmem->syn, hLPDmem->syn_flt, Q_syn_l, ( M + 1 ) ); +#endif mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); } @@ -576,16 +799,17 @@ ivas_error acelp_core_enc( { st->hLPDmem->tilt_code = float_to_fix16( st->hLPDmem->tilt_code_flt, Q15 ); st->hLPDmem->gc_threshold = float_to_fix16( st->hLPDmem->gc_threshold_flt, Q16 ); - f2me_buf_16( st->hLPDmem->mem_syn_flt, st->hLPDmem->mem_syn, &st->hLPDmem->e_mem_syn, M ); - f2me_16( st->hLPDmem->mem_w0_flt, &st->hLPDmem->mem_w0, &e_mem_w0 ); + f2me_buf_16( &st->hLPDmem->mem_syn_flt[-1], &st->hLPDmem->mem_syn[-1], &st->hLPDmem->e_mem_syn, M + 1 ); // -1 to sync the exponent of mem_syn with mem_w0 } floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); st->clip_var_fx[0] = (Word16) ( st->clip_var[0] * 2.56f ); - for ( i = 1; i < 6; i++ ) - { - st->clip_var_fx[i] = (Word16) ( st->clip_var[i] * ONE_IN_Q14 ); - } + st->clip_var_fx[1] = float_to_fix16( st->clip_var[1], Q14 ); + st->clip_var_fx[2] = float_to_fix16( st->clip_var[2], Q7 ); + st->clip_var_fx[3] = float_to_fix16( st->clip_var[3], 0 ); + st->clip_var_fx[4] = float_to_fix16( st->clip_var[4], Q14 ); + st->clip_var_fx[5] = float_to_fix16( st->clip_var[5], Q14 ); + st->streaklimit_fx = (Word16) floatToFixed( st->streaklimit, Q15 ); FOR( Word16 idx = 0; idx < M; idx++ ) { @@ -595,17 +819,29 @@ ivas_error acelp_core_enc( st->lsfoldbfi1_fx[idx] = (Word16) ( st->lsfoldbfi1[idx] * 2.56f ); st->lsfoldbfi0_fx[idx] = (Word16) ( st->lsfoldbfi0[idx] * 2.56f ); } - Q_exc = Q_factor_arr( old_exc_flt, st->L_frame ); Q_old_bwe_exc = Q_factor_arr( old_bwe_exc, 1380 ); floatToFixed_arr( old_bwe_exc, old_bwe_exc_fx, Q_old_bwe_exc, 1380 ); + Q_exc = Q_factor_arr( old_exc_flt, st->L_frame ); hLPDmem->e_old_exc = Q_factor_arr( &hLPDmem->old_exc_flt[-M - 1], L_EXC_MEM + M + 1 ) - 1; Q_exc = s_min( Q_exc, hLPDmem->e_old_exc ); - hLPDmem->e_old_exc = Q15 - hLPDmem->e_old_exc; + hLPDmem->e_old_exc = Q15 - Q_exc; floatToFixed_arr( &hLPDmem->old_exc_flt[-M - 1], &hLPDmem->old_exc[-M - 1], Q15 - hLPDmem->e_old_exc, L_EXC_MEM + M + 1 ); floatToFixed_arr16( old_exc_flt, old_exc_fx, Q_exc, st->L_frame ); st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); + + // Word16 pitch_buf_fx[NB_SUBFR16k]; + // Word16 voice_factors_fx[NB_SUBFR16k]; + floatToFixed_arr( voice_factors, voice_factors_fx, Q15, NB_SUBFR16k ); + st->hGSCEnc->Last_frame_ener_fx = floatToFixed_32( st->hGSCEnc->Last_frame_ener, Q4 ); + f2me_buf_16( st->hGSCEnc->last_exc_dct_in, st->hGSCEnc->last_exc_dct_in_fx, &st->hGSCEnc->Q_last_exc_dct_in, L_FRAME16k ); + st->hGSCEnc->Q_last_exc_dct_in = Q15 - st->hGSCEnc->Q_last_exc_dct_in; + st->hGSCEnc->last_ener_fx = (Word16) st->hGSCEnc->last_ener; + IF( st->hLPDmem ) + st->hLPDmem->tilt_code = float_to_fix16( st->hLPDmem->tilt_code_flt, Q15 ); + IF( st->hTdCngEnc ) + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); #endif /*-----------------------------------------------------------------* * Configure ACELP bit allocation @@ -663,17 +899,11 @@ ivas_error acelp_core_enc( *-----------------------------------------------------------------*/ /* SC-VBR & channel-aware mode - back-up memories for LSF quantizer and synthesis filter */ - st->next_force_safety_net_fx = st->next_force_safety_net; - move16(); lsf_syn_mem_backup_ivas_fx( st, &tilt_code_bck_fx, &gc_threshold_bck_fx, clip_var_bck_fx, &next_force_sf_bck, lsp_new_fx, lsp_mid_fx, &clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsp_mid_bck_fx, Bin_E_fx, Bin_E_old_fx, mem_syn_bck_fx, &mem_w0_bck_fx, &streaklimit_fx, &pstreaklen ); IF( !tdm_lp_reuse_flag ) { - st->next_force_safety_net_fx = st->next_force_safety_net; - move16(); lsf_enc_ivas_fx( st, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, tdm_low_rate_mode, st->GSC_IVAS_mode, tdm_lsfQ_PCh_fx, Q_new ); - st->next_force_safety_net = st->next_force_safety_net_fx; - move16(); } ELSE { @@ -747,11 +977,7 @@ ivas_error acelp_core_enc( *---------------------------------------------------------------*/ calc_residu_fx( st, inp_fx, res_fx, Aq_fx ); - -#if 1 // TODO: To be replaced with fixed version once available - calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); - att_fx = float_to_fix16( att, Q15 ); -#endif + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); IF( NE_16( att_fx, 32767 /* ONE_IN_Q15 */ ) ) { @@ -779,26 +1005,45 @@ ivas_error acelp_core_enc( Es_pred_enc_fx( &Es_pred_fx, &i, st->L_frame, res_fx, st->voicing_fx, nb_bits, uc_two_stage_flag, Q_new + 1 ); push_indice( hBstr, IND_ES_PRED, i, nb_bits ); } -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->mem_deemp_preQ = fixedToFloat( st->mem_deemp_preQ_fx, -1 ); - tilt_code_bck = fix16_to_float( tilt_code_bck_fx, Q15 ); - gc_threshold_bck = fix_to_float( gc_threshold_bck_fx, Q16 ); - clip_var_bck[0] = (float) clip_var_bck_fx[0] / 2.56f; - for ( i = 1; i < 6; i++ ) + + /*------------------------------------------------------------* + * Encode excitation according to coding type + *------------------------------------------------------------*/ + Word16 Q_exc2 = add( Q_new, 1 ); + IF( tdm_low_rate_mode ) /* tdm stereo low rate mode */ + { + IF( LE_16( st->coder_type, UNVOICED ) ) + { + tdm_low_rate_enc( st, Aq_fx, res_fx, syn_fx, exc_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, 0 /*attack_flag*/, lsf_new_fx, &tmp_noise_fx, &Q_exc2 ); + } + ELSE /* GENERIC */ + { + encod_gen_2sbfr( st, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf_fx, &Q_exc2 ); + } + } + ELSE IF( nelp_mode ) { - clip_var_bck[i] = (float) clip_var_bck_fx[i] / (float) ( ONE_IN_Q14 ); + /* SC-VBR - NELP frames */ + encod_nelp_ivas_fx( st, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, &tmp_noise_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, Q_new, 0 ); } - clip_var = (float) clip_var_fx / 2.56f; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->mem_deemp_preQ = fixedToFloat( st->mem_deemp_preQ_fx, -1 ); + + st->clip_var[0] = (float) st->clip_var_fx[0] / 2.56f; + st->clip_var[1] = fix16_to_float( st->clip_var_fx[1], Q14 ); + st->clip_var[2] = fix16_to_float( st->clip_var_fx[2], Q7 ); + st->clip_var[3] = fix16_to_float( st->clip_var_fx[3], 0 ); + st->clip_var[4] = fix16_to_float( st->clip_var_fx[4], Q14 ); + st->clip_var[5] = fix16_to_float( st->clip_var_fx[5], Q14 ); + for ( int ii = 0; ii < M; ii++ ) { - mem_AR[i] = (float) mem_AR_fx[i] / 2.56f; - mem_MA[i] = (float) mem_MA_fx[i] / 2.56f; + mem_AR[ii] = (float) mem_AR_fx[ii] / 2.56f; + mem_MA[ii] = (float) mem_MA_fx[ii] / 2.56f; } fixedToFloat_arr( lsp_new_bck_fx, lsp_new_bck, Q15, M ); fixedToFloat_arr( lsp_mid_bck_fx, lsp_mid_bck, Q15, M ); me2f_buf_16( mem_syn_bck_fx, st->hLPDmem->e_mem_syn, mem_syn_bck, M ); - mem_w0_bck = me2f( mem_w0_bck_fx, e_mem_w0 ); - streaklimit = fixedToFloat( streaklimit_fx, Q15 ); fixedToFloat_arr( lsp_new_fx, lsp_new, 15, M ); fixedToFloat_arr( lsp_mid_fx, lsp_mid, 15, M ); for ( i = 0; i < M; i++ ) @@ -829,52 +1074,27 @@ ivas_error acelp_core_enc( fixedToFloat_arr( old_bwe_exc_fx, old_bwe_exc, Q_old_bwe_exc, 1380 ); fixedToFloat_arr( res_fx, res, Q_new + 1, st->L_frame ); Es_pred = fix16_to_float( Es_pred_fx, Q8 ); -#endif -#endif - /*------------------------------------------------------------* - * Encode excitation according to coding type - *------------------------------------------------------------*/ - IF( tdm_low_rate_mode ) /* tdm stereo low rate mode */ - { - IF( LE_16( st->coder_type, UNVOICED ) ) - { -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 pitch_buf_fx[NB_SUBFR]; - Word16 voice_factors_fx[NB_SUBFR16k]; - floatToFixed_arr( voice_factors, voice_factors_fx, Q15, NB_SUBFR16k ); - st->hGSCEnc->Last_frame_ener_fx = floatToFixed_32( st->hGSCEnc->Last_frame_ener, Q4 ); - f2me_buf_16( st->hGSCEnc->last_exc_dct_in, st->hGSCEnc->last_exc_dct_in_fx, &st->hGSCEnc->Q_last_exc_dct_in, L_FRAME16k ); - st->hGSCEnc->Q_last_exc_dct_in = Q15 - st->hGSCEnc->Q_last_exc_dct_in; - st->hGSCEnc->last_ener_fx = (Word16) st->hGSCEnc->last_ener; - IF( st->hLPDmem ) - st->hLPDmem->tilt_code = float_to_fix16( st->hLPDmem->tilt_code_flt, Q15 ); + me2f_buf_16( &st->hLPDmem->mem_w0, st->hLPDmem->e_mem_syn, &st->hLPDmem->mem_w0_flt, M + 1 ); + fixedToFloat_arr( exc_fx, exc, Q_exc, L_FRAME ); + fixedToFloat_arr( exc2_fx, exc2, Q_exc, L_FRAME16k ); + if ( st->hBWE_TD ) + fixedToFloat_arr( bwe_exc_fx, bwe_exc, Q_exc, L_FRAME32k ); + st->hGSCEnc->Last_frame_ener = fixedToFloat_32( st->hGSCEnc->Last_frame_ener_fx, Q4 ); + me2f_buf_16( st->hGSCEnc->last_exc_dct_in_fx, Q15 - st->hGSCEnc->Q_last_exc_dct_in, st->hGSCEnc->last_exc_dct_in, L_FRAME16k ); + fixedToFloat_arr( syn_fx, syn, Q_exc2, L_FRAME16k ); + fixedToFloat_arr( voice_factors_fx, voice_factors, Q15, NB_SUBFR16k ); + fixedToFloat_arr( pitch_buf_fx, pitch_buf, Q6, NB_SUBFR ); + tmp_noise = fix16_to_float( tmp_noise_fx, Q8 ); + IF( st->hLPDmem ) + st->hLPDmem->tilt_code_flt = fix16_to_float( st->hLPDmem->tilt_code, Q15 ); #endif - Word16 Q_exc2 = add( Q_new, 1 ); - tdm_low_rate_enc( st, Aq_fx, res_fx, syn_fx, exc_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, 0 /*attack_flag*/, lsf_new_fx, &tmp_noise_fx, &Q_exc2 ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( exc_fx, exc, Q_exc, L_FRAME ); - if ( st->hBWE_TD ) - fixedToFloat_arr( bwe_exc_fx, bwe_exc, Q_exc, L_FRAME32k ); - st->hGSCEnc->Last_frame_ener = fixedToFloat_32( st->hGSCEnc->Last_frame_ener_fx, Q4 ); - me2f_buf_16( st->hGSCEnc->last_exc_dct_in_fx, Q15 - st->hGSCEnc->Q_last_exc_dct_in, st->hGSCEnc->last_exc_dct_in, L_FRAME16k ); - fixedToFloat_arr( syn_fx, syn, Q_exc2, L_FRAME16k ); - fixedToFloat_arr( voice_factors_fx, voice_factors, Q15, NB_SUBFR16k ); - fixedToFloat_arr( pitch_buf_fx, pitch_buf, Q6, NB_SUBFR ); - tmp_noise = fix16_to_float( tmp_noise_fx, Q8 ); - IF( st->hLPDmem ) - st->hLPDmem->tilt_code_flt = fix16_to_float( st->hLPDmem->tilt_code, Q15 ); #endif - } - else /* GENERIC */ - { - encod_gen_2sbfr( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); - } + if ( tdm_low_rate_mode ) /* tdm stereo low rate mode */ + { } else if ( nelp_mode ) { - /* SC-VBR - NELP frames */ - encod_nelp( st, inp, Aw, Aq, res, syn, &tmp_noise, exc, exc2, pitch_buf, voice_factors, bwe_exc ); } else if ( st->coder_type == UNVOICED ) { @@ -888,17 +1108,84 @@ ivas_error acelp_core_enc( else if ( ppp_mode ) { /* SC-VBR - PPP frames */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 shift; + shift = 0; + move16(); +#endif + IF( ( error = encod_ppp_fx( st, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, Q_new, shift ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < NB_SUBFR16k; i++ ) + { + // Array is getting modified in chunks of 17 inside. + // So each chunk might have a different Q which is predicted by 1st element. + fixedToFloat_arr( &Aq_fx[i * ( M + 1 )], &Aq[i * ( M + 1 )], 14 - norm_s( Aq_fx[i * ( M + 1 )] ), ( M + 1 ) ); + } + fixedToFloat_arr( res_fx, res, Q_new + 1, st->L_frame ); + fixedToFloat_arr( syn_fx, syn, Q_exc2, L_FRAME16k ); + fixedToFloat_arr( exc_fx, exc, Q_exc, L_FRAME ); + fixedToFloat_arr( exc2_fx, exc2, Q_exc, L_FRAME16k ); + fixedToFloat_arr( pitch_buf_fx, pitch_buf, Q6, NB_SUBFR ); + fixedToFloat_arr( voice_factors_fx, voice_factors, Q15, NB_SUBFR16k ); + if ( st->hBWE_TD ) + { + fixedToFloat_arr( bwe_exc_fx, bwe_exc, Q_exc, L_FRAME32k ); + } +#endif +#else if ( ( error = encod_ppp( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc ) ) != IVAS_ERR_OK ) { return error; } - +#endif if ( st->hSC_VBR->bump_up ) /* PPP failed, bump up */ { /* restore memories of LSF quantizer and synthesis filter */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( lsp_new_bck, lsp_new_bck_fx, Q15, M ); + floatToFixed_arr( lsp_mid_bck, lsp_mid_bck_fx, Q15, M ); + q_comm_Bin = s_min( Q_factor_arrL( st->Bin_E_old, L_FFT / 2 ), Q_factor_arrL( st->Bin_E, L_FFT ) ); + floatToFixed_arrL( Bin_E, Bin_E_fx, q_comm_Bin, L_FFT ); + floatToFixed_arrL( Bin_E_old, Bin_E_old_fx, q_comm_Bin, L_FFT / 2 ); + Word16 mem_syn = Q_factor_arr( mem_syn_bck, M ); + floatToFixed_arr( mem_syn_bck, mem_syn_bck_fx, mem_syn, M ); + for ( i = 0; i < M; i++ ) + { + mem_AR_fx[i] = (Word16) ( mem_AR[i] * 2.56f ); + mem_MA_fx[i] = (Word16) ( mem_MA[i] * 2.56f ); + } +#endif + lsf_syn_mem_restore_ivas_fx( st, tilt_code_bck_fx, gc_threshold_bck_fx, clip_var_bck_fx, next_force_sf_bck, lsp_new_fx, lsp_mid_fx, clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsp_mid_bck_fx, Bin_E_fx, Bin_E_old_fx, mem_syn_bck_fx, mem_w0_bck_fx, streaklimit_fx, pstreaklen ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hLPDmem->tilt_code_flt = fix16_to_float( st->hLPDmem->tilt_code, Q15 ); + st->hLPDmem->gc_threshold_flt = fix_to_float( st->hLPDmem->gc_threshold, Q16 ); + st->clip_var[0] = st->clip_var_fx[0] / 2.56f; + st->clip_var[1] = fix16_to_float( st->clip_var_fx[1], Q14 ); + st->clip_var[2] = fix16_to_float( st->clip_var_fx[2], Q7 ); + st->clip_var[3] = fix16_to_float( st->clip_var_fx[3], 0 ); + st->clip_var[4] = fix16_to_float( st->clip_var_fx[4], Q14 ); + st->clip_var[5] = fix16_to_float( st->clip_var_fx[5], Q14 ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, q_comm_Bin, L_FFT ); + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, q_comm_Bin, L_FFT / 2 ); + fixedToFloat_arr( st->hLPDmem->mem_syn, st->hLPDmem->mem_syn_flt, mem_syn, M ); + st->hLPDmem->mem_w0_flt = me2f( st->hLPDmem->mem_w0, st->hLPDmem->e_mem_syn ); + for ( i = 0; i < M; i++ ) + { + st->mem_AR[i] = (float) st->mem_AR_fx[i] / 2.56f; + st->mem_MA[i] = (float) st->mem_MA_fx[i] / 2.56f; + } +#endif +#else lsf_syn_mem_restore( st, tilt_code_bck, gc_threshold_bck, clip_var_bck, next_force_sf_bck, lsp_new, lsp_mid, clip_var, mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, Bin_E, Bin_E_old, mem_syn_bck, mem_w0_bck, streaklimit, pstreaklen ); - +#endif /* Configure ACELP bit allocation */ config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 0, &nb_bits, unbits, 0, &uc_two_stage_flag, 0, 0, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); @@ -934,12 +1221,49 @@ ivas_error acelp_core_enc( /* save and delay synthesis to be used by SWB BWE */ if ( st->hBWE_FD != NULL ) { - save_old_syn( st->L_frame, syn, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 old_syn_12k8_16k_fx[L_FRAME16k]; + Word16 Q_syn_l = Q_factor_arr( syn, st->L_frame ); + Word16 Q_old_syn_l = Q_factor_arr( st->hBWE_FD->old_syn_12k8_16k, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + Q_syn_l = min( Q_syn_l, Q_old_syn_l ); + Word16 Q_deemph_l = Q_factor( st->hBWE_FD->mem_deemph_old_syn ); + Q_syn_l = min( Q_syn_l, Q_deemph_l ); + // Q_syn_l = sub( Q_syn_l, 1 ); + st->hBWE_FD->mem_deemph_old_syn_fx = float_to_fix16_thrld( st->hBWE_FD->mem_deemph_old_syn, Q_syn_l ); + floatToFixed_arr( syn, syn_fx, Q_syn_l, st->L_frame ); + floatToFixed_arr( st->hBWE_FD->old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k_fx, Q_syn_l, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif + // save_old_syn( st->L_frame, syn, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + save_old_syn_fx( st->L_frame, syn_fx, old_syn_12k8_16k_fx, st->hBWE_FD->old_syn_12k8_16k_fx, st->preemph_fac, &st->hBWE_FD->mem_deemph_old_syn_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn_fx, syn, Q_syn_l, st->L_frame ); + fixedToFloat_arr( old_syn_12k8_16k_fx, old_syn_12k8_16k, Q_syn_l, st->L_frame ); + st->hBWE_FD->mem_deemph_old_syn = fix16_to_float( st->hBWE_FD->mem_deemph_old_syn_fx, Q_syn_l ); + fixedToFloat_arr( st->hBWE_FD->old_syn_12k8_16k_fx, st->hBWE_FD->old_syn_12k8_16k, Q_syn_l, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + st->preemph_fac_flt = fix16_to_float( st->preemph_fac, Q15 ); +#endif } /*Update MODE2 core switching memory*/ mvr2r( syn, syn1, st->L_frame ); - deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_syn_l, Q_lpd_syn_l; + Q_syn_l = Q_factor_arr( syn1, st->L_frame ); + Q_lpd_syn_l = Q_factor_arr( hLPDmem->syn_flt, ( M + 1 ) ); + Q_syn_l = min( Q_syn_l, Q_lpd_syn_l ); + + floatToFixed_arr( syn1, syn1_fx, Q_syn_l, st->L_frame ); + floatToFixed_arr( hLPDmem->syn_flt, hLPDmem->syn, Q_syn_l, ( M + 1 ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif + /*Update MODE2 core switching memory*/ + deemph_fx( syn1_fx, st->preemph_fac, st->L_frame, &( hLPDmem->syn[M] ) ); + // deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn1_fx, syn1, Q_syn_l, st->L_frame ); + fixedToFloat_arr( hLPDmem->syn, hLPDmem->syn_flt, Q_syn_l, ( M + 1 ) ); +#endif mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); if ( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) @@ -955,14 +1279,58 @@ ivas_error acelp_core_enc( { /* exc2 buffer is needed only for updating of Aq[] which is needed for core switching */ mvr2r( exc, exc2, st->L_frame ); +#ifndef IVAS_FLOAT_FIXED stat_noise_uv_enc( st, epsP, lsp_new, lsp_mid, Aq, exc2, uc_two_stage_flag ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from float to fix + Q_exc2 = Q_factor_arr( exc2, L_FRAME ); + floatToFixed_arr( exc2, exc2_fx, Q_exc2, L_FRAME16k ); + floatToFixed_arr( Aq, Aq_fx, 12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr( st->lspold_s, st->lspold_s_fx, 15, 16 ); + st->min_alpha_fx = float_to_fix16( st->min_alpha, 15 ); + Word32 LepsP[2]; + Word32 epsP_fx[M + 1]; + Word16 e_epsP; + f2me_buf( epsP, epsP_fx, &e_epsP, M + 1 ); + st->ge_sm_fx = float_to_fix( st->ge_sm, 6 ); + st->exc_pe_fx = float_to_fix16( st->exc_pe, st->Q_stat_noise ); + floatToFixed_arr( lsp_new, lsp_new_fx, 15, 16 ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, 15, 16 ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, 15, 16 ); +#endif + LepsP[0] = epsP_fx[2]; + move32(); + LepsP[1] = epsP_fx[16]; + move32(); + stat_noise_uv_enc_ivas_fx( st, LepsP, lsp_new_fx, lsp_mid_fx, Aq_fx, exc2_fx, uc_two_stage_flag, Q_exc2 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from fix to float + fixedToFloat_arr( exc2_fx, exc2, Q_exc2, L_FRAME16k ); + fixedToFloat_arr( Aq_fx, Aq, 12, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( st->lspold_s_fx, st->lspold_s, 15, 16 ); + st->min_alpha = fix16_to_float( st->min_alpha_fx, 15 ); + st->ge_sm = fix_to_float( st->ge_sm_fx, 6 ); + st->exc_pe = fix16_to_float( st->exc_pe_fx, st->Q_stat_noise ); +#endif +#endif } /*-----------------------------------------------------------------* * Encode supplementary information for Frame Error Concealment *-----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_syn = Q_factor_arr( syn, L_FRAME16k ); + q_syn = min( q_syn, Q_factor_arr( res, L_FRAME16k ) ); + floatToFixed_arr16( syn, syn_fx, q_syn, L_FRAME16k ); + floatToFixed_arr( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr16( res, res_fx, q_syn, L_FRAME16k ); +#endif + FEC_encode_ivas_fx( hBstr, st->acelp_cfg, syn_fx, st->coder_type, st->clas, pitch_buf_fx, res_fx, &st->Last_pulse_pos, st->L_frame, st->total_brate, q_syn ); +#else FEC_encode( hBstr, st->acelp_cfg, syn, st->coder_type, st->clas, pitch_buf, res, &st->Last_pulse_pos, st->L_frame, st->total_brate ); +#endif if ( st->hBWE_TD != NULL ) { @@ -1010,7 +1378,37 @@ ivas_error acelp_core_enc( if ( !st->Opt_SC_VBR && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { /* Apply a non linearity to the SHB excitation */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + // Word16 voice_factors_fx[NB_SUBFR16k]; + floatToFixed_arr( voice_factors, voice_factors_fx, Q15, 5 ); // Saturation Conversion used as last values have garbage values even in float + + st->hBWE_TD->bwe_non_lin_prev_scale_fx = floatToFixed( st->hBWE_TD->bwe_non_lin_prev_scale, Q30 ); + + Word32 bwe_exc_extended_fx[L_FRAME32k + NL_BUFF_OFFSET]; + Word16 q_bwe_exc = min( 14, Q_factor_arr( st->hBWE_TD->old_bwe_exc_extended, NL_BUFF_OFFSET ) ); + q_bwe_exc = min( q_bwe_exc, Q_factor_arr( bwe_exc, ( ( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2 ) - PIT16k_MAX * 2 ) ); + floatToFixed_arr16( bwe_exc, bwe_exc_fx, q_bwe_exc, ( ( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2 ) - PIT16k_MAX * 2 ); + floatToFixed_arr16( st->hBWE_TD->old_bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended_fx, q_bwe_exc, NL_BUFF_OFFSET ); + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + Copy_Scale_sig_16_32( st->hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_fx, NL_BUFF_OFFSET, 0 ); + non_linearity_ivas_fx( bwe_exc_fx, bwe_exc_extended_fx + NL_BUFF_OFFSET, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale_fx, q_bwe_exc, st->coder_type, voice_factors_fx, st->L_frame ); + // Q bwe_exc_extended_fx = 2 * Q bwe_exc_fx = 2 * q_bwe_exc + Copy_Scale_sig_32_16( bwe_exc_extended_fx + L_FRAME32k, st->hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET, -q_bwe_exc ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st->hBWE_TD->bwe_non_lin_prev_scale = fixedToFloat_32( st->hBWE_TD->bwe_non_lin_prev_scale_fx, Q30 ); + fixedToFloat_arrL( bwe_exc_extended_fx, bwe_exc_extended, 2 * q_bwe_exc, L_FRAME32k + NL_BUFF_OFFSET ); + fixedToFloat_arr( st->hBWE_TD->old_bwe_exc_extended_fx, st->hBWE_TD->old_bwe_exc_extended, q_bwe_exc, NL_BUFF_OFFSET ); + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); +#endif // IVAS_FLOAT_FIXED } if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) @@ -1022,12 +1420,88 @@ ivas_error acelp_core_enc( /*-----------------------------------------------------------------* * Updates *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + // Word16 pitch_buf_fx[NB_SUBFR16k]; + floatToFixed_arr( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr16( st->old_pitch_buf, st->old_pitch_buf_fx, Q6, 2 * NB_SUBFR16k ); + + Es_pred_fx = float_to_fix16( Es_pred, Q8 ); + floatToFixed_arr16( Aq, Aq_fx, 12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr16( lsp_new, lsp_new_fx, 15, M ); + for ( i = 0; i < M; i++ ) + { + + lsf_new_fx[i] = (Word16) ( lsf_new[i] * 2.56f ); + }; + + Word16 q_old_exc = Q_factor_arr( old_exc_flt, L_EXC ); + floatToFixed_arr16( old_exc_flt, old_exc_fx, q_old_exc, L_EXC ); + st->hLPDmem->e_old_exc = sub( 15, q_old_exc ); + + Word16 q_old_bwe_exc; + IF( st->hBWE_TD != NULL ) + { + q_old_bwe_exc = Q_factor_arr( old_bwe_exc, ( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2 ); + floatToFixed_arr16( old_bwe_exc, old_bwe_exc_fx, q_old_bwe_exc, ( PIT16k_MAX + ( L_FRAME16k + 1 ) + L_SUBFR16k ) * 2 ); + st->Q_exc = q_old_bwe_exc; + } + + IF( st->hGSCEnc != NULL ) + { + st->hGSCEnc->mid_dyn_fx = float_to_fix16( st->hGSCEnc->mid_dyn, Q7 ); + } + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + updt_enc_fx( st, old_exc_fx, pitch_buf_fx, Es_pred_fx, Aq_fx, lsf_new_fx, lsp_new_fx, old_bwe_exc_fx ); + +#endif // IVAS_FLOAT_FIXED updt_enc( st, old_exc_flt, pitch_buf, Es_pred, Aq, lsf_new, lsp_new, old_bwe_exc ); if ( st->hTdCngEnc != NULL && st->Opt_DTX_ON && st->core_brate > SID_2k40 ) { /* update CNG parameters in active frames */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 q_exc = Q_factor_arr( exc, L_EXC - L_EXC_MEM ); + q_exc = min( q_exc, Q_factor_arr( st->hTdCngEnc->cng_exc2_buf_flt, HO_HIST_SIZE * L_FFT ) ); + floatToFixed_arr16( exc, exc_fx, q_exc, L_EXC - L_EXC_MEM ); + floatToFixed_arr16( st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_exc2_buf, q_exc, HO_HIST_SIZE * L_FFT ); + + floatToFixed_arr32( st->hTdCngEnc->ho_ener_circ, st->hTdCngEnc->ho_ener_circ_fx, Q6, HO_HIST_SIZE ); + floatToFixed_arr32( st->hTdCngEnc->ho_env_circ, st->hTdCngEnc->ho_env_circ_fx, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); + floatToFixed_arr16( st->hTdCngEnc->ho_lsp_circ, st->hTdCngEnc->ho_lsp_circ_fx, Q15, HO_HIST_SIZE * M ); + + // Backup + Word16 ho_circ_ptr = st->hTdCngEnc->ho_circ_ptr; + Word16 ho_circ_size = st->hTdCngEnc->ho_circ_size; + Word16 cng_buf_cnt = st->hTdCngEnc->cng_buf_cnt; + Word32 cng_brate_buf[HO_HIST_SIZE]; + for ( int j = 0; j < HO_HIST_SIZE; j++ ) + { + cng_brate_buf[j] = st->hTdCngEnc->cng_brate_buf[j]; + } + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + cng_params_upd_ivas_fx( lsp_new_fx, exc_fx, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ_fx, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ_fx, q_exc, ENC, st->hTdCngEnc->ho_env_circ_fx, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf, st->hTdCngEnc->cng_Qexc_buf, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Restore + st->hTdCngEnc->ho_circ_ptr = ho_circ_ptr; + st->hTdCngEnc->ho_circ_size = ho_circ_size; + st->hTdCngEnc->cng_buf_cnt = cng_buf_cnt; + for ( int j = 0; j < HO_HIST_SIZE; j++ ) + { + st->hTdCngEnc->cng_brate_buf[j] = cng_brate_buf[j]; + } +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#endif // IVAS_FLOAT_FIXED + cng_params_upd( lsp_new, exc, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ, ENC, st->hTdCngEnc->ho_env_circ, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); if ( st->L_frame == L_FRAME ) @@ -1052,7 +1526,19 @@ ivas_error acelp_core_enc( /* reset in case of bitrate switching in EVS */ if ( st->hSC_VBR != NULL ) { +#ifndef IVAS_FLOAT_FIXED update_average_rate( st->hSC_VBR, st->core_brate ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing float to fix conversions + st->hSC_VBR->SNR_THLD_fx = float_to_fix16( st->hSC_VBR->SNR_THLD, 8 ); +#endif + update_average_rate_fx( st->hSC_VBR, st->core_brate ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing fix to float conversions + st->hSC_VBR->SNR_THLD = fix16_to_float( st->hSC_VBR->SNR_THLD_fx, 8 ); +#endif +#endif } } @@ -1187,6 +1673,355 @@ ivas_error acelp_core_enc( tc_subfr = -1; position = -1; + exc = old_exc_flt + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + mvr2r( hLPDmem->old_exc_flt, old_exc_flt, L_EXC_MEM ); + mvr2r( hLPDmem->mem_syn2_flt, hLPDmem->mem_syn1_flt, M ); + mvr2r( hLPDmem->mem_syn2_flt, hLPDmem->mem_syn3_flt, M ); + + /* update Aw[] coefficients */ + weight_a_subfr( st->L_frame / L_SUBFR, A, Aw, st->gamma_flt, M ); +} + +if ( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) +{ + st->rate_switching_reset = 1; +} + +/*----------------------------------------------------------------* + * Encoding of CNG frames + *----------------------------------------------------------------*/ + +if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) +{ + if ( st->cng_type == LP_CNG ) + { + /* Run CNG post parameter update */ + cng_params_postupd( st->hTdCngEnc->ho_circ_ptr, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hTdCngEnc->ho_env_circ, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); + + /* encode CNG parameters */ + CNG_enc( st, Aq, inp, ener, lsp_mid, lsp_new, lsf_new, &allow_cn_step, q_env, &sid_bw ); + + /* comfort noise generation */ + CNG_exc( st->core_brate, st->L_frame, &st->hTdCngEnc->Enew, &st->hTdCngEnc->cng_seed, exc, exc2, &st->hTdCngEnc->lp_ener, st->last_core_brate, &st->hDtxEnc->first_CNG, &st->hTdCngEnc->cng_ener_seed, bwe_exc, allow_cn_step, &st->hTdCngEnc->last_allow_cn_step, st->hTdCngEnc->num_ho, q_env, st->hTdCngEnc->lp_env, st->hTdCngEnc->old_env, st->hTdCngEnc->exc_mem, st->hTdCngEnc->exc_mem1, &sid_bw, &st->hTdCngEnc->cng_ener_seed1, exc3, st->Opt_AMR_WB, EVS_MONO ); + } + else + { + if ( st->core_brate == SID_2k40 && st->element_mode != IVAS_CPE_MDCT ) + { + FdCng_encodeSID( st ); + st->hDtxEnc->last_CNG_L_frame = st->L_frame; + } + + generate_comfort_noise_enc( st ); + + FdCng_exc_flt( st->hFdCngEnc->hFdCngCom, &st->hDtxEnc->CNG_mode, st->L_frame, st->lsp_old, st->hDtxEnc->first_CNG, st->hDtxEnc->lspCNG, Aq, lsp_new, lsf_new, exc, exc2, bwe_exc ); + mvr2r( exc2, exc3, st->L_frame ); + + if ( st->core_brate == SID_2k40 ) + { + if ( st->hTdCngEnc != NULL ) + { + tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); + i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); + i = min( max( i, 0 ), 127 ); + st->hTdCngEnc->old_enr_index = i; + } + } + } + + /* Reset HO counter in the first SID frame */ + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->burst_ho_cnt = 0; + } + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8( st->L_frame, Aq, exc3, syn1, hLPDmem->mem_syn3_flt, 1 ); + + /* reset the encoder */ + CNG_reset_enc( st, pitch_buf, voice_factors, 0 ); + + /* update st->mem_syn1_flt for ACELP core switching */ + mvr2r( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn1_flt, M ); + + /* update ACELP core synthesis filter memory */ + mvr2r( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn_flt, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn1 + st->L_frame - L_SYN_MEM, hLPDmem->mem_syn_r_flt, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + if ( st->hBWE_FD != NULL ) + { + save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + } + + /*Update MODE2 core switching memory*/ + deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); +} + +/*----------------------------------------------------------------* + * Encoding of all other frames + *----------------------------------------------------------------*/ + +else +{ + /*-----------------------------------------------------------------* + * Configure ACELP bit allocation + *-----------------------------------------------------------------*/ + + nb_bits = 0; + st->acelp_cfg.FEC_mode = 0; + uc_two_stage_flag = 0; + + if ( !nelp_mode && !ppp_mode ) + { + config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, st->GSC_noisy_speech, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 0, &nb_bits, unbits, st->element_mode, &uc_two_stage_flag, tdm_lp_reuse_flag, tdm_low_rate_mode, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); + } + + /*-----------------------------------------------------------------* + * After inactive period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + +#ifdef NON_BE_FIX_807_MASA_DTX_BRSW + if ( st->hDtxEnc != NULL && ( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) ) +#else + if ( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) +#endif + { + mvr2r( st->hDtxEnc->lspCNG, st->lsp_old, M ); + lsp2lsf( st->hDtxEnc->lspCNG, st->lsf_old, M, int_fs ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + + if ( !st->use_acelp_preq ) + { + st->mem_deemp_preQ = 0.0f; + st->mem_preemp_preQ = 0.0f; + st->last_code_preq = 0; + st->last_nq_preQ = 0; + } + st->use_acelp_preq = 0; + + /*-----------------------------------------------------------------* + * LSF Quantization + * A[z] calculation + *-----------------------------------------------------------------*/ + + /* SC-VBR & channel-aware mode - back-up memories for LSF quantizer and synthesis filter */ + lsf_syn_mem_backup( st, &tilt_code_bck, &gc_threshold_bck, clip_var_bck, &next_force_sf_bck, lsp_new, lsp_mid, &clip_var, mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, Bin_E, Bin_E_old, mem_syn_bck, &mem_w0_bck, &streaklimit, &pstreaklen ); + + if ( !tdm_lp_reuse_flag ) + { + lsf_enc( st, lsf_new, lsp_new, lsp_mid, Aq, tdm_low_rate_mode, st->GSC_IVAS_mode, tdm_lsfQ_PCh ); + } + else + { + const float *pt_interp_2; + + if ( st->active_cnt != 1 ) + { + int16_t beta_index; + float lsf_wgts[M]; + + /* intra_frame prediction for the LSFs */ + lsp2lsf( lsp_new, lsf_new, M, 12800 ); + + Unified_weighting( &st->Bin_E[L_FFT / 2], lsf_new, lsf_wgts, st->bwidth == NB, st->coder_type == UNVOICED, st->sr_core, M ); + + tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); + + push_indice( hBstr, IND_IC_LSF_PRED, beta_index, TDM_IC_LSF_PRED_BITS ); + } + + pt_interp_2 = interpol_frac_12k8; + if ( tdm_low_rate_mode == 1 && st->coder_type > UNVOICED ) + { + pt_interp_2 = interpol_frac2; + } + + if ( st->active_cnt == 1 ) + { + mvr2r( lsp_new, st->lsp_old, M ); + lsp2lsf( lsp_new, st->lsf_old, M, st->sr_core ); + lsp2lsf( lsp_new, lsf_new, M, st->sr_core ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp( st->L_frame, st->lsp_old, lsp_new, Aq, M, pt_interp_2, 0 ); + + /* Check LSF stability (distance between old LSFs and current LSFs) */ + st->stab_fac = lsf_stab( lsf_new, st->lsf_old, 0, st->L_frame ); + } + + if ( st->last_core == HQ_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory from last HQ frame */ + tmpF = hLPDmem->old_exc_flt[0]; + preemph( hLPDmem->old_exc_flt, st->preemph_fac_flt, st->L_frame, &tmpF ); + mvr2r( hLPDmem->old_exc_flt + st->L_frame - M, hLPDmem->mem_syn_flt, M ); + residu( Aq, M, hLPDmem->old_exc_flt, old_exc_flt, st->L_frame ); + } + + if ( st->last_core != ACELP_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory of old_bwe_exc */ + if ( st->L_frame == L_FRAME ) + { + lerp_flt( old_exc_flt, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC ); + } + else + { + lerp_flt( old_exc_flt, old_bwe_exc, L_EXC_MEM_DEC * 2, L_EXC_MEM_DEC ); + } + } + + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( inp, res, Aq, st->L_frame ); + + calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); + if ( att != 1.0f ) + { + v_multc( res, att, res, st->L_frame ); + } + + /*-----------------------------------------------------------------* + * Determine TC subframe classification + *-----------------------------------------------------------------*/ + + if ( st->coder_type == TRANSITION ) + { + tc_classif_enc( st->L_frame, &tc_subfr, &position, attack_flag, st->pitch[0], res ); + + config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 1, NULL, unbits, st->element_mode, &uc_two_stage_flag, tdm_lp_reuse_flag, tdm_low_rate_mode, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); + } + + /*---------------------------------------------------------------* + * Calculation of prediction for scaled innovation energy + * (for memory-less gain quantizer) + *---------------------------------------------------------------*/ + + if ( nb_bits > 0 ) + { + Es_pred_enc( &Es_pred, &i, st->L_frame, L_SUBFR, res, st->voicing, nb_bits, uc_two_stage_flag ); + push_indice( hBstr, IND_ES_PRED, i, nb_bits ); + } + + /*------------------------------------------------------------* + * Encode excitation according to coding type + *------------------------------------------------------------*/ + + if ( tdm_low_rate_mode ) /* tdm stereo low rate mode */ + { + if ( st->coder_type <= UNVOICED ) + { + tdm_low_rate_enc( st, Aq, res, syn, exc, pitch_buf, voice_factors, bwe_exc, 0 /*attack_flag*/, lsf_new, &tmp_noise ); + } + else /* GENERIC */ + { + encod_gen_2sbfr( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + } + else if ( nelp_mode ) + { + /* SC-VBR - NELP frames */ + encod_nelp( st, inp, Aw, Aq, res, syn, &tmp_noise, exc, exc2, pitch_buf, voice_factors, bwe_exc ); + } + else if ( st->coder_type == UNVOICED ) + { + /* UNVOICED frames (Gauss. excitation) */ + encod_unvoiced( st, inp, Aw, Aq, Es_pred, uc_two_stage_flag, res, syn, &tmp_noise, exc, pitch_buf, voice_factors, bwe_exc ); + } + else if ( st->coder_type == TRANSITION ) + { + encod_tran( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tc_subfr, position, unbits ); + } + else if ( ppp_mode ) + { + /* SC-VBR - PPP frames */ + if ( ( error = encod_ppp( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc ) ) != IVAS_ERR_OK ) + { + return error; + } + + + if ( st->hSC_VBR->bump_up ) /* PPP failed, bump up */ + { + /* restore memories of LSF quantizer and synthesis filter */ + lsf_syn_mem_restore( st, tilt_code_bck, gc_threshold_bck, clip_var_bck, next_force_sf_bck, lsp_new, lsp_mid, clip_var, mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, Bin_E, Bin_E_old, mem_syn_bck, mem_w0_bck, streaklimit, pstreaklen ); + + /* Configure ACELP bit allocation */ + config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 0, &nb_bits, unbits, 0, &uc_two_stage_flag, 0, 0, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); + + /* redo LSF quantization */ + lsf_enc( st, lsf_new, lsp_new, lsp_mid, Aq, tdm_low_rate_mode, 0, NULL ); + + /* recalculation of LP residual (filtering through A[z] filter) */ + calc_residu( inp, res, Aq, st->L_frame ); + st->hTdCngEnc->burst_ho_cnt = 0; + + /* VOICED frames in SC-VBR */ + encod_gen_voic( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + } + else if ( st->coder_type == AUDIO || ( st->coder_type == INACTIVE && st->inactive_coder_type_flag ) ) + { + /* AUDIO and INACTIVE frames (coded by GSC technology) */ + encod_audio( st, inp, Aw, Aq, res, syn, exc, pitch_buf, voice_factors, bwe_exc, attack_flag, lsf_new, &tmp_noise, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + else + { + /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */ + encod_gen_voic( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + + + /* update mem_syn1_flt for ACELP core switching */ + mvr2r( hLPDmem->mem_syn_flt, hLPDmem->mem_syn1_flt, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + st->L_frame - L_SYN_MEM, hLPDmem->mem_syn_r_flt, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + if ( st->hBWE_FD != NULL ) + { + save_old_syn( st->L_frame, syn, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + } + + /*Update MODE2 core switching memory*/ + mvr2r( syn, syn1, st->L_frame ); + deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); + + if ( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + mvr2r( syn1 + st->L_frame / 2, st->hTcxEnc->Txnq_flt, st->L_frame / 2 ); + } + + /*--------------------------------------------------------------------------------------* + * Modify the excitation signal when the noise is stationary + *--------------------------------------------------------------------------------------*/ + + if ( !( st->idchan == 1 && st->element_mode == IVAS_CPE_TD ) && nelp_mode != 1 && !( st->element_mode == IVAS_SCE && tdm_low_rate_mode ) ) + { + /* exc2 buffer is needed only for updating of Aq[] which is needed for core switching */ + mvr2r( exc, exc2, st->L_frame ); + stat_noise_uv_enc( st, epsP, lsp_new, lsp_mid, Aq, exc2, uc_two_stage_flag ); + } + + /*-----------------------------------------------------------------* + * Encode supplementary information for Frame Error Concealment + *-----------------------------------------------------------------*/ + + FEC_encode( hBstr, st->acelp_cfg, syn, st->coder_type, st->clas, pitch_buf, res, &st->Last_pulse_pos, st->L_frame, st->total_brate ); /* SC-VBR temporary variables */ pstreaklen = 0; clip_var = 0; @@ -1429,9 +2264,30 @@ ivas_error acelp_core_enc( lsp2lsf( lsp_new, lsf_new, M, 12800 ); Unified_weighting( &st->Bin_E[L_FFT / 2], lsf_new, lsf_wgts, st->bwidth == NB, st->coder_type == UNVOICED, st->sr_core, M ); +#ifdef IVAS_FLOAT_FIXED + Word16 lsf_new_fx[M]; + Word16 lsp_new_fx[M]; + Word16 tdm_lsfQ_PCh_fx[M]; + Word16 lsf_wgts_fx[M]; + for ( int ii = 0; ii < M; ii++ ) + { + lsf_new_fx[ii] = (Word16) ( ( lsf_new[ii] ) * 2.56f ); + tdm_lsfQ_PCh_fx[ii] = (Word16) ( ( tdm_lsfQ_PCh[ii] ) * 2.56f ); + lsf_wgts_fx[ii] = (Word16) ( ( lsf_wgts[ii] ) * 2.56f ); + } + floatToFixed_arr( lsp_new, lsp_new_fx, 15, M ); - tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); + tdm_SCh_lsf_reuse_fx( ENC, st->element_brate, lsf_new_fx, lsp_new_fx, tdm_lsfQ_PCh_fx, lsf_wgts_fx, &beta_index ); + for ( int ii = 0; ii < M; ii++ ) + { + lsf_new[ii] = (Word16) ( ( lsf_new_fx[ii] ) / 2.56f ); + lsf_wgts[ii] = (Word16) ( ( lsf_wgts_fx[ii] ) / 2.56f ); + } + fixedToFloat_arr( lsp_new_fx, lsp_new, 15, M ); +#else + tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); +#endif push_indice( hBstr, IND_IC_LSF_PRED, beta_index, TDM_IC_LSF_PRED_BITS ); } diff --git a/lib_enc/acelp_core_switch_enc_fx.c b/lib_enc/acelp_core_switch_enc_fx.c index 9ab60f5d76c32855bc03b007e9cc6f56e55d054e..029e3083ea893830d663c161a859cc83aa2943f9 100644 --- a/lib_enc/acelp_core_switch_enc_fx.c +++ b/lib_enc/acelp_core_switch_enc_fx.c @@ -11,7 +11,7 @@ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "basop_util.h" /* Function prototypes */ - +#include "prot.h" /*---------------------------------------------------------------------* * Local function prototypes *---------------------------------------------------------------------*/ @@ -26,8 +26,19 @@ static void encod_gen_voic_core_switch_fx( Encoder_State *st_fx, const Word32 core_bitrate_fx, Word16 shift, Word16 Q_new ); +static void encod_gen_voic_core_switch_ivas_fx( Encoder_State *st_fx, + const Word16 L_frame_fx, + const Word16 inp_fx[], + const Word16 Aq_fx[], + const Word16 A_fx[], + const Word16 T_op[], + Word16 *exc_fx, + const Word32 core_bitrate_fx, + Word16 shift, + Word16 Q_new ); static void bwe_switch_enc_fx( Encoder_State *st_fx, const Word16 *new_speech ); +static void bwe_switch_enc_ivas_fx( Encoder_State *st_fx, const Word16 *new_speech ); static Word16 dotprod_satcont( const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta ); @@ -181,6 +192,118 @@ void acelp_core_switch_enc_fx( return; } + +void acelp_core_switch_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 inp12k8[], /* i : input signal @12.8 kHz Q0 */ + const Word16 inp16k[], /* i : input signal @16 kHz Q0 */ + const Word16 A[NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes Q12*/ + Word16 shift, + Word16 Q_new ) +{ + Word16 i, j, T_op[2]; + Word16 old_exc[L_EXC], *exc; /* excitation signal buffer Qexc */ + const Word16 *inp; + Word32 cbrate; + Word16 Aq[2 * ( M + 1 )]; + LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */ + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + Word16 nb_bits; + UWord16 value; + + hLPDmem = st_fx->hLPDmem; + + /* initializations */ + exc = &old_exc[L_EXC_MEM]; + move16(); /* pointer to excitation signal in the current frame */ + Copy( hLPDmem->old_exc, old_exc, L_EXC_MEM ); /*now old_exc has the same scaling as st_fx->old_exc; need to change later? */ + + Copy( st_fx->old_Aq_12_8_fx, Aq, M + 1 ); + Copy( st_fx->old_Aq_12_8_fx, Aq + ( M + 1 ), M + 1 ); + T_op[0] = st_fx->pitch[0]; + move16(); + T_op[1] = st_fx->pitch[1]; + move16(); + + /*----------------------------------------------------------------* + * set switching frame bitrate + *----------------------------------------------------------------*/ + + IF( EQ_16( st_fx->last_L_frame, L_FRAME ) ) /* ACELP@12k8 core */ + { + inp = inp12k8; + + IF( GT_32( st_fx->core_brate, ACELP_24k40 ) ) + { + cbrate = L_add( ACELP_24k40, 0 ); + } + ELSE + { + cbrate = L_add( st_fx->core_brate, 0 ); + } + } + ELSE /* ACELP@16k core */ + { + inp = inp16k; + + IF( LE_32( st_fx->core_brate, ACELP_8k00 ) ) + { + cbrate = L_add( ACELP_8k00, 0 ); + } + ELSE IF( LE_32( st_fx->core_brate, ACELP_14k80 ) ) + { + cbrate = L_add( ACELP_14k80, 0 ); + } + ELSE + { + cbrate = L_min( st_fx->core_brate, ACELP_22k60 ); + } + } + + IF( NE_16( st_fx->last_L_frame, L_FRAME ) ) + { + T_op[0] = shr( add( round_fx( L_shl( L_mult( 20480, T_op[0] ), 2 ) ), 1 ), 1 ); + move16(); + T_op[1] = shr( add( round_fx( L_shl( L_mult( 20480, T_op[1] ), 2 ) ), 1 ), 1 ); + move16(); + } + + /*----------------------------------------------------------------* + * Excitation encoding + *----------------------------------------------------------------*/ + config_acelp1_IVAS( ENC, st_fx->total_brate, cbrate, st_fx->core, -1, -1, st_fx->last_L_frame, -1, &( st_fx->acelp_cfg ), hBstr->nb_bits_tot, + GENERIC, -1, -1, &j, &i, st_fx->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st_fx->idchan, st_fx->active_fr_cnt_fx, 0 /*tdm_Pitch_reuse_flag*/, 0, 0 /*GSC_IVAS_mode*/ ); + + encod_gen_voic_core_switch_ivas_fx( st_fx, st_fx->last_L_frame, inp, Aq, A, T_op, exc, cbrate, shift, Q_new ); + + /*----------------------------------------------------------------* + * bit-stream: modify the layer of sub frame CELP + *----------------------------------------------------------------*/ + + i = find_indice( hBstr, TAG_ACELP_SUBFR_LOOP_START, &value, &nb_bits ); + + while ( hBstr->ind_list[i].id == TAG_ACELP_SUBFR_LOOP_START ) + { + push_indice( hBstr, IND_CORE_SWITCHING_CELP_SUBFRAME, hBstr->ind_list[i].value, hBstr->ind_list[i].nb_bits ); + i++; + } + delete_indice( hBstr, TAG_ACELP_SUBFR_LOOP_START ); + + /*----------------------------------------------------------------* + * BWE encoding + *----------------------------------------------------------------*/ + + test(); + test(); + IF( !( ( EQ_16( st_fx->last_L_frame, L_FRAME16k ) && EQ_16( inner_frame_tbl[st_fx->bwidth], L_FRAME16k ) ) || EQ_16( inner_frame_tbl[st_fx->bwidth], L_FRAME8k ) ) ) + { + bwe_switch_enc_ivas_fx( st_fx, (const Word16 *) st_fx->old_input_signal_fx ); + } + + return; +} + + /*-------------------------------------------------------------------* * encod_gen_voic_core_switch() * @@ -406,6 +529,228 @@ static void encod_gen_voic_core_switch_fx( return; } +static void encod_gen_voic_core_switch_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 inp[], /* i : input signal */ + const Word16 Aq[], /* i : LP coefficients */ + const Word16 A[], /* i : unquantized A(z) filter */ + const Word16 T_op[], /* i : open loop pitch */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + const Word32 core_bitrate, /* i : switching frame bitrate */ + Word16 shift, + Word16 Q_new ) +{ + Word16 res[L_SUBFR]; /* residual signal Qexc */ + Word16 Ap[M + 1]; /* A(z) with spectral expansion Q12 */ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR + ( M + 1 )]; /* Impulse response vector */ + + Word16 code[L_SUBFR]; /* Fixed codebook excitation Q9 */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit; /* Pitch gain Q15 */ + Word16 voice_fac; /* Voicing factor Q15 */ + Word32 gain_code; /* Gain of code Q16 */ + Word16 gain_inov; /* inovation gain */ + Word16 i, gcode16; /* tmp variables */ + Word16 T0, T0_frac; /* close loop integer pitch and fractional part */ + Word16 T0_min, T0_max; /* pitch variables */ + + Word16 pitch, tmp16; /* floating pitch value */ + Word16 g_corr[6]; /* ACELP correl, values + gain pitch */ + Word16 clip_gain; /* ISF clip gain */ + + Word16 unbits; /* number of unused bits for PI */ + Word32 norm_gain_code; + Word16 pitch_limit_flag; + Word32 L_tmp, Lgcode; + Word16 shift_wsp; + Word16 h2[L_SUBFR + ( M + 1 )]; + Word16 dummyF[NB_SUBFR16k]; + Word16 lp_select, lp_flag; + LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */ + BSTR_ENC_HANDLE hBstr; + + hLPDmem = st_fx->hLPDmem; + hBstr = st_fx->hBstr; + + // TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + shift_wsp = add( Q_new, shift ); + + unbits = 0; + move16(); + + IF( EQ_16( L_frame, L_FRAME ) ) + { + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + move16(); + T0_min = PIT16k_MIN; + move16(); + } + + /*------------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *------------------------------------------------------------------*/ + + tmp16 = st_fx->L_frame; + move16(); + st_fx->L_frame = L_SUBFR; + move16(); + calc_residu_fx( st_fx, inp, res, Aq ); + + // hTdCngEnc->burst_ho_cnt = 0; + st_fx->L_frame = tmp16; + move16(); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + + Copy( res, exc, L_SUBFR ); + + IF( EQ_16( L_frame, L_FRAME16k ) ) + { + weight_a_fx( A, Ap, GAMMA16k, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets_ivas_fx( inp, hLPDmem->mem_syn, 0, &( hLPDmem->mem_w0 ), Aq, res, L_SUBFR, Ap, PREEMPH_FAC_16k, xn, cn, h1 ); + } + ELSE + { + weight_a_fx( A, Ap, GAMMA1, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets_ivas_fx( inp, hLPDmem->mem_syn, 0, &( hLPDmem->mem_w0 ), Aq, res, L_SUBFR, Ap, TILT_FAC_FX, xn, cn, h1 ); + } + + /*Scale_sig(h1, L_SUBFR, shift); */ /*Q14-shift */ + Copy_Scale_sig( h1, h2, L_SUBFR, -2 ); + Scale_sig( h1, L_SUBFR, add( 1, shift ) ); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig( xn, L_SUBFR, shift ); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + set16_fx( dummyF, -1, NB_SUBFR16k ); /* hack to signal ACELP->HQ switching frame */ + pitch = pit_encode_ivas_fx( hBstr, + st_fx->acelp_cfg.pitch_bits, core_bitrate, 0, L_frame, GENERIC, &pitch_limit_flag, 0, exc, L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn, 0 /*hStereoTD->tdm_Pitch_reuse_flag*/, dummyF /*hStereoTD->tdm_Pri_pitch_buf*/ ); + + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4( &exc[0], &exc[0], T0, T0_frac, L_SUBFR + 1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip_fx( st_fx->element_mode, core_bitrate, st_fx->voicing_fx, 0, GENERIC, xn, st_fx->clip_var_fx, sub( shift_wsp, 1 ) ); + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + lp_flag = st_fx->acelp_cfg.ltf_mode; + lp_select = lp_filt_exc_enc_ivas_fx( MODE1, GENERIC, 0, exc, h1, xn, y1, xn2, L_SUBFR, L_frame, g_corr, clip_gain, &gain_pit, &lp_flag ); + + IF( EQ_16( lp_flag, NORMAL_OPERATION ) ) + { + push_indice( hBstr, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode_ivas_fx( st_fx, core_bitrate, 0, L_frame, st_fx->last_L_frame, GENERIC, st_fx->bwidth, 0, 0, -1, Aq, gain_pit, cn, exc, + h2, hLPDmem->tilt_code, pitch, xn2, code, y2, &unbits, L_SUBFR, shift, Q_new ); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + IF( EQ_16( L_frame, L_FRAME ) ) + { + gain_enc_mless_ivas_fx( hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + ELSE + { + gain_enc_mless_ivas_fx( hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + gp_clip_test_gain_pit_fx( st_fx->element_mode, core_bitrate, gain_pit, st_fx->clip_var_fx ); + + Lgcode = L_shl( gain_code, Q_new ); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx( Lgcode ); + + // hLPDmem->tilt_code = Est_tilt2( exc + 0, gain_pit, code, gain_code, &voice_fac, shift ); + // Q_new or shift ?? ->Qexc + hLPDmem->tilt_code = est_tilt_ivas_fx( exc + 0, gain_pit, code, gain_code, &voice_fac, Q_new, L_SUBFR, 0 ); + move16(); + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < L_SUBFR; i++ ) + { + /* code in Q9, gain_pit in Q14 */ + L_tmp = L_mult( gcode16, code[i] ); +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( L_tmp, 5 ); + L_tmp = L_mac_sat( L_tmp, exc[i], gain_pit ); + L_tmp = L_shl_sat( L_tmp, 1 ); /* saturation can occur here */ + exc[i] = round_fx_sat( L_tmp ); +#else + L_tmp = L_shl( L_tmp, 5 ); + L_tmp = L_mac( L_tmp, exc[i], gain_pit ); + L_tmp = L_shl( L_tmp, 1 ); /* saturation can occur here */ + exc[i] = round_fx( L_tmp ); +#endif + move16(); + } + + /* write reserved bits */ + IF( unbits ) + { + push_indice( hBstr, IND_UNUSED, 0, unbits ); + } + + /*-----------------------------------------------------------------* + * long term prediction on the 2nd sub frame + *-----------------------------------------------------------------*/ + + pred_lt4( &exc[L_SUBFR], &exc[L_SUBFR], T0, T0_frac, L_SUBFR + 1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + FOR( i = L_SUBFR; i < 2 * L_SUBFR; i++ ) + { +#ifdef BASOP_NOGLOB + exc[i] = round_fx_sat( L_shl_sat( L_mult_sat( exc[i], gain_pit ), 1 ) ); +#else + exc[i] = round_fx( L_shl( L_mult( exc[i], gain_pit ), 1 ) ); +#endif + move16(); + } + + return; +} + /*-------------------------------------------------------------------* * bwe_switch_enc() @@ -559,6 +904,154 @@ static void bwe_switch_enc_fx( return; } +static void bwe_switch_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *new_speech_fx /* i : original input signal Q0 */ +) +{ + + Word16 k, Loverlapp_fx, d1m_fx, maxd1_fx, ind1_fx, gapsize_fx; + Word16 delta_fx, fdelay_fx; + const Word16 *hp_filter_fx; + const Word16 *fpointers_tab[6] = { hp12800_16000_fx, hp12800_32000_fx, hp12800_48000_fx, hp16000_48000_fx, hp16000_32000_fx, hp16000_48000_fx }; + Word16 tmp, shift; + const Word16 *ptmp; + Word16 tmp_mem_fx[2 * L_FILT48k], tmp_mem2_fx[2 * L_FILT48k], hb_synth_tmp_fx[480]; + Word16 Fs_kHz; + Word16 q_tmp1, q_tmp2, Qmc, Qsq; + Word32 L_tmp1, L_tmp2, L_tmp3, min_sq_cross_fx; + Word16 accA_fx, accB_fx, min_corr_fx, E1_fx, E2_fx, gain_fx; + Word16 synth_subfr_bwe_fx[SWITCH_MAX_GAP]; /* synthesized bwe for core switching */ + Word16 n, L; + BSTR_ENC_HANDLE hBstr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + hBstr = st_fx->hBstr; + L = NS2SA_FX2( st_fx->input_Fs, FRAME_SIZE_NS ); + + /* set multiplication factor according to the sampling rate */ + tmp = extract_l( L_shr( st_fx->input_Fs, 14 ) ); + delta_fx = add( tmp, 1 ); + Fs_kHz = shl( delta_fx, 4 ); + tmp = add( tmp, i_mult2( 3, ( sub( st_fx->last_L_frame, L_FRAME ) != 0 ) ) ); + ptmp = fpointers_tab[tmp]; + move16(); + + hp_filter_fx = ptmp; + fdelay_fx = i_mult2( 16, delta_fx ); + IF( EQ_16( st_fx->last_L_frame, L_FRAME ) ) + { + fdelay_fx = i_mult2( 20, delta_fx ); + } + + n = i_mult2( N16_CORE_SW, delta_fx ); + + set16_fx( tmp_mem_fx, 0, 2 * L_FILT48k ); + set16_fx( tmp_mem2_fx, 0, 2 * L_FILT48k ); + + Loverlapp_fx = i_mult2( delta_fx, SWITCH_OVERLAP_8k * 2 ); + gapsize_fx = i_mult2( delta_fx, NS2SA( 16000, SWITCH_GAP_LENGTH_NS ) ); + + shift = sub( add( add( shr( L, 1 ), n ), Loverlapp_fx ), gapsize_fx ); + Copy( new_speech_fx + shift, synth_subfr_bwe_fx, add( gapsize_fx, fdelay_fx ) ); + Copy( new_speech_fx + sub( shift, fdelay_fx ), tmp_mem_fx, fdelay_fx ); + + tmp = add( gapsize_fx, fdelay_fx ); + fir_fx( synth_subfr_bwe_fx, hp_filter_fx, synth_subfr_bwe_fx, tmp_mem_fx, tmp, fdelay_fx, 0, 0 ); + Copy( synth_subfr_bwe_fx + shr( fdelay_fx, 1 ), synth_subfr_bwe_fx, sub( gapsize_fx, shr( fdelay_fx, 1 ) ) ); + + tmp = i_mult2( Fs_kHz, 10 ); + fir_fx( new_speech_fx, hp_filter_fx, hb_synth_tmp_fx, tmp_mem2_fx, tmp, fdelay_fx, 1, 0 ); + + min_sq_cross_fx = L_negate( 1 ); + Qsq = 0; + move16(); + min_corr_fx = 0; + move16(); + Qmc = 0; + move16(); + d1m_fx = 0; + move16(); + + maxd1_fx = sub( tmp, add( gapsize_fx, fdelay_fx ) ); + + IF( EQ_16( delta_fx, 2 ) ) + { + maxd1_fx = shr( maxd1_fx, 1 ); + } + ELSE IF( EQ_16( delta_fx, 3 ) ) + { + maxd1_fx = extract_h( L_mult( maxd1_fx, 10923 ) ); + } + + /* find delay */ + ptmp = &hb_synth_tmp_fx[fdelay_fx]; + + FOR( k = 0; k < maxd1_fx; k++ ) + { + accA_fx = dotprod_satcont( ptmp, ptmp, 0, 0, &q_tmp1, gapsize_fx, delta_fx ); + accB_fx = dotprod_satcont( ptmp, synth_subfr_bwe_fx, 0, 0, &q_tmp2, gapsize_fx, delta_fx ); + ptmp += delta_fx; + L_tmp1 = L_mult0( accB_fx, accB_fx ); /*2*q_tmp2; */ + L_tmp2 = Mult_32_16( L_tmp1, min_corr_fx ); /*2*q_tmp2+Qmc-15 */ + L_tmp3 = Mult_32_16( min_sq_cross_fx, accA_fx ); /*Qsq+q_tmp1-15 */ + shift = s_min( add( shl( q_tmp2, 1 ), Qmc ), add( q_tmp1, Qsq ) ); + L_tmp2 = L_shr( L_tmp2, sub( add( shl( q_tmp2, 1 ), Qmc ), shift ) ); + L_tmp3 = L_shr( L_tmp3, sub( add( q_tmp1, Qsq ), shift ) ); + + IF( GE_32( L_tmp2, L_tmp3 ) ) + { + d1m_fx = k; + move16(); + min_corr_fx = accA_fx; + move16(); + Qmc = q_tmp1; + move16(); + min_sq_cross_fx = L_add( L_tmp1, 0 ); + Qsq = shl( q_tmp2, 1 ); + move16(); + } + } + + push_indice( hBstr, IND_CORE_SWITCHING_AUDIO_DELAY, d1m_fx, AUDIODELAYBITS ); + + tmp = add( i_mult2( d1m_fx, delta_fx ), fdelay_fx ); + ptmp = &hb_synth_tmp_fx[tmp]; + move16(); + E1_fx = dotprod_satcont( synth_subfr_bwe_fx, synth_subfr_bwe_fx, 0, 0, &q_tmp1, gapsize_fx, 1 ); + E2_fx = dotprod_satcont( ptmp, ptmp, 0, 0, &q_tmp2, gapsize_fx, 1 ); + + IF( !E1_fx ) + { + E1_fx = shl( 1, 14 ); + q_tmp1 = 14; + move16(); + } + IF( !E2_fx ) + { + E2_fx = shl( 1, 14 ); + q_tmp2 = 14; + move16(); + } + + tmp = div_s( shl( 1, 14 ), E1_fx ); /*Q(29-q_tmp1) */ + L_tmp1 = L_mult( tmp, E2_fx ); /*30-q_tmp1+q_tmp2 */ + q_tmp2 = sub( q_tmp1, q_tmp2 ); /*30-q_tmp2 */ + L_tmp1 = L_shl( L_tmp1, sub( q_tmp2, 24 ) ); +#ifdef BASOP_NOGLOB + gain_fx = round_fx_o( Isqrt( L_tmp1 ), &Overflow ); /*Q12 */ +#else + gain_fx = round_fx( Isqrt( L_tmp1 ) ); /*Q12 */ +#endif + ind1_fx = usquant_fx( gain_fx, &gain_fx, shr( MINVALUEOFFIRSTGAIN_FX, 1 ), shr( DELTAOFFIRSTGAIN_FX, 4 ), ( 1 << NOOFGAINBITS1 ) ); + push_indice( hBstr, IND_CORE_SWITCHING_AUDIO_GAIN, ind1_fx, NOOFGAINBITS1 ); + + return; +} + + static Word16 dotprod_satcont( const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta ) { Word16 tmp_tabx[L_FRAME48k], tmp_taby[L_FRAME48k]; diff --git a/lib_enc/amr_wb_enc.c b/lib_enc/amr_wb_enc.c index 054332d5fc4b9ab31c11a0e1086e88d12a109110..02a5152f71524b737874fb3d395e6cfe9c0bb5f5 100644 --- a/lib_enc/amr_wb_enc.c +++ b/lib_enc/amr_wb_enc.c @@ -42,7 +42,11 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * amr_wb_enc() * @@ -102,6 +106,8 @@ void amr_wb_enc( LPD_state_HANDLE hLPDmem = st->hLPDmem; + push_wmops( "amr_wb_enc" ); + /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ @@ -516,11 +522,87 @@ void amr_wb_enc( updt_enc( st, old_exc_flt, pitch_buf, 0, Aq, isf_new, isp_new, dummy_buf ); /* update main codec paramaters */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf_16( st->buf_speech_enc_pe_flt, st->buf_speech_enc_pe, &st->exp_buf_speech_enc_pe, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_speech_enc_flt, st->buf_speech_enc, &st->exp_buf_speech_enc, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_synth_flt, st->buf_synth, &st->exp_buf_synth, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + f2me_buf_16( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, &st->exp_buf_wspeech_enc, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + f2me_buf_16( st->hTcxEnc->buf_speech_ltp_flt, st->hTcxEnc->buf_speech_ltp, &st->hTcxEnc->exp_buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, 15 ); + } +#endif + + updt_enc_common_ivas_fx( st ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf_16( st->buf_speech_enc_pe, st->exp_buf_speech_enc_pe, st->buf_speech_enc_pe_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_speech_enc, st->exp_buf_speech_enc, st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_synth, st->exp_buf_synth, st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + me2f_buf_16( st->buf_wspeech_enc, st->exp_buf_wspeech_enc, st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + me2f_buf_16( st->hTcxEnc->buf_speech_ltp, st->hTcxEnc->exp_buf_speech_ltp, st->hTcxEnc->buf_speech_ltp_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) + { + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + IF( st->hTcxEnc != NULL ) + { + IF( st->element_mode != IVAS_CPE_MDCT ) + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + } + } + + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem_flt = fixedToFloat( st->hTcxEnc->tcxltp_norm_corr_mem, 31 ); + } + + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac_flt = PREEMPH_FAC_FLT; + st->gamma_flt = GAMMA1_FLT; + } + ELSE + { + st->preemph_fac_flt = PREEMPH_FAC_16k_FLT; + st->gamma_flt = GAMMA16k_FLT; + } + } + + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + } + } +#endif +#else updt_enc_common( st ); +#endif + pop_wmops(); return; } +#endif /*---------------------------------------------------------------------* * amr_wb_enc_init() diff --git a/lib_enc/amr_wb_enc_fx.c b/lib_enc/amr_wb_enc_fx.c index d2b2569b533e07439988c52ad28d0b3d2c0096bc..b07fc980fea3c2ed7a6003cbcf4a4525ab0e112b 100644 --- a/lib_enc/amr_wb_enc_fx.c +++ b/lib_enc/amr_wb_enc_fx.c @@ -89,6 +89,8 @@ void amr_wb_enc_fx( TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; FD_BWE_ENC_HANDLE hBWE_FD = st->hBWE_FD; + push_wmops( "amr_wb_enc_fx" ); + /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ @@ -609,6 +611,8 @@ void amr_wb_enc_fx( dbgwrite( &st->vad_flag, sizeof( short ), 1, input_frame, "res/vad_flag" ); #endif + pop_wmops(); + return; } /*---------------------------------------------------------------------* diff --git a/lib_enc/analy_sp_fx.c b/lib_enc/analy_sp_fx.c index e23c9b9a5eb4701391cfe37e7c43a7149f6ca0b5..82a77f60294300701605a70f1bb039e14b6f23c2 100644 --- a/lib_enc/analy_sp_fx.c +++ b/lib_enc/analy_sp_fx.c @@ -12,13 +12,15 @@ #include "rom_enc.h" #include "rom_com.h" #include - +#include /*-------------------------------------------------------------------* * Local prototypes *-------------------------------------------------------------------*/ static void find_enr( Word16 data[], Word32 band[], Word32 *ptE, Word32 *LEtot, const Word16 min_band, const Word16 max_band, const Word16 Q_new2, const Word32 e_min, Word32 *Bin_E, Word16 BIN_FREQ_FX, Word32 *band_energies ); - +#ifdef IVAS_FLOAT_FIXED1 +static void ivas_find_enr( Word16 data[], Word32 band[], Word32 *ptE, Word32 *LEtot, const Word16 min_band, const Word16 max_band, const Word16 Q_new2, const Word32 e_min, Word32 *Bin_E, Word16 BIN_FREQ_FX, Word32 *band_energies ); +#endif #ifdef IVAS_CODE_CPE static void find_enr_dft( CPE_ENC_HANDLE hCPE, const int32_t input_Fs, float DFT_past_DMX[], float band[], float *ptE, float *Etot, const int16_t min_band, const int16_t max_band, float *Bin_E, float *band_ener ); #endif @@ -194,6 +196,362 @@ void analy_sp_fx( return; } +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------* + * find_enr_dft_fx() + * + * find input signal energy for each critical band using the DFT buffers + *------------------------------------------------------------------------*/ + +static void find_enr_dft_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word32 input_Fs, /* i : input sampling rate */ + Word32 DFT_past_DMX_fx[], /* i:input DFT_Dmx (Q_inp_dmx ) */ + Word32 band_fx[], /* o : per band energy */ + Word32 *ptE_fx, /* o : per bin energy for low frequencies */ + Word32 *Etot_fx, /* i/o: total energy (Q8) */ + const Word16 min_band, /* i : minimum critical band */ + const Word16 max_band, /* i : maximum critical band */ + Word32 *Bin_E_fx, /* o : Per bin energy (Q7) */ + Word32 *band_ener_fx, /* o : per band energy without E_MIN (Qout) */ + Word16 Q_inp_dmx, + Word16 Qout ) +{ + Word16 i, cnt; + Word32 tmp_fx; + Word32 freq; + const Word32 *ptR_fx, *ptI_fx; + Word32 norm_val_fx; + Word16 bin_cnt = 0; + move16(); + // Word32 band_ener_fx[2 * NB_BANDS]; + // Etot_fx[0] = Etot[0] * ONE_IN_Q8; + Word32 c_fx, s_fx; + /* One window - 40ms*12.8kHz = 512 samples */ + Word32 c_1_fx = 2147321984; // cosf( PI2 / STEREO_DFT_N_12k8_ENC ) * ONE_IN_Q31; + Word32 s_1_fx = 26352928; // sinf( PI2 / STEREO_DFT_N_12k8_ENC ) * ONE_IN_Q31; + Word32 g_1_fx = 1570240000; // ( 1.f + 0.68f * 0.68f ) * ONE_IN_Q30; + Word32 g_2_fx = 1460288896; // 2 * 0.68f * ONE_IN_Q30; + move32(); + move32(); + move32(); + move32(); + + Word32 g_fx; + Word32 scaleWin_fx; + + Word32 BinE_fx[STEREO_DFT_N_12k8_ENC / 2]; /* NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 158 */ + Word16 tmp16, scale = 0; + tmp16 = BASOP_Util_Divide3216_Scale( input_Fs, hCPE->hStereoDft->NFFT, &scale ); + tmp16 = shr( tmp16, negate( add( 1, scale ) ) ); + Word16 bin_freq = tmp16; // input_Fs / (float) hCPE->hStereoDft->NFFT; /* adaptive frequency bin width */ + + // scaleWin = 1 / ( 2 * hCPE->hStereoDft->win_ana_energy ); + // scaleWin_fx = ONE_IN_Q31/ ( hCPE->hStereoDft->win_ana_energy_fx ); + scaleWin_fx = BASOP_Util_Divide3216_Scale( ONE_IN_Q31, hCPE->hStereoDft->win_ana_energy_fx, &scale ); // q = 16-scale + Word16 scalewin_q = sub( 16, scale ); + tmp16 = BASOP_Util_Divide3216_Scale( BIN, bin_freq, &scale ); + tmp16 = shr( tmp16, negate( add( 1, scale ) ) ); + Word16 x_fx = tmp16; + move16(); + scaleWin_fx = L_mult0( x_fx, extract_l( scaleWin_fx ) ); // scalewin_q + // scaleWin *= (float) BIN / bin_freq; + // norm_val = scaleWin * 4.0f / ( hCPE->hStereoDft->NFFT * hCPE->hStereoDft->NFFT ); + norm_val_fx = L_deposit_l( BASOP_Util_Divide3232_Scale( L_shl( scaleWin_fx, Q2 ), L_mult0( hCPE->hStereoDft->NFFT, hCPE->hStereoDft->NFFT ), &scale ) ); + norm_val_fx = L_shl( norm_val_fx, Q31 - ( scalewin_q + 15 - scale ) ); // q31 + + ptR_fx = &DFT_past_DMX_fx[2]; /* first real */ + ptI_fx = &DFT_past_DMX_fx[3]; /* first imaginary */ + move32(); + move32(); + c_fx = c_1_fx; + s_fx = s_1_fx; + move32(); + move32(); + + /* for low frequency bins, save per bin energy for the use in find_tilt() */ + freq = bin_freq; + move32(); + FOR( i = 0; i < NB_BANDS - 1; i++ ) /* up to maximum allowed voiced critical band */ + { + band_fx[i] = 0; + move32(); + cnt = 0; + move16(); + /* bins up to crit_band 17 (<= 3700 Hz): + * bin_cnt old (bin_width 50 Hz): 74 (74 * FRAMES_PER_SEC = 3700) + * bin_cnt new (bin_width 40 Hz): 92 (92 * 40 = 3680) + */ + tmp16 = BASOP_Util_Divide3216_Scale( L_sub( crit_bands_fx[i], freq ), bin_freq, &scale ); + tmp16 = shr( tmp16, negate( add( 1, scale ) ) ); + Word32 freq_diff = L_deposit_l( tmp16 ); + Word16 guarded_bits; + guarded_bits = find_guarded_bits_fx( freq_diff ); + s_fx = L_shr( s_fx, guarded_bits ); + c_fx = L_shr( c_fx, guarded_bits ); + WHILE( LE_32( freq, crit_bands_fx[i] ) ) + { + BinE_fx[bin_cnt] = W_extract_l( W_shr( W_add( W_mult0_32_32( *ptR_fx, *ptR_fx ), W_mult0_32_32( *ptI_fx, *ptI_fx ) ), 31 ) ); // /* energy */ + g_fx = L_sub( L_shr( g_1_fx, guarded_bits ), Mpy_32_32( g_2_fx, c_fx ) ); + tmp_fx = L_sub( Mpy_32_32( c_fx, c_1_fx ), Mpy_32_32( s_fx, s_1_fx ) ); + s_fx = L_add( Mpy_32_32( s_fx, c_1_fx ), Mpy_32_32( c_fx, s_1_fx ) ); + c_fx = tmp_fx; + move32(); + BinE_fx[bin_cnt] = Mpy_32_32( Mpy_32_32( BinE_fx[bin_cnt], norm_val_fx ), g_fx ); /* normalization - corresponds to FFT normalization by 2/L_FFT */ + move32(); + BinE_fx[bin_cnt] = L_shl( BinE_fx[bin_cnt], guarded_bits ); // 2 * Q_inp_dmx - 32 - 1 + move32(); + band_fx[i] = L_add( BinE_fx[bin_cnt], band_fx[i] ); + move32(); + ptR_fx += 2; + ptI_fx += 2; + freq = L_add( freq, L_deposit_l( bin_freq ) ); + cnt = add( cnt, 1 ); + bin_cnt = add( bin_cnt, 1 ); + } + s_fx = L_shl( s_fx, guarded_bits ); + c_fx = L_shl( c_fx, guarded_bits ); + band_fx[i] = Mpy_32_16_r( band_fx[i], inv_tbl_fx[cnt] ); /* normalization per frequency bin */ + move32(); + band_fx[i] = L_shl( band_fx[i], sub( Qout, sub( shl( Q_inp_dmx, 1 ), 32 ) ) ); + move32(); + band_ener_fx[i] = band_fx[i]; /* per band energy without E_MIN */ + move32(); + if ( LT_32( band_fx[i], L_shl( E_MIN_Q11_FX, sub( Qout, Q11 ) ) ) ) + { + band_fx[i] = L_shl( E_MIN_Q11_FX, sub( Qout, Q11 ) ); + move32(); + } + } + + /* continue computing the energy per critical band for higher frequencies */ + + /* old version, FFT 256 @ SR12.8 (-> bin_width = 50 Hz): + NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 127 = L_FFT/2-1*/ + + /* new version: DFT (1200/800/400) @ input SR (48/32/16) (-> bin_width = 40 Hz): + * + */ + /* NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 158 */ + /* NB_BANDS = 21 (= 7700Hz) = highest band available for SR 16 -> bin_cnt = 192 */ + /* NB_BANDS = 24 (= 15500Hz) = highest band available for SR 32 -> bin_cnt = 387 */ + /* NB_BANDS = 24 (= 15500Hz) = highest band available for SR 48 -> bin_cnt = 387 */ + + for ( ; i < NB_BANDS; i++ ) + { + band_fx[i] = 0; + move32(); + cnt = 0; + move16(); + tmp16 = BASOP_Util_Divide3216_Scale( L_sub( 6399, freq ), bin_freq, &scale ); + tmp16 = shr( tmp16, negate( add( 1, scale ) ) ); + Word32 freq_diff = L_deposit_l( tmp16 ); + Word16 guarded_bits; + guarded_bits = find_guarded_bits_fx( freq_diff ); + c_fx = L_shr( c_fx, guarded_bits ); + WHILE( LT_32( freq, 6399 ) ) + { + BinE_fx[bin_cnt] = W_extract_l( W_shr( W_add( W_mult0_32_32( *ptR_fx, *ptR_fx ), W_mult0_32_32( *ptI_fx, *ptI_fx ) ), 31 ) ); + move32(); + g_fx = L_sub( L_shr( g_1_fx, guarded_bits ), Mpy_32_32( g_2_fx, c_fx ) ); + BinE_fx[bin_cnt] = Mpy_32_32( Mpy_32_32( BinE_fx[bin_cnt], norm_val_fx ), g_fx ); + move32(); + BinE_fx[bin_cnt] = L_shl( BinE_fx[bin_cnt], guarded_bits ); // Q11 + move32(); + band_fx[i] = L_add( BinE_fx[bin_cnt], band_fx[i] ); + move32(); + ptR_fx += 2; + ptI_fx += 2; + freq = L_add( freq, L_deposit_l( bin_freq ) ); + cnt = add( cnt, 1 ); + bin_cnt = add( bin_cnt, 1 ); + } + c_fx = L_shl( c_fx, guarded_bits ); + band_fx[i] = Mpy_32_16_r( band_fx[i], inv_tbl_fx[cnt] ); + band_fx[i] = L_shl( band_fx[i], sub( Qout, sub( shl( Q_inp_dmx, 1 ), 32 ) ) ); + band_ener_fx[i] = band_fx[i]; + move32(); + if ( LT_32( band_fx[i], L_shl( E_MIN_Q11_FX, sub( Qout, Q11 ) ) ) ) + { + band_fx[i] = L_shl( E_MIN_Q11_FX, sub( Qout, Q11 ) ); + move32(); + } + } + + /* put bin energies from BinE into Bin_E[L_FFT/2-1] (interpolate 40 Hz bin values to fit into 50 Hz bins) */ + /* Last value of Bin_E is handled outside this function*/ + assert( bin_cnt == ( STEREO_DFT_N_12k8_ENC / 2 - 1 ) ); + Scale_sig32( BinE_fx, 256, sub( Qout, sub( shl( Q_inp_dmx, 1 ), 32 ) ) ); + BinE_fx[STEREO_DFT_N_12k8_ENC / 2 - 1] = BinE_fx[STEREO_DFT_N_12k8_ENC / 2 - 2]; + move32(); + L_lerp_fx( BinE_fx, Bin_E_fx, L_FFT / 2, STEREO_DFT_N_12k8_ENC / 2, &Qout ); + MVR2R_WORD32( Bin_E_fx, ptE_fx, VOIC_BINS ); // Qout + + + /* find the total log energy */ + tmp_fx = *Etot_fx; + move32(); + FOR( i = min_band; i <= max_band; i++ ) + { + tmp_fx = L_add( tmp_fx, band_fx[i] ); // Qout + } + *Etot_fx = tmp_fx; + move32(); + return; +} +#endif +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * ivas_analy_sp_fx() + * + * Spectral analysis of 12.8kHz input + *-------------------------------------------------------------------*/ + +void ivas_analy_sp_fx( + const Word16 element_mode, /* i : element mode */ + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word32 input_Fs, /* i : input sampling rate */ + Word16 *speech, /* i : speech buffer Q_new - preemph_bits */ + const Word16 Q_new, /* i : current scaling exp Q0 */ + Word32 *fr_bands, /* o : energy in critical frequency bands Q_new + QSCALE */ + Word32 *lf_E, /* o : per bin E for first... Q_new + QSCALE - 2*/ + Word16 *Etot, /* o : total input energy Q8 */ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word32 e_min_scaled, /* i : minimum energy scaled Q_new + QSCALE */ + Word16 Scale_fac[2], /* o : FFT scales factors (2 values by frame) Q0 */ + Word32 *Bin_E, /* o : per-bin energy spectrum Q7 */ + Word32 *Bin_E_old, /* o : per-bin energy spectrum of the previous frame Q7 */ + Word32 *PS, /* o : per-bin energy spectrum Q_new + QSCALE */ + Word16 *EspecdB, /* o : per-bin log energy spectrum (with f=0) Q7 */ + Word32 *band_energies, /* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN (Q_new + QSCALE + 2)*/ + Word16 *fft_buff /* o : FFT coefficients (Q_new + QSCALE + 2) */ +) +{ + Word16 *pt; + Word16 i_subfr, i; + Word32 *pt_bands; + Word32 Ltmp, LEtot; + Word16 *pt_fft; + Word16 Min_val, Max_val; + Word16 Scale_fac2; + Word16 fft_temp[L_FFT]; + + (void) input_Fs; + /*-----------------------------------------------------------------* + * Compute spectrum + * find energy per critical frequency band and total energy in dB + *-----------------------------------------------------------------*/ + + pt_bands = fr_bands; + pt_fft = fft_buff; + LEtot = L_deposit_l( 0 ); + IF( NE_16( element_mode, IVAS_CPE_DFT ) ) + { + FOR( i_subfr = 0; i_subfr <= 1; i_subfr++ ) + { + pt = speech + 3 * ( L_SUBFR / 2 ) - L_FFT / 2; + IF( i_subfr != 0 ) + { + pt = speech + 7 * ( L_SUBFR / 2 ) - L_FFT / 2; + } + + /* Clear 1st value of 1st part, copy 1st value of 2nd part */ + fft_temp[0] = 0; + move16(); + fft_temp[L_FFT / 2] = pt[L_FFT / 2]; + move16(); + Max_val = s_max( fft_temp[0], fft_temp[L_FFT / 2] ); + Min_val = s_min( fft_temp[0], fft_temp[L_FFT / 2] ); + + FOR( i = 1; i < L_FFT / 2; i++ ) + { + /* 1st windowed part */ + fft_temp[i] = mult_r( pt[i], sqrt_han_window_fx[i] ); + move16(); + if ( fft_temp[i] > 0 ) + Max_val = s_max( Max_val, fft_temp[i] ); + if ( fft_temp[i] < 0 ) + Min_val = s_min( Min_val, fft_temp[i] ); + + /* 2nd windowed part */ + fft_temp[L_FFT - i] = mult_r( pt[L_FFT - i], sqrt_han_window_fx[i] ); + move16(); + if ( fft_temp[L_FFT - i] > 0 ) + Max_val = s_max( Max_val, fft_temp[L_FFT - i] ); + if ( fft_temp[L_FFT - i] < 0 ) + Min_val = s_min( Min_val, fft_temp[L_FFT - i] ); + } + + /* Combine -Min_val and Max_val into one */ + Max_val = s_max( negate( Min_val ), Max_val ); + + Scale_fac[i_subfr] = s_min( sub( norm_s( Max_val ), 1 ), 6 ); + move16(); + Scale_fac2 = shl( Scale_fac[i_subfr], 1 ); + Scale_sig( fft_temp, L_FRAME_12k8, Scale_fac[i_subfr] ); + + r_fft_fx_lc( FFT_W128, SIZE_256, SIZE2_256, NUM_STAGE_256, fft_temp, pt_fft, 1 ); + /*e_min_scaled = Q_new + QSCALE + 2*/ + find_enr( pt_fft, pt_bands, lf_E + i_subfr * VOIC_BINS, &LEtot, min_band, max_band, + add( Q_new, Scale_fac2 ), e_min_scaled, &Bin_E[i_subfr * L_FFT / 2], BIN, band_energies + i_subfr * NB_BANDS ); + pt_bands += NB_BANDS; + pt_fft += L_FFT; + } + } + ELSE + { + Word16 Q_inp_dmx = Q_factor_arrL( hCPE->hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ); + floatToFixed_arrL( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], Q_inp_dmx, STEREO_DFT_N_MAX_ENC ); + Word16 Qout = add( Q_new, QSCALE - 2 ); + find_enr_dft_fx( hCPE, input_Fs, hCPE->hStereoDft->DFT_fx[0], pt_bands, lf_E, &LEtot, min_band, max_band, Bin_E, band_energies, Q_inp_dmx, Qout ); + MVR2R_WORD32( lf_E, lf_E + VOIC_BINS, VOIC_BINS ); + MVR2R_WORD32( Bin_E, Bin_E + ( L_FFT / 2 ), L_FFT / 2 ); + MVR2R_WORD32( band_energies, band_energies + NB_BANDS, NB_BANDS ); + MVR2R_WORD32( pt_bands, pt_bands + NB_BANDS, NB_BANDS ); + LEtot = L_shl( LEtot, 1 ); + } + Word32 temp32_log; + temp32_log = L_add( BASOP_Util_Log2( L_shr( LEtot, 1 ) ), L_shl( sub( Q31, add( Q_new, QSCALE - Q2 ) ), Q25 ) ); + temp32_log = Mpy_32_32( temp32_log, 1616142483 ); // log10(x) = log2(x)/log2(10) + /* 10.0 * log10( (float) tmp )*/ + /* 10.0/log2(10) in Q29 = 1616142483*/ + *Etot = extract_l( L_shr( temp32_log, 23 - 8 ) ); // Q8 + + Bin_E[L_FFT / 2 - 1] = Bin_E[L_FFT / 2 - 2]; + move32(); + Bin_E[L_FFT - 1] = Bin_E[L_FFT - 2]; + move32(); + + /* Per-bin log-energy spectrum */ + + FOR( i = 0; i < L_FFT / 2; i++ ) + { + Bin_E_old[i] = Bin_E[i]; + move32(); + /* tmp = (input[i] + input[i+Len]+0.001f)/2.0f */ + Ltmp = L_max( L_shr( 21474, sub( Q31, add( Q_new, QSCALE ) ) ), L_add( L_shr( Bin_E[i], 1 ), L_shr( Bin_E[i + L_FFT / 2], 1 ) ) ); + if ( PS != NULL ) + { + PS[i] = Ltmp; + move32(); + } + if ( EspecdB != NULL ) + { + temp32_log = L_add( BASOP_Util_Log2( Ltmp ), L_shl( sub( Q31, Q_new + QSCALE ), Q25 ) ); + EspecdB[i] = extract_l( L_shr( Mpy_32_32( temp32_log, 1860652798 ), Q22 - Q7 ) ); /*log(x) = log2(x)*logf(2)*/ + /* 10.0*log((float)tmp) */ + /* 10.0*logf(2) in Q28 = 1860652798 */ + + move16(); + } + } + + + return; +} +#endif + /*------------------------------------------------------------------------* * find_enr() * @@ -226,6 +584,7 @@ static void find_enr( Word32 *tmpptr; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move16(); #endif @@ -436,6 +795,250 @@ static void find_enr( return; } +#ifdef IVAS_FLOAT_FIXED1 +/*------------------------------------------------------------------------* + * ivas_find_enr() + * + * find input signal energy for each critical band and first 74 LF bins + * The energy is normalized by the number of frequency bins in a channel + *------------------------------------------------------------------------*/ + +static void ivas_find_enr( + Word16 data[], /* i : fft result */ + Word32 band[], /* o : per band energy Q_new + QSCALE */ + Word32 *ptE, /* o : per bin energy for low frequencies Q_new + QSCALE-2 */ + Word32 *LEtot, /* o : total energy Q_new + QSCALE */ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word16 Q_new2, /* i : scaling factor Q0 */ + const Word32 e_min, /* i : minimum energy scaled Q_new + QSCALE */ + Word32 *Bin_E, /* o : Per bin energy Q_new + QSCALE-2 */ + Word16 BIN_FREQ_FX, /* i : Number of frequency bins */ + Word32 *band_energies /* o : per band energy without MODE2_E_MIN */ +) +{ + Word16 i, cnt, shift_to_norm; + Word16 freq, wtmp; + Word16 *ptR, *ptI, diff_scaleP1, diff_scaleM2; + Word16 exp_band; + Word32 Ltmp, Ltmp1; + Word16 voic_band; + Word32 etot; + Word16 exp_etot; + Word32 *tmpptr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + ptR = &data[1]; /* first real */ + ptI = &data[L_FFT - 1]; /* first imaginary */ + + /*-----------------------------------------------------------------------------------* + * Scaling needed by band and ptE output + * Wants all energies scaled by Q_new + QSCALE to maintain maximum + * precision on bckr noise in clean speech + * First shift left by Q_new + QSCALE than shift right by 2*Q_new-1 + * shift left (Q_new + QSCALE - (2*Q_new -1)) + * shift left (QSCALE - Q_new + 1) == shift left by (QSCALE+1) - Q_new + *-----------------------------------------------------------------------------------*/ + + diff_scaleP1 = sub( QSCALE + 1 + 1, Q_new2 ); + diff_scaleM2 = sub( QSCALE + 1 - 2, Q_new2 ); + + voic_band = VOIC_BAND_8k; + move16(); + assert( VOIC_BAND == VOIC_BAND_8k ); + + etot = L_deposit_l( 0 ); + exp_etot = 0; + move16(); + + /*-----------------------------------------------------------------* + * For low frequency bins, save per bin energy for the use + * in NS and find_tilt() + *-----------------------------------------------------------------*/ + + freq = BIN_FREQ_FX; + move16(); + FOR( i = 0; i < voic_band; i++ ) /* up to maximum allowed voiced critical band */ + { + tmpptr = Bin_E; + move16(); + Ltmp1 = L_deposit_l( 0 ); + + FOR( ; freq <= crit_bands[i]; freq += BIN_FREQ_FX ) + { + /*ptE = *ptR * *ptR + *ptI * *ptI */ /* energy */ + Ltmp = L_mult( *ptI, *ptI ); + Ltmp = L_mac( Ltmp, *ptR, *ptR ); + + /* *ptE *= 4.0 / (L_FFT*L_FFT) */ + /* normalization - corresponds to FFT normalization by 2/L_FFT */ + BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */ +#ifdef BASOP_NOGLOB + *ptE = L_shl_o( Ltmp, diff_scaleM2, &Overflow ); +#else /* BASOP_NOGLOB */ + *ptE = L_shl( Ltmp, diff_scaleM2 ); +#endif /* BASOP_NOGLOB */ + move32(); /* scaled by Q_new + QSCALE - 2 */ + BASOP_SATURATE_WARNING_ON_EVS; + /*band[i] += *ptE++;*/ + *Bin_E = *ptE; + move32(); + Bin_E++; + Ltmp1 = L_add_sat( Ltmp1, Ltmp ); + + ptE++; + ptR++; + ptI--; + } + + exp_band = sub( norm_l( Ltmp1 ), 1 ); /* divide by 2 to ensure band < cnt */ + wtmp = round_fx( L_shl( Ltmp1, exp_band ) ); + + /* band[i] /= cnt */ /* normalization per frequency bin */ + cnt = (Word16) ( Bin_E - tmpptr ); + shift_to_norm = norm_s( cnt ); + wtmp = div_s( wtmp, shl( cnt, shift_to_norm ) ); + Ltmp1 = L_deposit_l( wtmp ); + + exp_band = sub( exp_band, shift_to_norm ); + exp_band = sub( diff_scaleP1, exp_band ); + BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */ +#ifdef BASOP_NOGLOB + band[i] = L_shl_o( Ltmp1, exp_band, &Overflow ); +#else /* BASOP_NOGLOB */ + band[i] = L_shl( Ltmp1, exp_band ); +#endif /* BASOP_NOGLOB */ + move32(); /* band scaled by Q_new + QSCALE */ + BASOP_SATURATE_WARNING_ON_EVS; + + test(); + IF( GE_16( i, min_band ) && LE_16( i, max_band ) ) + { + IF( LT_32( band[i], e_min ) ) + { + Ltmp1 = L_shl( e_min, 0 ); + exp_band = 0; + move16(); + } + + wtmp = sub( exp_band, exp_etot ); + if ( wtmp > 0 ) + { + etot = L_shr( etot, wtmp ); + } + exp_etot = s_max( exp_etot, exp_band ); + etot = L_add( etot, L_shl( Ltmp1, sub( exp_band, exp_etot ) ) ); + } + + band_energies[i] = band[i]; + move32(); + + band[i] = L_max( band[i], e_min ); + move32(); + } + + IF( EQ_16( BIN_FREQ_FX, 50 ) ) + { + /*-----------------------------------------------------------------* + * Continue compute the E per critical band for high frequencies + *-----------------------------------------------------------------*/ + + FOR( i = voic_band; i < NB_BANDS; i++ ) + { + tmpptr = Bin_E; + move16(); + Ltmp1 = L_deposit_l( 0 ); + + FOR( ; freq <= crit_bands[i]; freq += BIN_FREQ_FX ) + { + /* *ptE = *ptR * *ptR + *ptI * *ptI */ + Ltmp = L_mult( *ptI, *ptI ); + Ltmp = L_mac_sat( Ltmp, *ptR, *ptR ); + + /* *ptE *= 4.0 / (L_FFT*L_FFT) */ + /* normalization - corresponds to FFT normalization by 2/L_FFT */ + BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */ +#ifdef BASOP_NOGLOB + *Bin_E = L_shl_o( Ltmp, diff_scaleM2, &Overflow ); +#else /* BASOP_NOGLOB */ + *Bin_E = L_shl( Ltmp, diff_scaleM2 ); +#endif /* BASOP_NOGLOB */ + move32(); /* scaled by Q_new + QSCALE - 2 */ + BASOP_SATURATE_WARNING_ON_EVS; + Bin_E++; + Ltmp1 = L_add_sat( Ltmp1, Ltmp ); + + ptR++; + ptI--; + } + + exp_band = sub( norm_l( Ltmp1 ), 1 ); /* divide by 2 to ensure band < cnt */ + wtmp = round_fx( L_shl( Ltmp1, exp_band ) ); + + /* band[i] /= cnt */ /* normalization per frequency bin */ + cnt = (Word16) ( Bin_E - tmpptr ); + shift_to_norm = norm_s( cnt ); + wtmp = div_s( wtmp, shl( cnt, shift_to_norm ) ); + Ltmp1 = L_deposit_l( wtmp ); + + exp_band = sub( exp_band, shift_to_norm ); + exp_band = sub( diff_scaleP1, exp_band ); + BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */ +#ifdef BASOP_NOGLOB + band[i] = L_shl_o( Ltmp1, exp_band, &Overflow ); +#else /* BASOP_NOGLOB */ + band[i] = L_shl( Ltmp1, exp_band ); +#endif + move32(); /* band scaled by Q_new + QSCALE */ + BASOP_SATURATE_WARNING_ON_EVS; + + test(); + IF( GE_16( i, min_band ) && LE_16( i, max_band ) ) + { + IF( LT_32( band[i], e_min ) ) + { + Ltmp1 = L_shl( e_min, 0 ); + exp_band = 0; + move16(); + } + + wtmp = sub( exp_band, exp_etot ); + if ( wtmp > 0 ) + { + etot = L_shr( etot, wtmp ); + } + exp_etot = s_max( exp_etot, exp_band ); + + etot = L_add( etot, L_shl( Ltmp1, sub( exp_band, exp_etot ) ) ); + } + + band_energies[i] = band[i]; + move32(); + + band[i] = L_max( band[i], e_min ); + move32(); + } + } + + /*-----------------------------------------------------------------* + * Find the total energy over the input bandwidth + *-----------------------------------------------------------------*/ + +#ifdef BASOP_NOGLOB + etot = L_add_sat( *LEtot, L_shl_sat( etot, sub( exp_etot, 4 ) ) ); +#else + etot = L_add( *LEtot, L_shl( etot, sub( exp_etot, 4 ) ) ); +#endif + *LEtot = etot; + move32(); + + + return; +} +#endif #ifdef IVAS_CODE_CPE /*------------------------------------------------------------------------* * find_enr_dft() diff --git a/lib_enc/arith_coder_enc.c b/lib_enc/arith_coder_enc.c index a2517f99fa6fe529a1ae619f392bb541a6bff6a4..21d36d21727a036ac45c587a0950936414cd6270 100644 --- a/lib_enc/arith_coder_enc.c +++ b/lib_enc/arith_coder_enc.c @@ -66,6 +66,7 @@ typedef struct Heap } Heap; +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * tcx_arith_estimate_scale() * @@ -683,3 +684,4 @@ void tcx_arith_encode_envelope( return; } +#endif diff --git a/lib_enc/cng_enc.c b/lib_enc/cng_enc.c index 40e488c4ffda29361be00c249f6ceaa992299a59..571fc35494de65cb9b181485c4a7ee75a0ef34a5 100644 --- a/lib_enc/cng_enc.c +++ b/lib_enc/cng_enc.c @@ -43,6 +43,12 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#include "ivas_rom_com_fx.h" +#endif + /*---------------------------------------------------------------------* * Local constants *---------------------------------------------------------------------*/ @@ -54,11 +60,18 @@ * Local function prototypes *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static int16_t shb_DTX( Encoder_State *st, const float *shb_speech, const float *syn_12k8_16k ); static void shb_CNG_encod( Encoder_State *st, const int16_t update ); +#else +static Word16 shb_DTX_ivas_fx( Encoder_State *st, const Word16 *shb_speech_fx, const Word16 *syn_12k8_16k_fx ); + +static void shb_CNG_encod_ivas_fx( Encoder_State *st, const Word16 update ); +#endif +#ifndef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * CNG_enc() * @@ -893,6 +906,53 @@ void swb_CNG_enc( return; } +#endif + +#ifdef IVAS_FLOAT_FIXED +void swb_CNG_enc_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q0 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz Q0 */ +) +{ + Word16 shb_SID_updt; + + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) + { + IF( st->cng_type == LP_CNG ) + { + test(); + IF( GE_32( st->input_Fs, L_FRAME32k * FRAMES_PER_SEC ) ) + { + /* decide if SHB SID encoding or not */ + shb_SID_updt = shb_DTX_ivas_fx( st, shb_speech_fx, syn_12k8_16k_fx ); + + /* SHB CNG encoding */ + shb_CNG_encod_ivas_fx( st, shb_SID_updt ); + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && EQ_32( st->core_brate, SID_2k40 ) ) + { + /* LF-boost not used in DFT-stereo, instead the bandwidth is transmitted */ + delete_indice( st->hBstr, IND_CNG_ENV1 ); + push_indice( st->hBstr, IND_BWIDTH, st->bwidth, 2 ); + push_indice( st->hBstr, IND_UNUSED, 0, 4 ); + push_indice( st->hBstr, IND_SID_BW, 1, 1 ); + } + } + st->hTdCngEnc->last_vad = 0; + move16(); + } + ELSE + { + st->hTdCngEnc->last_vad = 1; + move16(); + } + + return; +} + +#endif /*---------------------------------------------------------------------* * shb_CNG_encod() @@ -900,6 +960,7 @@ void swb_CNG_enc( * SID parameters encoding for SHB signal *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void shb_CNG_encod( Encoder_State *st, /* i/o: State structure */ const int16_t update /* i : SID update flag */ @@ -974,7 +1035,121 @@ static void shb_CNG_encod( return; } +#else +static void shb_CNG_encod_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 update /* i : SID update flag */ +) +{ + Word16 idx_ener = 0; + move16(); + BSTR_ENC_HANDLE hBstr = st->hBstr; + Word16 ener_mid_dec_thr_fx; + + IF( EQ_16( update, 1 ) ) + { + IF( st->element_mode == EVS_MONO ) + { + /* 6.0 in Q8 -> 1510 */ + /* 0.9 in Q15 29491 */ + /* ( 1 / log10(2.0) ) * 0.1 in Q15 ->10886 */ + idx_ener = shr( mult( add( mult( st->hTdCngEnc->mov_shb_cng_ener_fx, 10886 ), 1510 ), 29491 ), 8 ); /* Q0 */ + } + ELSE + { + /*idx_ener = (int16_t)(0.7f * (0.1f * st->hTdCngEnc->mov_shb_cng_ener / (float)log10(2.0f) + 6.0f) + 0.5f);*/ + // PMT("shb_CNG_encod_fx quantization in missing") + /* 6.0 in Q8 -> 1510 */ + /* 0.7 in Q15 22938 */ + /* ( 1 / log10(2.0) ) * 0.1 in Q15 -> 10886 */ + idx_ener = shr( mult( add( mult( st->hTdCngEnc->mov_shb_cng_ener_fx, 10886 ), 1510 ), 22938 ), 8 ); /* Q0 */ + } + + + if ( LT_16( st->bwidth, SWB ) ) + { + idx_ener = 0; + move16(); + } + + IF( GT_16( idx_ener, 15 ) ) + { + idx_ener = 15; + move16(); + } + ELSE IF( idx_ener < 0 ) + { + idx_ener = 0; + move16(); + } + + /* prevent toggling of idx_ener by adding small dead-zone interval around decision thresholds */ + IF( st->element_mode != EVS_MONO ) + { + IF( EQ_16( abs_s( sub( idx_ener, st->hTdCngEnc->last_idx_ener ) ), 1 ) ) + { + + Word16 tmp, tmp1, tmp2, scale, exp1, exp2, ener_mid_dec_thr_e; + tmp = BASOP_Util_Divide1616_Scale( st->hTdCngEnc->last_idx_ener, 22938, &scale ); // 0.7 in Q15 ->exp 0 + scale = scale + ( 15 - 0 ); + tmp = sub( tmp, shl( 6, sub( Q15, scale ) ) ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, 3277, &exp1 ); + exp1 = exp1 + ( scale - 0 ); + + ener_mid_dec_thr_fx = shr( mult( tmp1, 9864 ), 1 ); // exp = exp + + tmp = BASOP_Util_Divide1616_Scale( idx_ener, 22938, &scale ); // 0.7 in Q15 ->exp 0 + scale = add( scale, ( 15 - 0 ) ); + tmp = sub( tmp, shl( 6, sub( Q15, scale ) ) ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, 3277, &exp2 ); + exp2 = add( exp2, ( scale - 0 ) ); + + tmp2 = shr( mult( tmp1, 9864 ), 1 ); // exp = exp + + ener_mid_dec_thr_e = BASOP_Util_Add_MantExp( tmp2, exp2, ener_mid_dec_thr_fx, exp1, &ener_mid_dec_thr_fx ); + + + scale = BASOP_Util_Add_MantExp( st->hTdCngEnc->mov_shb_cng_ener_fx, 7, negate( ener_mid_dec_thr_fx ), ener_mid_dec_thr_e, &tmp ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, ener_mid_dec_thr_fx, &exp1 ); + exp1 = add( exp1, sub( scale, ener_mid_dec_thr_e ) ); + IF( LT_16( abs_s( tmp1 ), shr( 328, sub( 15, exp1 ) ) ) ) + { + idx_ener = st->hTdCngEnc->last_idx_ener; + move16(); + } + } + } + + st->hTdCngEnc->last_idx_ener = idx_ener; + move16(); + + push_indice( hBstr, IND_SHB_CNG_GAIN, idx_ener, 4 ); + push_indice( hBstr, IND_SID_BW, 1, 1 ); + delete_indice( hBstr, IND_CNG_ENV1 ); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + push_indice( st->hBstr, IND_BWIDTH, st->bwidth, 2 ); + } + ELSE + { + push_indice( hBstr, IND_UNUSED, 0, 2 ); + } + st->hTdCngEnc->ho_sid_bw = L_shl( L_and( st->hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + st->hTdCngEnc->ho_sid_bw = L_or( st->hTdCngEnc->ho_sid_bw, 0x1L ); + move32(); + move32(); + } + ELSE IF( EQ_32( st->core_brate, SID_2k40 ) ) + { + st->hTdCngEnc->ho_sid_bw = L_shl( L_and( st->hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + move32(); + push_indice( hBstr, IND_SID_BW, 0, 1 ); + } + + return; +} +#endif /*---------------------------------------------------------------------* * shb_DTX() @@ -982,6 +1157,7 @@ static void shb_CNG_encod( * Decide if encoding SHB SID or not *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static int16_t shb_DTX( Encoder_State *st, /* i/o: State structure */ const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ @@ -1112,7 +1288,221 @@ static int16_t shb_DTX( return ( update ); } +#else +static Word16 shb_DTX_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q0 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz Q0 */ +) +{ + Word16 i; + Word16 update; + + Word16 allow_cn_step = 0; + move16(); + Word16 shb_old_speech_fx[( ACELP_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 4]; + Word16 *shb_new_speech_fx; + Word32 wb_ener_fx; + Word32 shb_ener_fx; + Word16 log_wb_ener_fx; + Word16 log_shb_ener_fx; + Word16 tmp; + Word16 exp; + Word16 fra; + Word16 att_fx; /*Q8*/ + + TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; + + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); +#endif + + shb_new_speech_fx = shb_old_speech_fx + ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4; + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4 ); // old_speech_shb_fx -> Q0 + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); // Q0 + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4 ); // Q0 + + shb_ener_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME16k; i++ ) + { +#ifdef BASOP_NOGLOB + shb_ener_fx = L_mac_sat( shb_ener_fx, shb_old_speech_fx[i], shb_old_speech_fx[i] ); // ( Q0 + Q0 + Q1 ) --> Q1 due to left shift in L_mac +#else + shb_ener_fx = L_mac( shb_ener_fx, shb_old_speech_fx[i], shb_old_speech_fx[i] ); +#endif + } + + shb_ener_fx = L_add( Mpy_32_16_1( shb_ener_fx, 102 ), 1 ); /* ( 1 / L_FRAME16K ) -> 102 in Q15, shb_ener_fx in Q1 */ + + wb_ener_fx = L_deposit_l( 0 ); + FOR( i = 0; i < st->L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + wb_ener_fx = L_mac_o( wb_ener_fx, syn_12k8_16k_fx[i], syn_12k8_16k_fx[i], &Overflow ); // ( Q0 + Q0 + Q1 ) --> Q1 due to left shift in L_mac +#else + wb_ener_fx = L_mac( wb_ener_fx, syn_12k8_16k[i], syn_12k8_16k[i] ); +#endif + } + + wb_ener_fx = L_add( Mpy_32_16_1( wb_ener_fx, 128 ), 1 ); /* 128 in Q15, wb_ener_fx in Q1 */ + + exp = norm_l( wb_ener_fx ); + fra = Log2_norm_lc( L_shl( wb_ener_fx, exp ) ); + exp = sub( 30 - 1, exp ); + wb_ener_fx = Mpy_32_16( exp, fra, LG10 ); + +#ifdef BASOP_NOGLOB + log_wb_ener_fx = round_fx_o( L_shl_o( wb_ener_fx, 10, &Overflow ), &Overflow ); /* log_wb_ener_fx in Q8 */ +#else + log_wb_ener_fx = round_fx( L_shl( wb_ener_fx, 10 ) ); /* log_wb_ener_fx in Q8 */ +#endif + exp = norm_l( shb_ener_fx ); + fra = Log2_norm_lc( L_shl( shb_ener_fx, exp ) ); + exp = sub( 30 - 1, exp ); + shb_ener_fx = Mpy_32_16( exp, fra, LG10 ); + + + test(); + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + Word32 att_fx32 = 0; + move32(); + Word16 index; + + apply_scale_ivas_fx( &att_fx32, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO, &index ); // Q23; + + att_fx = extract_l( L_shr( att_fx32, 15 ) ); // Q8 + } + ELSE + { + att_fx = -1664; // Q8 + move16(); + } + + +#ifdef BASOP_NOGLOB + log_shb_ener_fx = sub_o( round_fx_o( L_shl_o( shb_ener_fx, 10, &Overflow ), &Overflow ), att_fx, &Overflow ); /* log_shb_ener_fx in Q8 */ +#else + log_shb_ener_fx = sub( round_fx( L_shl( shb_ener_fx, 10 ) ), att_fx ); /* log_shb_ener_fx in Q8 */ +#endif + + IF( st->hDtxEnc->first_CNG == 0 ) + { + + + hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx; // Q8 + hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx; // Q8 + hTdCngEnc->last_wb_cng_ener_fx = log_wb_ener_fx; // Q8 + hTdCngEnc->last_shb_cng_ener_fx = log_shb_ener_fx; // Q8 + move16(); + move16(); + move16(); + move16(); + } + IF( GT_16( abs_s( sub( log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx ) ), 3072 ) ) // 12 in Q8 + { + allow_cn_step = 1; + move16(); + } + + /* Also allow step if shb energy has dropped 12 dB */ + test(); + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GT_16( sub( hTdCngEnc->mov_shb_cng_ener_fx, log_shb_ener_fx ), 3072 ) ) + { + allow_cn_step = 1; + move16(); + } + + IF( EQ_16( allow_cn_step, 1 ) ) + { + hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx; + hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx; + } + ELSE + { + tmp = sub( log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx ); /* Q8 */ + tmp = mult( tmp, 29491 ); /* Q8 */ + hTdCngEnc->mov_wb_cng_ener_fx = add( hTdCngEnc->mov_wb_cng_ener_fx, tmp ); /* Q8 */ + + tmp = sub( log_shb_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx ); + tmp = mult( tmp, 8192 ); /* Q8 */ + hTdCngEnc->mov_shb_cng_ener_fx = add( hTdCngEnc->mov_shb_cng_ener_fx, tmp ); /* Q8 */ + } + + hTdCngEnc->shb_NO_DATA_cnt = add( hTdCngEnc->shb_NO_DATA_cnt, 1 ); + update = 0; + + move16(); + move16(); + + test(); + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) ) + { + IF( st->hDtxEnc->first_CNG == 0 ) + { + update = 1; + move16(); + } + ELSE IF( hTdCngEnc->shb_cng_ini_cnt > 0 ) + { + hTdCngEnc->shb_cng_ini_cnt = sub( hTdCngEnc->shb_cng_ini_cnt, 1 ); + update = 1; + move16(); + move16(); + } + ELSE IF( EQ_16( hTdCngEnc->last_vad, 1 ) ) + { + update = 1; + move16(); + } + ELSE IF( GE_16( hTdCngEnc->shb_NO_DATA_cnt, 100 ) ) + { + update = 1; + move16(); + } + ELSE IF( GT_16( abs_s( sub( sub( hTdCngEnc->mov_wb_cng_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx ), sub( hTdCngEnc->last_wb_cng_ener_fx, hTdCngEnc->last_shb_cng_ener_fx ) ) ), 768 ) ) + { + update = 1; + move16(); + } + ELSE IF( ( GE_16( st->bwidth, SWB ) && LT_16( hTdCngEnc->last_SID_bwidth, SWB ) ) || ( LT_16( st->bwidth, SWB ) && GE_16( hTdCngEnc->last_SID_bwidth, SWB ) ) ) + { + update = 1; + move16(); + } + hTdCngEnc->last_SID_bwidth = st->bwidth; + move16(); + } + + /* LF-boost not yet implemented in decoder which means that the specific wb_sid information is not used */ + test(); + test(); + if ( ( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && EQ_32( st->core_brate, SID_2k40 ) ) + { + update = 1; + move16(); + } + + IF( EQ_16( update, 1 ) ) + { + hTdCngEnc->last_wb_cng_ener_fx = hTdCngEnc->mov_wb_cng_ener_fx; + hTdCngEnc->last_shb_cng_ener_fx = hTdCngEnc->mov_shb_cng_ener_fx; + hTdCngEnc->shb_NO_DATA_cnt = 0; + move16(); + move16(); + move16(); + } + + test(); + return ( update ); +} +#endif /*---------------------------------------------------------------------* * calculate_hangover_attenuation_gain() diff --git a/lib_enc/cng_enc_fx.c b/lib_enc/cng_enc_fx.c index c3f7e789339a6b93c9092545024ecde6c2c454e5..aaede46bec27bdabf9d16517a6d488cefe3108e8 100644 --- a/lib_enc/cng_enc_fx.c +++ b/lib_enc/cng_enc_fx.c @@ -7,6 +7,9 @@ #include "rom_enc.h" /* Encoder static table prototypes */ #include "rom_com.h" /* Static table prototypes */ //#include "prot_fx.h" /* Function prototypes */ +#ifdef IVAS_FLOAT_FIXED +#include "prot.h" /* Function prototypes */ +#endif #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ //#include "basop_mpy.h" @@ -16,26 +19,1193 @@ * Local constants *---------------------------------------------------------------------*/ -#define MAX_DELTA 1 -#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */ -#define INT_H 50 -#define INT_L 8 +#define MAX_DELTA 1 +#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */ +#define INT_H 50 +#define INT_L 8 + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ +static void shb_CNG_encod_fx( Encoder_State *st_fx, const Word16 update_fx ); +static Word16 shb_DTX_fx( Encoder_State *st_fx, const Word16 *shb_speech_fx, const Word16 *syn_12k8_16k ); +/*---------------------------------------------------------------------* + * CNG_enc() + * + * Confort noise generation for the coder + *---------------------------------------------------------------------*/ +void CNG_enc_fx( + Encoder_State *st_fx, /* i/o: State structure */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */ + Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */ + const Word16 *lsp_mid, /* i : mid frame LSPs Q15 */ + Word16 *lsp_new, /* i/o: current frame ISPs Q15 */ + Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */ + Word16 *allow_cn_step, /* o : allow CN step Q0 */ + Word16 Q_new, /* i : Q value of speech */ + Word32 *q_env, + Word16 *sid_bw ) +{ + Word16 enr_index; + Word16 i, j, ptr; + Word16 m1; + Word16 res[L_FRAME16k]; + Word16 step_inv = 0; + Word16 hi, lo; + Word16 maxl = 0; + Word16 num_bits = 0; + Word16 step = 0; + Word16 *pt_res; + const Word16 *pt_sp; + Word16 enr; + Word32 L_tmp, L_ener; + Word16 k, tmp1; + Word16 weights; + Word16 sp_enr; + Word32 L_tmp1; + Word16 exp; + Word16 m = 0; + Word16 tmp[HO_HIST_SIZE * M]; + Word16 ll, s_ptr; + Word16 tmpv, maxv, scale, att = 1; + Word16 lsf_tmp[M]; + Word32 C[M]; + Word32 max_val[2]; + Word16 max_idx[2]; + Word16 ftmp_fx; + Word16 lsp_tmp[M]; + Word16 dev; + Word16 max_dev; + Word16 dist; + Word16 max_idx1[2] = { 0, 0 }; + Word16 fft_io[L_FRAME16k]; + Word16 *ptR, *ptI; + Word32 enr1 = 0; + Word32 env[NUM_ENV_CNG]; + Word32 min1; + Word16 min1_idx; + Word32 d; + Word16 res1[L_FRAME16k]; + Word32 tmp_env[HO_HIST_SIZE * NUM_ENV_CNG]; + Word16 fra; + Word16 temp_lo_fx, temp_hi_fx; + Word16 exp_pow; + Word16 force_cn_step = 0; + Word16 tmp_loop; + Word16 st_lp_sp_enr; + DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc; + TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + st_lp_sp_enr = hTdCngEnc->lp_sp_enr_fx; + Word16 lp_ener_thr_scale; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + /* Temp variables for floating point functions */ + + lp_ener_thr_scale = 8; /* 4.0f*/ /*IVAS_CODE Q2 */ + move16(); + if ( NE_16( st_fx->element_mode, EVS_MONO ) ) + { + lp_ener_thr_scale = 7; /* 3.5f;*/ + move16(); + } + /*sp_enr = (float) log10( sum2_f( speech, L_frame )/L_frame + 0.1f )/ (float)log10(2.0f);*/ /*9.1 */ + pt_sp = speech; + L_ener = L_deposit_l( 1 ); + /* L_ener = L_add(L_shr(sum2_f_fx( speech, L_frame ), 8) , L_ener);*/ + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + FOR( j = 0; j < 128; j++ ) + { + L_tmp = L_mult0( *pt_sp, *pt_sp ); + pt_sp++; + L_tmp = L_mac0( L_tmp, *pt_sp, *pt_sp ); + pt_sp++; + L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*Q_new + 1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 80; j++ ) + { + L_tmp = L_mult0( *pt_sp, *pt_sp ); + pt_sp++; + L_tmp = L_mac0( L_tmp, *pt_sp, *pt_sp ); + pt_sp++; + L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*Q_new + 1, divide by L_frame done here */ + } + } + } + + hi = norm_l( L_ener ); + lo = Log2_norm_lc( L_shl( L_ener, hi ) ); + hi = sub( 29, hi ); /* log2 exp in Q2*Q_new */ + hi = sub( hi, shl( Q_new, 1 ) ); /* Q0 */ + L_tmp = L_Comp( hi, lo ); /* Q16 */ + sp_enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ + + if ( sp_enr < 0 ) + { + sp_enr = 0; + move16(); + } + test(); + IF( hDtxEnc->first_CNG == 0 || hTdCngEnc->old_enr_index < 0 ) + { + hTdCngEnc->lp_sp_enr_fx = sp_enr; + move16(); /* Q8 */ + } + ELSE + { + test(); + test(); + test(); + test(); + IF( GT_32( st_fx->last_core_brate, SID_2k40 ) && ( EQ_16( st_fx->last_core, HQ_CORE ) || st_fx->hTdCngEnc->burst_ho_cnt > 0 ) && LT_16( hTdCngEnc->lp_sp_enr_fx, 1536 ) && + GT_16( sub( sp_enr, hTdCngEnc->lp_sp_enr_fx ), 1024 ) && GT_16( sp_enr, 1536 ) ) + { + hTdCngEnc->lp_sp_enr_fx = sp_enr; + move16(); + force_cn_step = 1; + move16(); + } + ELSE + { + hTdCngEnc->lp_sp_enr_fx = round_fx( L_mac( L_mult( 29491 /* 0.9, Q15 */, hTdCngEnc->lp_sp_enr_fx ), 3277 /* 0.1, Q15 */, sp_enr ) ); /* Q8 (8+15+1-16) */ + } + } + /* update the pointer to circular buffer of old LSP vectors */ + hTdCngEnc->cng_hist_ptr = add( hTdCngEnc->cng_hist_ptr, 1 ); + if ( EQ_16( hTdCngEnc->cng_hist_ptr, DTX_HIST_SIZE ) ) + { + hTdCngEnc->cng_hist_ptr = 0; + move16(); + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + Copy( lsp_new, &( hTdCngEnc->cng_lsp_hist_fx[( hTdCngEnc->cng_hist_ptr ) * M] ), M ); + + /*-----------------------------------------------------------------* + * Find CNG spectral envelope + * Find LSP median + *-----------------------------------------------------------------*/ + test(); + test(); + IF( ( EQ_32( st_fx->core_brate, SID_2k40 ) || EQ_32( st_fx->core_brate, SID_1k75 ) ) && GE_16( hDtxEnc->cng_cnt, sub( hDtxEnc->cng_hist_size, 1 ) ) ) + { + set32_fx( max_val, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i = 0; i < hDtxEnc->cng_hist_size; i++ ) + { + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + lsp2lsf_fx( &hTdCngEnc->cng_lsp_hist_fx[i * M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16(); /*QX2.56 */ + tmpv = sub( 16384, add( lsf_tmp[M - 1], ftmp_fx ) ); /*QX2.56 */ + L_tmp = L_mult0( tmpv, tmpv ); /*QX6.5536 */ + } + ELSE + { + lsp2lsf_fx( &hTdCngEnc->cng_lsp_hist_fx[i * M], lsf_tmp, M, INT_FS_16k ); + ftmp_fx = 1205; + move16(); /*QX2.56 */ + tmpv = sub( 20480, add( lsf_tmp[M - 1], ftmp_fx ) ); /*QX2.56 */ + L_tmp = L_mult0( tmpv, tmpv ); /*QX6.5536 */ + } + + tmpv = sub( lsf_tmp[0], ftmp_fx ); /*QX2.56 */ + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /*QX6.5536 */ + FOR( j = 0; j < M - 1; j++ ) + { + tmpv = sub( sub( lsf_tmp[j + 1], lsf_tmp[j] ), ftmp_fx ); /*QX2.56 */ + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /*QX6.5536 */ + } + + C[i] = Mpy_32_16_1( L_tmp, 1928 ); + move32(); /*QX6.5536 */ + + IF( GT_32( C[i], max_val[0] ) ) + { + max_val[1] = max_val[0]; + move32(); + max_idx[1] = max_idx[0]; + move16(); + max_val[0] = C[i]; + move32(); + max_idx[0] = i; + move16(); + } + ELSE IF( GT_32( C[i], max_val[1] ) ) + { + max_val[1] = C[i]; + move32(); + max_idx[1] = i; + move16(); + } + } + + FOR( i = 0; i < M; i++ ) + { + L_tmp = 0; + FOR( j = 0; j < hDtxEnc->cng_hist_size; j++ ) + { + L_tmp = L_add( L_tmp, L_deposit_l( hTdCngEnc->cng_lsp_hist_fx[j * M + i] ) ); /*Q15 */ + } + + L_tmp = L_sub( L_tmp, L_add( L_deposit_l( hTdCngEnc->cng_lsp_hist_fx[max_idx[0] * M + i] ), L_deposit_l( hTdCngEnc->cng_lsp_hist_fx[max_idx[1] * M + i] ) ) ); /*Q15 */ + tmpv = div_s( 1, sub( hDtxEnc->cng_hist_size, 2 ) ); /*Q15 */ + L_tmp = Mpy_32_16_1( L_tmp, tmpv ); /*Q15 */ + lsp_new[i] = extract_l( L_tmp ); /*Q15 */ + } + max_idx1[0] = max_idx[0]; + move16(); + max_idx1[1] = max_idx[1]; + move16(); + } + + /*-----------------------------------------------------------------* + * Quantize CNG spectral envelope (only in SID frame) + * Quantize the LSF vector + *-----------------------------------------------------------------*/ + *allow_cn_step = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( hDtxEnc->cng_cnt == 0 ) && + GT_16( hTdCngEnc->lp_sp_enr_fx, 1536 ) && + ( LT_16( add( st_lp_sp_enr, 1024 /* 4.0, Q8 */ ), sp_enr ) ) && + ( hDtxEnc->first_CNG != 0 ) && + ( hTdCngEnc->old_enr_index >= 0 ) && + ( GT_32( st_fx->last_core_brate, SID_2k40 ) ) ) || + EQ_16( force_cn_step, 1 ) ) + { + *allow_cn_step = 1; + move16(); + } + + /* Initialize the CNG spectral envelope in case of the very first CNG frame */ + IF( hDtxEnc->first_CNG == 0 ) + { + Copy( st_fx->lsp_old_fx, hDtxEnc->lspCNG_fx, M ); + + /* Average the CNG spectral envelope in case of the very first CNG frame */ + IF( NE_16( st_fx->element_mode, EVS_MONO ) ) + { + FOR( i = 0; i < M; i++ ) + { + /*lsp_new[i] = 0.5f * (lsp_mid[i] + lsp_new[i]);*/ + lsp_new[i] = mac_r( L_mult( lsp_mid[i], 16384 ), lsp_new[i], 16384 ); + move16(); + } + } + } + + + test(); + IF( EQ_32( st_fx->core_brate, SID_2k40 ) || EQ_32( st_fx->core_brate, SID_1k75 ) ) + { + /* LSF quantization */ + IF( st_fx->Opt_AMR_WB != 0 ) + { + isf_enc_amr_wb_fx( st_fx, lsf_new, lsp_new, 0 ); + } + ELSE + { +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + lsf_enc_fx( st_fx, lsf_new, lsp_new, NULL, NULL, 100, 0, 0, NULL, Q_new ); +#else + lsf_enc_fx( st_fx, lsf_new, lsp_new, NULL, NULL, 100, 0, 0, Q_new ); +#endif + } + /* Reset CNG history if CNG frame length is changed */ + test(); + test(); + if ( EQ_16( st_fx->bwidth, WB ) && hDtxEnc->first_CNG != 0 && NE_16( st_fx->L_frame, hDtxEnc->last_CNG_L_frame ) ) + { + hTdCngEnc->ho_hist_size = 0; + move16(); + } + } + ELSE + { + /* Use old LSP vector */ + Copy( st_fx->lsp_old_fx, lsp_new, M ); + Copy( st_fx->lsf_old_fx, lsf_new, M ); + } + + /*---------------------------------------------------------------------* + * CNG spectral envelope update + * Find A(z) coefficients + *---------------------------------------------------------------------*/ + + IF( LE_32( st_fx->last_core_brate, SID_2k40 ) ) + { + /* Reset hangover counter if not first SID period */ + if ( GT_32( st_fx->core_brate, FRAME_NO_DATA ) ) + { + hTdCngEnc->num_ho = 0; + move16(); + } + /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */ + test(); + IF( LT_16( hTdCngEnc->num_ho, 3 ) || LT_32( Mult_32_16( hTdCngEnc->Enew_fx, 21845 /*1/1.5f, Q15*/ ), hTdCngEnc->lp_ener_fx ) ) + { + FOR( i = 0; i < M; i++ ) + { + /* AR low-pass filter */ + hDtxEnc->lspCNG_fx[i] = mac_r( L_mult( CNG_ISF_FACT_FX, hDtxEnc->lspCNG_fx[i] ), 32768 - CNG_ISF_FACT_FX, lsp_new[i] ); + move16(); /* Q15 (15+15+1-16) */ + } + } + } + ELSE + { + /* Update CNG_mode if allowed */ + test(); + test(); + test(); + IF( EQ_16( st_fx->element_mode, EVS_MONO ) && ( ( st_fx->Opt_AMR_WB || EQ_16( st_fx->bwidth, WB ) ) && ( !hDtxEnc->first_CNG || GE_16( hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) ) ) + { + IF( GT_32( hDtxEnc->last_active_brate, ACELP_16k40 ) ) + { + hDtxEnc->CNG_mode = -1; + move16(); + } + ELSE + { + hDtxEnc->CNG_mode = get_cng_mode( hDtxEnc->last_active_brate ); + } + } + + /* If first sid after active burst update LSF history from circ buffer */ + hTdCngEnc->burst_ho_cnt = s_min( hTdCngEnc->burst_ho_cnt, hTdCngEnc->ho_circ_size ); + hTdCngEnc->act_cnt = 0; + move16(); + s_ptr = add( sub( hTdCngEnc->ho_circ_ptr, hTdCngEnc->burst_ho_cnt ), 1 ); + + if ( s_ptr < 0 ) + { + s_ptr = add( s_ptr, hTdCngEnc->ho_circ_size ); + } + + FOR( ll = hTdCngEnc->burst_ho_cnt; ll > 0; ll-- ) + { + hTdCngEnc->ho_hist_ptr = add( hTdCngEnc->ho_hist_ptr, 1 ); + if ( EQ_16( hTdCngEnc->ho_hist_ptr, HO_HIST_SIZE ) ) + { + hTdCngEnc->ho_hist_ptr = 0; + move16(); + } + + /* Conversion between 12.8k and 16k LSPs */ + test(); + test(); + IF( EQ_16( st_fx->L_frame, L_FRAME ) && EQ_16( hTdCngEnc->ho_16k_lsp[s_ptr], 1 ) ) + { + /* Conversion from 16k LPSs to 12k8 */ + lsp_convert_poly_fx( &( hTdCngEnc->ho_lsp_circ_fx[s_ptr * M] ), st_fx->L_frame, 0 ); + } + ELSE IF( EQ_16( st_fx->L_frame, L_FRAME16k ) && hTdCngEnc->ho_16k_lsp[s_ptr] == 0 ) + { + /* 16k LSPs already converted and stored, just copy to the other buffer */ + Copy( &( hTdCngEnc->ho_lsp_circ2_fx[s_ptr * M] ), &( hTdCngEnc->ho_lsp_circ_fx[s_ptr * M] ), M ); + } + /* update the circular buffers */ + Copy( &( hTdCngEnc->ho_lsp_circ_fx[s_ptr * M] ), &( hTdCngEnc->ho_lsp_hist_fx[hTdCngEnc->ho_hist_ptr * M] ), M ); + Copy32( &( hTdCngEnc->ho_ener_circ_fx[s_ptr] ), &( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] ), 1 ); + hTdCngEnc->ho_sid_bw = L_shl( L_and( hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + Copy32( &( hTdCngEnc->ho_env_circ_fx[s_ptr * NUM_ENV_CNG] ), &( hTdCngEnc->ho_env_hist_fx[hTdCngEnc->ho_hist_ptr * NUM_ENV_CNG] ), NUM_ENV_CNG ); + + hTdCngEnc->ho_hist_size = add( hTdCngEnc->ho_hist_size, 1 ); + if ( GT_16( hTdCngEnc->ho_hist_size, HO_HIST_SIZE ) ) + { + hTdCngEnc->ho_hist_size = HO_HIST_SIZE; + move16(); + } + + s_ptr = add( s_ptr, 1 ); + + if ( EQ_16( s_ptr, hTdCngEnc->ho_circ_size ) ) + { + s_ptr = 0; + move16(); + } + } + + IF( hTdCngEnc->burst_ho_cnt > 0 ) + { + /**allow_cn_step |= ( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] > 4 * hTdCngEnc->lp_ener_fx ); */ +#if 1 + /*allow_cn_step |= (hDtxEnc->first_CNG || st->element_mode == EVS_MONO) && (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener);*/ + /* (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener); */ + L_tmp1 = L_shr( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], 2 ); + IF( NE_16( lp_ener_thr_scale, 8 ) ) + { + L_tmp1 = L_add( L_tmp1, L_shr( hTdCngEnc->lp_ener_fx, 8 ) ); + } + L_tmp1 = L_sub( L_tmp1, hTdCngEnc->lp_ener_fx ); +#else + L_tmp1 = L_shr( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], 2 ); + L_tmp1 = L_sub( L_tmp1, hTdCngEnc->lp_ener_fx ); +#endif + test(); + test(); + IF( ( hDtxEnc->first_CNG > 0 || EQ_16( st_fx->element_mode, EVS_MONO ) ) && L_tmp1 > 0 ) + { + *allow_cn_step = s_or( *allow_cn_step, 1 ); + } + } + test(); + IF( *allow_cn_step == 0 && hTdCngEnc->ho_hist_size > 0 ) + { + /* Use average of energies below last energy */ + ptr = hTdCngEnc->ho_hist_ptr; + move16(); + Copy( &( hTdCngEnc->ho_lsp_hist_fx[ptr * M] ), tmp, M ); + m1 = 0; + move16(); + IF( L_and( hTdCngEnc->ho_sid_bw, (Word32) 0x1 ) == 0 ) + { + Copy32( &hTdCngEnc->ho_env_hist_fx[ptr * NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); + m1 = 1; + move16(); + } + L_enr = Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], W_DTX_HO_FX[0] ); /* Q6+15-15->Q6 */ + + weights = W_DTX_HO_FX[0]; /* Q15 */ + + m = 1; + move16(); + FOR( k = 1; k < hTdCngEnc->ho_hist_size; k++ ) + { + ptr = sub( ptr, 1 ); + if ( ptr < 0 ) + { + ptr = HO_HIST_SIZE - 1; + move16(); + } + + test(); + IF( LT_32( Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], ONE_OVER_BUF_H_NRG_FX ), hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] ) && + GT_32( hTdCngEnc->ho_ener_hist_fx[ptr], Mult_32_16( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], BUF_L_NRG_FX ) ) ) + { + /*enr += W_DTX_HO[k] * st_fx->ho_ener_hist[ptr]; */ + L_tmp1 = Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], W_DTX_HO_FX[k] ); /* Q6+15-15->Q6 */ + L_enr = L_add( L_enr, L_tmp1 ); /* Q6 */ + + /*weights += W_DTX_HO[k]; */ + weights = add( weights, W_DTX_HO_FX[k] ); /* Q15 */ + + Copy( &hTdCngEnc->ho_lsp_hist_fx[ptr * M], &tmp[m * M], M ); + IF( L_and( hTdCngEnc->ho_sid_bw, L_shl( (Word32) 0x1, k ) ) == 0 ) + { + Copy32( &hTdCngEnc->ho_env_hist_fx[ptr * NUM_ENV_CNG], &tmp_env[m1 * NUM_ENV_CNG], NUM_ENV_CNG ); + m1 = add( m1, 1 ); + } + m = add( m, 1 ); + } + } + + /*enr /= weights; */ + exp = norm_s( weights ); + tmp1 = div_s( shl( 1, sub( 14, exp ) ), weights ); /* Q(15+14-exp-15) */ + L_tmp1 = Mult_32_16( L_enr, tmp1 ); /* Q(14-exp+6-15)->Q(5-exp) */ + L_enr = L_shl( L_tmp1, add( exp, 1 ) ); /* Q6 */ + + hTdCngEnc->lp_ener_fx = L_enr; + move32(); /* Q6 */ + + set32_fx( max_val, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i = 0; i < m; i++ ) + { + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + lsp2lsf_fx( &tmp[i * M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16(); /*QX2.56 */ + tmpv = sub( 16384, add( lsf_tmp[M - 1], ftmp_fx ) ); /*QX2.56 */ + L_tmp = L_mult0( tmpv, tmpv ); /*QX6.5536 */ + } + ELSE + { + lsp2lsf_fx( &tmp[i * M], lsf_tmp, M, INT_FS_16k ); + ftmp_fx = 1205; + move16(); /*QX2.56 */ + tmpv = sub( 20480, add( lsf_tmp[M - 1], ftmp_fx ) ); /*QX2.56 */ + L_tmp = L_mult0( tmpv, tmpv ); /*QX6.5536 */ + } + + tmpv = sub( lsf_tmp[0], ftmp_fx ); /*QX2.56 */ + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /*QX6.5536 */ + FOR( j = 0; j < M - 1; j++ ) + { + tmpv = sub( sub( lsf_tmp[j + 1], lsf_tmp[j] ), ftmp_fx ); /*QX2.56 */ + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /*QX6.5536 */ + } + + C[i] = Mpy_32_16_1( L_tmp, 1928 ); + move32(); /*QX6.5536 */ + + IF( GT_32( C[i], max_val[0] ) ) + { + max_val[1] = max_val[0]; + move32(); + max_idx[1] = max_idx[0]; + move16(); + max_val[0] = C[i]; + move32(); + max_idx[0] = i; + move16(); + } + ELSE IF( GT_32( C[i], max_val[1] ) ) + { + max_val[1] = C[i]; + move32(); + max_idx[1] = i; + move16(); + } + } + + IF( EQ_16( m, 1 ) ) + { + Copy( tmp, lsp_tmp, M ); + } + ELSE IF( LT_16( m, 4 ) ) + { + FOR( i = 0; i < M; i++ ) + { + L_tmp = L_deposit_l( 0 ); + FOR( j = 0; j < m; j++ ) + { + L_tmp = L_add( L_tmp, L_deposit_l( tmp[j * M + i] ) ); + } + + L_tmp = L_sub( L_tmp, L_deposit_l( tmp[max_idx[0] * M + i] ) ); + tmpv = div_s( 1, sub( m, 1 ) ); /*Q15 */ + L_tmp = Mpy_32_16_1( L_tmp, tmpv ); /*Q15 */ + lsp_tmp[i] = extract_l( L_tmp ); /*Q15 */ + } + } + ELSE + { + FOR( i = 0; i < M; i++ ) + { + L_tmp = L_deposit_l( 0 ); + FOR( j = 0; j < m; j++ ) + { + L_tmp = L_add( L_tmp, L_deposit_l( tmp[j * M + i] ) ); + } + + L_tmp = L_sub( L_tmp, L_add( L_deposit_l( tmp[max_idx[0] * M + i] ), L_deposit_l( tmp[max_idx[1] * M + i] ) ) ); /*Q15 */ + tmpv = div_s( 1, sub( m, 2 ) ); /*Q15 */ + L_tmp = Mpy_32_16_1( L_tmp, tmpv ); /*Q15 */ + lsp_tmp[i] = extract_l( L_tmp ); /*Q15 */ + } + } + + dist = 0; /*Q15 */ + max_dev = 0; /*Q15 */ + FOR( i = 0; i < M; i++ ) + { + dev = abs_s( sub( lsp_tmp[i], lsp_new[i] ) ); /*Q15 */ +#ifdef BASOP_NOGLOB + dist = add_o( dist, dev, &Overflow ); /*Q15 */ +#else + dist = add( dist, dev ); /*Q15 */ +#endif + if ( GT_16( dev, max_dev ) ) + { + max_dev = dev; + move16(); + } + } + + test(); + IF( GT_16( dist, 13107 ) || GT_16( max_dev, 3277 ) ) + { + FOR( i = 0; i < M; i++ ) + { + hDtxEnc->lspCNG_fx[i] = lsp_tmp[i]; + move16(); /*Q15 */ + } + } + ELSE + { + FOR( i = 0; i < M; i++ ) + { + /* AR low-pass filter */ + hDtxEnc->lspCNG_fx[i] = add( mult_r( 26214, lsp_tmp[i] ), mult_r( 6554, lsp_new[i] ) ); + move16(); + } + } + IF( m1 > 0 ) + { + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + L_tmp = L_deposit_l( 0 ); + FOR( j = 0; j < m1; j++ ) + { + /* env[i] += tmp_env[j*NUM_ENV_CNG+i]; */ +#ifdef BASOP_NOGLOB + L_tmp = L_add_sat( L_tmp, tmp_env[j * NUM_ENV_CNG + i] ); +#else + L_tmp = L_add( L_tmp, tmp_env[j * NUM_ENV_CNG + i] ); +#endif + } + /* env[i] /= (float)m1; */ + /* env[i] = env[i] - 2*hTdCngEnc->lp_ener_fx; */ + IF( EQ_16( m1, 1 ) ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_sub_sat( L_tmp, L_add_sat( hTdCngEnc->lp_ener_fx, hTdCngEnc->lp_ener_fx ) ); +#else + L_tmp = L_sub( L_tmp, L_add( hTdCngEnc->lp_ener_fx, hTdCngEnc->lp_ener_fx ) ); +#endif + } + ELSE + { + tmp1 = div_s( 1, m1 ); + L_tmp = Mult_32_16( L_tmp, tmp1 ); +#ifdef BASOP_NOGLOB + L_tmp = L_sub_sat( L_tmp, L_add_sat( hTdCngEnc->lp_ener_fx, hTdCngEnc->lp_ener_fx ) ); +#else + L_tmp = L_sub( L_tmp, L_add( hTdCngEnc->lp_ener_fx, hTdCngEnc->lp_ener_fx ) ); +#endif + } + + env[i] = L_tmp; + move32(); + } + Copy32( env, hTdCngEnc->lp_env_fx, NUM_ENV_CNG ); + } + } + ELSE + { + Copy( lsp_new, hDtxEnc->lspCNG_fx, M ); /* use newly analyzed ISFs */ + } + } + IF( st_fx->Opt_AMR_WB != 0 ) + { + E_LPC_f_isp_a_conversion( hDtxEnc->lspCNG_fx, Aq, M ); + } + ELSE + { + E_LPC_f_lsp_a_conversion( hDtxEnc->lspCNG_fx, Aq, M ); /* Find A(z) (not interpolated) */ + } + + tmp_loop = shr( st_fx->L_frame, 6 ); + FOR( i = 1; i < tmp_loop; i++ ) + { + Copy( Aq, &Aq[i * ( M + 1 )], M + 1 ); + } + /*-----------------------------------------------------------------* + * Find residual signal + * Calculate residual signal energy per sample + *-----------------------------------------------------------------*/ + + /* calculate the residual signal */ + Residu3_fx( Aq, speech, res, st_fx->L_frame, 0 ); + Copy( res, res1, st_fx->L_frame ); + test(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) || EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + // PMT("Code to be completed") +#ifdef IVAS_CODE + att = powf( 10.0f, hTdCngEnc->CNG_att / 20.0f ); + v_multc( res1, att, res1, st->L_frame ); +#endif + } + ELSE IF( NE_16( st_fx->bwidth, NB ) ) + { + test(); + IF( EQ_16( st_fx->bwidth, WB ) && hDtxEnc->CNG_mode >= 0 ) + { + ftmp_fx = HO_ATT_FX[hDtxEnc->CNG_mode]; + } + ELSE + { + ftmp_fx = 19661; + move16(); + } + + att = mult( ftmp_fx, 5461 ); /* Q15 */ + L_tmp = L_mult( att, 8 ); /* Q16 */ + tmp1 = extract_l( L_shr( L_tmp, 2 ) ); /* Q14 */ + tmp1 = add( 16384, tmp1 ); + att = div_s( 16374, tmp1 ); /* Q15 */ + + att = s_max( att, ftmp_fx ); + FOR( i = 0; i < st_fx->L_frame; i++ ) + { + /*res1[i] *= att;*/ + res1[i] = mult( res1[i], att ); + move16(); /* Q_new */ + } + att = shr( att, 7 ); /* Q8 */ + } + + /* calculate the spectrum of residual signal */ + Copy( res1, fft_io, st_fx->L_frame ); + + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + Word16 Q_new_inp, mem_decim_size; // TO be removed + modify_Fs_fx( fft_io, L_FRAME16k, 16000, fft_io, 12800, hTdCngEnc->exc_mem2_fx, 0, &Q_new_inp, &mem_decim_size ); + } + + fft_rel_fx( fft_io, L_FFT, LOG2_L_FFT ); + ptR = &fft_io[1]; + ptI = &fft_io[L_FFT - 1]; + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + /* env[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */ +#ifdef BASOP_NOGLOB + L_tmp = L_mult_o( *ptR, *ptR, &Overflow ); /* 2*Q_new+1 */ + L_tmp = L_add_o( L_tmp, L_mult_o( *ptI, *ptI, &Overflow ), &Overflow ); /* 2*Q_new+1 */ + L_tmp = L_add_o( L_tmp, L_tmp, &Overflow ); /* 2*Q_new+1 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_mult( *ptR, *ptR ); /* 2*Q_new+1 */ + L_tmp = L_add( L_tmp, L_mult( *ptI, *ptI ) ); /* 2*Q_new+1 */ + L_tmp = L_add( L_tmp, L_tmp ); /* 2*Q_new+1 */ +#endif /* BASOP_NOGLOB */ + L_tmp = Mult_32_16( L_tmp, 128 ); /* 2*Q_new+1 */ + tmp1 = add( add( Q_new, Q_new ), 1 ); + env[i] = L_shr( L_tmp, sub( tmp1, 6 ) ); + move32(); /* Q6 */ + ptR++; + ptI--; + } + + Copy32( env, &( hTdCngEnc->cng_res_env_fx[( hTdCngEnc->cng_hist_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG ); + + /* calculate the residual signal energy */ + /*enr = dotp( res, res, L_frame ) / L_frame; */ + maxv = 0; + move16(); + FOR( i = 0; i < st_fx->L_frame; i++ ) + { + maxv = s_max( maxv, abs_s( res[i] ) ); + } + scale = norm_s( maxv ); + pt_res = res; + L_ener = L_deposit_l( 1 ); + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + FOR( j = 0; j < 128; j++ ) + { + tmpv = shl( *pt_res, scale ); + L_tmp = L_mult0( tmpv, tmpv ); + pt_res++; + tmpv = shl( *pt_res, scale ); +#ifdef BASOP_NOGLOB + L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add_sat( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ +#else + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ +#endif + } + } + ELSE /* L_FRAME16k */ + { + FOR( j = 0; j < 160; j++ ) + { + tmpv = shl( *pt_res, scale ); + L_tmp = L_mult0( tmpv, tmpv ); + pt_res++; + tmpv = shl( *pt_res, scale ); +#ifdef BASOP_NOGLOB + L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add_sat( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ +#else + L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ +#endif + } + } + /* convert log2 of residual signal energy */ + /*enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); */ + hi = norm_l( L_ener ); + lo = Log2_norm_lc( L_shl( L_ener, hi ) ); + hi = sub( 29, hi ); /* log2 exp in Q2*(Q_new+scale) */ + hi = sub( hi, shl( add( Q_new, scale ), 1 ) ); /* Q0 */ + L_tmp = L_Comp( hi, lo ); /* Q16 */ + enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ + + /* update the circular buffer of old energies */ + hTdCngEnc->cng_ener_hist_fx[hTdCngEnc->cng_hist_ptr] = enr; + move16(); /* Q8 */ + + /*-----------------------------------------------------------------* + * Quantize residual signal energy (only in SID frame) + *-----------------------------------------------------------------*/ + test(); + IF( EQ_32( st_fx->core_brate, SID_2k40 ) || EQ_32( st_fx->core_brate, SID_1k75 ) ) + { + IF( GE_16( hDtxEnc->cng_cnt, sub( hDtxEnc->cng_hist_size, 1 ) ) ) + { + /* average the envelope except outliers */ + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + L_tmp1 = L_add( env[i], 0 ); + FOR( j = 0; j < hDtxEnc->cng_hist_size; j++ ) + { +#ifdef BASOP_NOGLOB + L_tmp1 = L_add_sat( L_tmp1, hTdCngEnc->cng_res_env_fx[j * NUM_ENV_CNG + i] ); +#else + L_tmp1 = L_add( L_tmp1, hTdCngEnc->cng_res_env_fx[j * NUM_ENV_CNG + i] ); +#endif + } + L_tmp = L_add( hTdCngEnc->cng_res_env_fx[max_idx1[0] * NUM_ENV_CNG + i], hTdCngEnc->cng_res_env_fx[max_idx1[1] * NUM_ENV_CNG + i] ); + L_tmp1 = L_sub( L_tmp1, L_tmp ); + + /* env[i] /= (float)(st_fx->cng_hist_size - 2); */ + tmp1 = sub( hDtxEnc->cng_hist_size, 2 ); + IF( GT_16( tmp1, 1 ) ) + { + tmp1 = div_s( 1, tmp1 ); + L_tmp1 = Mult_32_16( L_tmp1, tmp1 ); + } + + env[i] = L_tmp1; + move32(); + } + /* compute average excitation energy */ + L_tmp = L_deposit_l( 0 ); + ptr = hTdCngEnc->cng_hist_ptr; + move16(); + + FOR( k = 0; k < hDtxEnc->cng_hist_size; k++ ) + { + /* enr += W_HIST[k]*cng_ener_hist[ptr] */ + L_tmp = L_mac0( L_tmp, W_HIST_FX[k], hTdCngEnc->cng_ener_hist_fx[ptr] ); /* Q24 (8+16) */ + ptr = sub( ptr, 1 ); + if ( ptr < 0 ) /* check for circular pointer */ + { + ptr = DTX_HIST_SIZE - 1; + move16(); + } + } + /*----------------------------------------------------------- + * here we want to divide L_tmp by the sum + * of all the coefs used W_HIST[0..cng_hist_size-1] + * The table W_HIST_S already contains the inverted sum. + * That is + * W_HIST_S[k] 1 + * ------------- = --------------------------- + * 4096 W_HIST[0] + ... + W_HIST[k] + * + * 1 / Sum(W_HIST[0..k]) is always > 1 since the sum + * of the coefs 0..k is always < 1 but > 0 + * enr is in Q8 since the history buffer constains Q8 energies + *-----------------------------------------------------------*/ + /*L_tmp = Mpy_32_16_1(L_tmp, W_HIST_S_FX[k-1]); */ /* normalize average value */ + L_tmp = Mult_32_16( L_tmp, W_HIST_S_FX[k - 1] ); /* Q21 (24+12+1-16) */ + L_tmp = L_shl( L_tmp, 3 ); /* Q24 */ + enr = round_fx( L_tmp ); /* Q8 */ + } + /* decrease the energy in case of WB input */ + IF( EQ_16( st_fx->element_mode, IVAS_SCE ) || EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + // PMT("CNG IVAS_SCE and IVAS_CPE_DFT code missing") + // IVAS_CODE + // enr += hTdCngEnc->CNG_att * FAC_LOG2 / 10.0f; + } + ELSE IF( NE_16( st_fx->bwidth, NB ) ) + { + IF( EQ_16( st_fx->bwidth, WB ) ) + { + IF( hDtxEnc->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT_fx[hDtxEnc->CNG_mode]; + move16(); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT_fx[4]; + move16(); + } + } + ELSE + { + att = 384; + move16(); /*Q8*/ + } + enr = sub( enr, att ); + } + /* intialize the energy quantization parameters */ + IF( st_fx->Opt_AMR_WB == 0 ) + { + step = STEP_SID_FX; + move16(); + step_inv = ISTEP_SID_FX; + move16(); + maxl = 127; + move16(); + num_bits = 7; + move16(); + } + ELSE + { + step = STEP_AMR_WB_SID_FX; + move16(); + step_inv = ISTEP_AMR_WB_SID_FX; + move16(); + maxl = 63; + move16(); + num_bits = 6; + move16(); + } + + /* calculate the energy quantization index */ + enr_index = add( enr, 512 /* Q8(2.0) */ ); /* enr + 2.0 */ + enr_index = extract_l( L_shr( L_mult0( enr_index, step ), 12 + 8 ) ); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min( enr_index, maxl ); + enr_index = s_max( enr_index, 0 ); + + /* allow only slow energy increase */ + test(); + IF( hTdCngEnc->old_enr_index >= 0 && GT_16( enr_index, add( hTdCngEnc->old_enr_index, MAX_DELTA ) ) ) + { + IF( *allow_cn_step != 0 ) + { + tmp1 = mult( 27853 /* Q15(0.85) */, sub( enr_index, hTdCngEnc->old_enr_index ) ); + enr_index = add( hTdCngEnc->old_enr_index, tmp1 ); + } + ELSE + { + enr_index = add( hTdCngEnc->old_enr_index, MAX_DELTA ); + } + } + hTdCngEnc->old_enr_index = enr_index; + move16(); + + push_indice_fx( hBstr, IND_ENERGY, enr_index, num_bits ); + if ( enr_index == 0 ) + { + enr_index = -5; + move16(); + } + /* Find quantized energy */ + /* *Enew = (float)enr_index / step - 2.0 */ + /* *Enew = (float)pow(2.0, *Enew) */ + L_tmp = L_mult( enr_index, step_inv ); /* Q16(0+15+1) */ + /* substract by 2 not done to leave Energy in Q2 */ + lo = L_Extract_lc( L_tmp, &hi ); + hTdCngEnc->Enew_fx = Pow2( add( hi, 4 ), lo ); /* Q6 */ + IF( EQ_32( st_fx->core_brate, SID_2k40 ) ) + { + /* enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f );*/ + exp = norm_l( hTdCngEnc->Enew_fx ); + L_tmp = L_shl( hTdCngEnc->Enew_fx, exp ); /*Q(exp+6) */ + L_tmp = Mult_32_16( L_tmp, shl( st_fx->L_frame, 5 ) ); /* Q(exp+6+5-15=exp-4) */ + +#ifdef BASOP_NOGLOB + L_tmp = L_shr_sat( L_tmp, sub( exp, 10 ) ); /* Q6 */ +#else + L_tmp = L_shr( L_tmp, sub( exp, 10 ) ); /* Q6 */ +#endif + + exp = norm_l( L_tmp ); + fra = Log2_norm_lc( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 6 ); + L_tmp = L_Comp( exp, fra ); + enr1 = L_shr( L_tmp, 10 ); /* Q6 */ + + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + /* env[i] -= 2 * st->Enew;*/ + L_tmp1 = L_add( env[i], 0 ); + L_tmp = L_add( hTdCngEnc->Enew_fx, hTdCngEnc->Enew_fx ); + L_tmp1 = L_sub( L_tmp1, L_tmp ); /*Q6*/ + + IF( L_tmp1 < 0 ) + { + L_tmp1 = L_deposit_l( 6 ); /* (0.1)Q6 */ + } + /* env[i] = (float)log10( env[i] + 0.1f ) / (float)log10( 2.0f ); */ + exp = norm_l( L_tmp1 ); + fra = Log2_norm_lc( L_shl( L_tmp1, exp ) ); + exp = sub( sub( 30, exp ), 6 ); + L_tmp = L_Comp( exp, fra ); + L_tmp1 = L_shr( L_tmp, 10 ); /* Q6 */ + + L_tmp = L_shr( L_deposit_l( att ), 2 ); /* Q6 */ + L_tmp1 = L_sub( L_tmp1, L_tmp ); + + IF( L_tmp1 < 0 ) + { + L_tmp1 = L_deposit_l( 0 ); + } + + L_tmp1 = L_sub( enr1, L_tmp1 ); + + env[i] = L_tmp1; + move32(); + } + + /* codebook search */ + min1 = L_add( 1310588928, 0 ); /* Q17 */ + min1_idx = 0; + move16(); + + FOR( i = 0; i < 64; i++ ) + { + d = L_deposit_l( 0 ); + FOR( j = 0; j < NUM_ENV_CNG; j++ ) + { + /* d += (env[j] - CNG_details_codebook_fx[i][j]) * (env[j] - CNG_details_codebook_fx[i][j]);*/ + L_tmp = L_sub( env[j], L_deposit_l( CNG_details_codebook_fx[i][j] ) ); /* Q6 */ + exp = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp ); /*Q(exp+6)*/ + tmp1 = extract_h( L_tmp ); /*Q(exp+6-16)=exp-10*/ +#ifdef BASOP_NOGLOB + L_tmp = L_mult_o( tmp1, tmp1, &Overflow ); /*Q(2*exp - 19)*/ +#else /* BASOP_NOGLOB */ + L_tmp = L_mult( tmp1, tmp1 ); /*Q(2*exp - 19)*/ +#endif + L_tmp = L_shr( L_tmp, sub( add( exp, exp ), 36 ) ); /* Q17 */ + d = L_add( d, L_tmp ); + } + + IF( LT_32( d, min1 ) ) + { + min1 = L_add( d, 0 ); + min1_idx = i; + move16(); + } + } + push_indice_fx( hBstr, IND_CNG_ENV1, min1_idx, 6 ); + /* get quantized res_env_details */ + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + q_env[i] = L_deposit_l( CNG_details_codebook_fx[min1_idx][i] ); + } + } + /* Update hangover memory during CNG */ + test(); + IF( *allow_cn_step == 0 && LT_32( Mult_32_16( hTdCngEnc->Enew_fx, 21845 /*1/1.5f, Q15*/ ), hTdCngEnc->lp_ener_fx ) ) + { + /* update the pointer to circular buffer of old LSP vectors */ + hTdCngEnc->ho_hist_ptr = add( hTdCngEnc->ho_hist_ptr, 1 ); + if ( EQ_16( hTdCngEnc->ho_hist_ptr, HO_HIST_SIZE ) ) + { + hTdCngEnc->ho_hist_ptr = 0; + move16(); + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + Copy( lsp_new, &( hTdCngEnc->ho_lsp_hist_fx[( hTdCngEnc->ho_hist_ptr ) * M] ), M ); + + /* update the hangover energy buffer */ + hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] = hTdCngEnc->Enew_fx; + move32(); + IF( EQ_32( st_fx->core_brate, SID_2k40 ) ) + { + FOR( i = 0; i < NUM_ENV_CNG; i++ ) + { + /* get quantized envelope */ + /* env[i] = pow(2.0f,(enr1 - q_env[i])) + 2*st->Enew;*/ + L_tmp = L_sub( enr1, q_env[i] ); /* Q6 */ + L_tmp = L_shl( L_tmp, 10 ); /* 16 */ + temp_lo_fx = L_Extract_lc( L_tmp, &temp_hi_fx ); + + exp_pow = sub( 14, temp_hi_fx ); + L_tmp = Pow2( 14, temp_lo_fx ); /* Qexp_pow */ + env[i] = L_shl( L_tmp, sub( 6, exp_pow ) ); + move32(); /* Q6 */ + L_tmp = L_add( hTdCngEnc->Enew_fx, hTdCngEnc->Enew_fx ); + env[i] = L_add( env[i], L_tmp ); + move32(); /* Q6 */ + } + Copy32( env, &( hTdCngEnc->ho_env_hist_fx[( hTdCngEnc->ho_hist_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG ); + } + hTdCngEnc->ho_hist_size = add( hTdCngEnc->ho_hist_size, 1 ); + if ( GT_16( hTdCngEnc->ho_hist_size, HO_HIST_SIZE ) ) + { + hTdCngEnc->ho_hist_size = HO_HIST_SIZE; + move16(); + } + } + } + /* dithering bit for AMR-WB IO mode is always set to 0 */ + IF( EQ_32( st_fx->core_brate, SID_1k75 ) ) + { + push_indice_fx( hBstr, IND_DITHERING, 0, 1 ); + } + IF( EQ_32( st_fx->core_brate, SID_2k40 ) ) + { + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + push_indice_fx( hBstr, IND_ACELP_16KHZ, 1, 1 ); + } + ELSE + { + push_indice_fx( hBstr, IND_ACELP_16KHZ, 0, 1 ); + } + + push_indice_fx( hBstr, IND_CNG_HO, s_min( hTdCngEnc->burst_ho_cnt, 7 ), 3 ); + hTdCngEnc->num_ho = m; + move16(); + push_indice_fx( hBstr, IND_SID_TYPE, 0, 1 ); + + IF( LT_32( st_fx->input_Fs, 32000 ) && NE_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + push_indice_fx( hBstr, IND_SID_BW, 0, 1 ); + *sid_bw = 0; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + /* update the SID frames counter */ + test(); + IF( EQ_32( st_fx->core_brate, SID_2k40 ) || EQ_32( st_fx->core_brate, SID_1k75 ) ) + { + hDtxEnc->cng_cnt = 0; + move16(); + hTdCngEnc->cng_hist_ptr = -1; + move16(); + /* update frame length memory */ + hDtxEnc->last_CNG_L_frame = st_fx->L_frame; + move16(); + } + ELSE + { + hDtxEnc->cng_cnt = add( hDtxEnc->cng_cnt, 1 ); + } + + return; +} -/*---------------------------------------------------------------------* - * Local function prototypes - *---------------------------------------------------------------------*/ -static void shb_CNG_encod_fx( Encoder_State *st_fx, const Word16 update_fx ); -static Word16 shb_DTX_fx( Encoder_State *st_fx, const Word16 *shb_speech_fx, const Word16 *syn_12k8_16k ); -/*---------------------------------------------------------------------* - * CNG_enc() - * - * Confort noise generation for the coder - *---------------------------------------------------------------------*/ -void CNG_enc_fx( - Encoder_State *st_fx, /* i/o: State structure */ - Word16 Aq[], /* o : LP coefficients Q12 */ - const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */ - Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */ +#ifdef IVAS_FLOAT_FIXED +void CNG_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: State structure */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */ + // Word32 L_ener, /* i : residual energy from Levinson-Durbin Q6 */ const Word16 *lsp_mid, /* i : mid frame LSPs Q15 */ Word16 *lsp_new, /* i/o: current frame ISPs Q15 */ Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */ @@ -48,37 +1218,35 @@ void CNG_enc_fx( Word16 i, j, ptr; Word16 m1; Word16 res[L_FRAME16k]; - Word16 step_inv = 0; + Word16 step_inv; Word16 hi, lo; - Word16 maxl = 0; - Word16 num_bits = 0; - Word16 step = 0; - Word16 *pt_res; - const Word16 *pt_sp; + Word16 maxl; + Word16 num_bits; + Word16 step; Word16 enr; - Word32 L_tmp, L_ener; + Word32 L_tmp; Word16 k, tmp1; Word16 weights; Word16 sp_enr; Word32 L_tmp1; Word16 exp; - Word16 m = 0; + Word16 m; Word16 tmp[HO_HIST_SIZE * M]; Word16 ll, s_ptr; - Word16 tmpv, maxv, scale, att = 1; + Word16 tmpv, att; Word16 lsf_tmp[M]; Word32 C[M]; Word32 max_val[2]; Word16 max_idx[2]; Word16 ftmp_fx; Word16 lsp_tmp[M]; - Word16 dev; - Word16 max_dev; - Word16 dist; - Word16 max_idx1[2] = { 0, 0 }; + Word32 dev; + Word32 max_dev; + Word32 dist; + Word16 max_idx1[2]; Word16 fft_io[L_FRAME16k]; Word16 *ptR, *ptI; - Word32 enr1 = 0; + Word32 enr1; Word32 env[NUM_ENV_CNG]; Word32 min1; Word16 min1_idx; @@ -88,55 +1256,104 @@ void CNG_enc_fx( Word16 fra; Word16 temp_lo_fx, temp_hi_fx; Word16 exp_pow; - Word16 force_cn_step = 0; + Word16 force_cn_step; Word16 tmp_loop; Word16 st_lp_sp_enr; DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc; TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc; BSTR_ENC_HANDLE hBstr = st_fx->hBstr; - st_lp_sp_enr = hTdCngEnc->lp_sp_enr_fx; Word16 lp_ener_thr_scale; + Word64 w_temp; + Word32 inv_frame_len; + Word32 L_ener; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + step_inv = 0; + move16(); + maxl = 0; + move16(); + num_bits = 0; + move16(); + step = 0; + move16(); + m = 0; + move16(); + att = 1; + move16(); + max_idx1[0] = 0; + max_idx1[1] = 0; + move16(); + move16(); + enr1 = 0; + move32(); + force_cn_step = 0; + move16(); + st_lp_sp_enr = hTdCngEnc->lp_sp_enr_fx; + move16(); /* Temp variables for floating point functions */ - lp_ener_thr_scale = 8; /* 4.0f*/ /*IVAS_CODE Q2 */ + lp_ener_thr_scale = 8; /* 4.0f*/ /* Q2 */ move16(); - if ( NE_16( st_fx->element_mode, EVS_MONO ) ) + if ( st_fx->element_mode != EVS_MONO ) { - lp_ener_thr_scale = 7; /* 3.5f;*/ + lp_ener_thr_scale = 7; /* 3.5f;*/ /* Q2 */ move16(); } - /*sp_enr = (float) log10( sum2_f( speech, L_frame )/L_frame + 0.1f )/ (float)log10(2.0f);*/ /*9.1 */ - pt_sp = speech; - L_ener = L_deposit_l( 1 ); - /* L_ener = L_add(L_shr(sum2_f_fx( speech, L_frame ), 8) , L_ener);*/ - IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + + w_temp = 1; + move64(); + + FOR( j = 0; j < st_fx->L_frame; j++ ) { - FOR( j = 0; j < 128; j++ ) - { - L_tmp = L_mult0( *pt_sp, *pt_sp ); - pt_sp++; - L_tmp = L_mac0( L_tmp, *pt_sp, *pt_sp ); - pt_sp++; - L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*Q_new + 1, divide by L_frame done here */ - } + w_temp = W_mac0_16_16( w_temp, speech[j], speech[j] ); } - ELSE /* L_FRAME16k */ + exp = W_norm( w_temp ); + + inv_frame_len = 0; + move32(); + + SWITCH( st_fx->L_frame ) { - FOR( i = 0; i < 2; i++ ) - { - FOR( j = 0; j < 80; j++ ) - { - L_tmp = L_mult0( *pt_sp, *pt_sp ); - pt_sp++; - L_tmp = L_mac0( L_tmp, *pt_sp, *pt_sp ); - pt_sp++; - L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*Q_new + 1, divide by L_frame done here */ - } - } + case L_FRAME25_6k: + inv_frame_len = ONE_BY_L_FRAME25_6k_Q31; + move16(); + BREAK; + case L_FRAME: + inv_frame_len = ONE_BY_L_FRAME_Q31; + move16(); + BREAK; + case L_FRAME48k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case 240: + inv_frame_len = ONE_BY_240_Q31; + move16(); + BREAK; + case L_FRAME32k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME16k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME8k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME4k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + default: + inv_frame_len = divide3216( 1, st_fx->L_frame ); } + L_ener = W_extract_h( W_shl( w_temp, exp ) ); /* Q = 2*Q_new+exp-32 */ + L_ener = Mpy_32_32( L_ener, inv_frame_len ); /* Q = 2*Q_new+exp-32 */ + L_ener = L_shl( L_ener, sub( 33, exp ) ); /* Q = 2*Q_new+1 */ hi = norm_l( L_ener ); lo = Log2_norm_lc( L_shl( L_ener, hi ) ); @@ -162,10 +1379,11 @@ void CNG_enc_fx( test(); test(); test(); - IF( GT_32( st_fx->last_core_brate, SID_2k40 ) && ( EQ_16( st_fx->last_core, HQ_CORE ) || st_fx->hTdCngEnc->burst_ho_cnt > 0 ) && LT_16( hTdCngEnc->lp_sp_enr_fx, 1536 ) && - GT_16( sub( sp_enr, hTdCngEnc->lp_sp_enr_fx ), 1024 ) && GT_16( sp_enr, 1536 ) ) + test(); + IF( GT_32( st_fx->last_core_brate, SID_2k40 ) && ( EQ_16( st_fx->last_core, HQ_CORE ) || st_fx->hTdCngEnc->burst_ho_cnt > 0 ) && LT_16( hTdCngEnc->lp_sp_enr_fx, 1536 /*6.0f in Q8*/ ) && + GT_16( sub( sp_enr, hTdCngEnc->lp_sp_enr_fx ), 1024 /*4.0f in Q8*/ ) && GT_16( sp_enr, 1536 /*6.0f in Q8*/ ) ) { - hTdCngEnc->lp_sp_enr_fx = sp_enr; + hTdCngEnc->lp_sp_enr_fx = sp_enr; /* Q8 */ move16(); force_cn_step = 1; move16(); @@ -173,10 +1391,12 @@ void CNG_enc_fx( ELSE { hTdCngEnc->lp_sp_enr_fx = round_fx( L_mac( L_mult( 29491 /* 0.9, Q15 */, hTdCngEnc->lp_sp_enr_fx ), 3277 /* 0.1, Q15 */, sp_enr ) ); /* Q8 (8+15+1-16) */ + move16(); } } /* update the pointer to circular buffer of old LSP vectors */ hTdCngEnc->cng_hist_ptr = add( hTdCngEnc->cng_hist_ptr, 1 ); + move16(); if ( EQ_16( hTdCngEnc->cng_hist_ptr, DTX_HIST_SIZE ) ) { hTdCngEnc->cng_hist_ptr = 0; @@ -279,7 +1499,7 @@ void CNG_enc_fx( test(); test(); IF( ( ( hDtxEnc->cng_cnt == 0 ) && - GT_16( hTdCngEnc->lp_sp_enr_fx, 1536 ) && + GT_16( hTdCngEnc->lp_sp_enr_fx, 1536 /* 6.0, Q8 */ ) && ( LT_16( add( st_lp_sp_enr, 1024 /* 4.0, Q8 */ ), sp_enr ) ) && ( hDtxEnc->first_CNG != 0 ) && ( hTdCngEnc->old_enr_index >= 0 ) && @@ -296,7 +1516,7 @@ void CNG_enc_fx( Copy( st_fx->lsp_old_fx, hDtxEnc->lspCNG_fx, M ); /* Average the CNG spectral envelope in case of the very first CNG frame */ - IF( NE_16( st_fx->element_mode, EVS_MONO ) ) + IF( st_fx->element_mode != EVS_MONO ) { FOR( i = 0; i < M; i++ ) { @@ -318,11 +1538,7 @@ void CNG_enc_fx( } ELSE { -#ifdef LSF_RE_USE_SECONDARY_CHANNEL - lsf_enc_fx( st_fx, lsf_new, lsp_new, NULL, NULL, 100, 0, 0, NULL, Q_new ); -#else - lsf_enc_fx( st_fx, lsf_new, lsp_new, NULL, NULL, 100, 0, 0, Q_new ); -#endif + lsf_enc_ivas_fx( st_fx, lsf_new, lsp_new, NULL, NULL, 0, 0, NULL, Q_new ); } /* Reset CNG history if CNG frame length is changed */ test(); @@ -344,11 +1560,12 @@ void CNG_enc_fx( * CNG spectral envelope update * Find A(z) coefficients *---------------------------------------------------------------------*/ - - IF( LE_32( st_fx->last_core_brate, SID_2k40 ) ) + test(); + test(); + IF( ( st_fx->last_core_brate == FRAME_NO_DATA ) || EQ_32( st_fx->last_core_brate, SID_1k75 ) || EQ_32( st_fx->last_core_brate, SID_2k40 ) ) { /* Reset hangover counter if not first SID period */ - if ( GT_32( st_fx->core_brate, FRAME_NO_DATA ) ) + if ( st_fx->core_brate > FRAME_NO_DATA ) { hTdCngEnc->num_ho = 0; move16(); @@ -371,7 +1588,7 @@ void CNG_enc_fx( test(); test(); test(); - IF( EQ_16( st_fx->element_mode, EVS_MONO ) && ( ( st_fx->Opt_AMR_WB || EQ_16( st_fx->bwidth, WB ) ) && ( !hDtxEnc->first_CNG || GE_16( hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) ) ) + IF( ( st_fx->element_mode == EVS_MONO ) && ( ( st_fx->Opt_AMR_WB || EQ_16( st_fx->bwidth, WB ) ) && ( !hDtxEnc->first_CNG || GE_16( hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) ) ) { IF( GT_32( hDtxEnc->last_active_brate, ACELP_16k40 ) ) { @@ -386,6 +1603,7 @@ void CNG_enc_fx( /* If first sid after active burst update LSF history from circ buffer */ hTdCngEnc->burst_ho_cnt = s_min( hTdCngEnc->burst_ho_cnt, hTdCngEnc->ho_circ_size ); + move16(); hTdCngEnc->act_cnt = 0; move16(); s_ptr = add( sub( hTdCngEnc->ho_circ_ptr, hTdCngEnc->burst_ho_cnt ), 1 ); @@ -398,6 +1616,7 @@ void CNG_enc_fx( FOR( ll = hTdCngEnc->burst_ho_cnt; ll > 0; ll-- ) { hTdCngEnc->ho_hist_ptr = add( hTdCngEnc->ho_hist_ptr, 1 ); + move16(); if ( EQ_16( hTdCngEnc->ho_hist_ptr, HO_HIST_SIZE ) ) { hTdCngEnc->ho_hist_ptr = 0; @@ -421,9 +1640,11 @@ void CNG_enc_fx( Copy( &( hTdCngEnc->ho_lsp_circ_fx[s_ptr * M] ), &( hTdCngEnc->ho_lsp_hist_fx[hTdCngEnc->ho_hist_ptr * M] ), M ); Copy32( &( hTdCngEnc->ho_ener_circ_fx[s_ptr] ), &( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] ), 1 ); hTdCngEnc->ho_sid_bw = L_shl( L_and( hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + move32(); Copy32( &( hTdCngEnc->ho_env_circ_fx[s_ptr * NUM_ENV_CNG] ), &( hTdCngEnc->ho_env_hist_fx[hTdCngEnc->ho_hist_ptr * NUM_ENV_CNG] ), NUM_ENV_CNG ); hTdCngEnc->ho_hist_size = add( hTdCngEnc->ho_hist_size, 1 ); + move16(); if ( GT_16( hTdCngEnc->ho_hist_size, HO_HIST_SIZE ) ) { hTdCngEnc->ho_hist_size = HO_HIST_SIZE; @@ -441,25 +1662,15 @@ void CNG_enc_fx( IF( hTdCngEnc->burst_ho_cnt > 0 ) { - /**allow_cn_step |= ( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] > 4 * hTdCngEnc->lp_ener_fx ); */ -#if 1 - /*allow_cn_step |= (hDtxEnc->first_CNG || st->element_mode == EVS_MONO) && (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener);*/ - /* (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener); */ - L_tmp1 = L_shr( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], 2 ); - IF( NE_16( lp_ener_thr_scale, 8 ) ) - { - L_tmp1 = L_add( L_tmp1, L_shr( hTdCngEnc->lp_ener_fx, 8 ) ); - } - L_tmp1 = L_sub( L_tmp1, hTdCngEnc->lp_ener_fx ); -#else - L_tmp1 = L_shr( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], 2 ); - L_tmp1 = L_sub( L_tmp1, hTdCngEnc->lp_ener_fx ); -#endif + /**allow_cn_step |= ( hDtxEnc->first_CNG || st->element_mode == EVS_MONO ) && ( hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener );*/ + w_temp = W_msu_32_16( W_shl( W_deposit32_l( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] ), 1 ), hTdCngEnc->lp_ener_fx, lp_ener_thr_scale ); /*Q7*/ + test(); test(); - IF( ( hDtxEnc->first_CNG > 0 || EQ_16( st_fx->element_mode, EVS_MONO ) ) && L_tmp1 > 0 ) + IF( ( hDtxEnc->first_CNG > 0 || ( st_fx->element_mode == EVS_MONO ) ) && w_temp > 0 ) { *allow_cn_step = s_or( *allow_cn_step, 1 ); + move16(); } } test(); @@ -471,13 +1682,13 @@ void CNG_enc_fx( Copy( &( hTdCngEnc->ho_lsp_hist_fx[ptr * M] ), tmp, M ); m1 = 0; move16(); - IF( L_and( hTdCngEnc->ho_sid_bw, (Word32) 0x1 ) == 0 ) + IF( L_and( hTdCngEnc->ho_sid_bw, 1 ) == 0 ) { Copy32( &hTdCngEnc->ho_env_hist_fx[ptr * NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); m1 = 1; move16(); } - L_enr = Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], W_DTX_HO_FX[0] ); /* Q6+15-15->Q6 */ + L_ener = Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], W_DTX_HO_FX[0] ); /* Q6+15-15->Q6 */ weights = W_DTX_HO_FX[0]; /* Q15 */ @@ -498,13 +1709,13 @@ void CNG_enc_fx( { /*enr += W_DTX_HO[k] * st_fx->ho_ener_hist[ptr]; */ L_tmp1 = Mult_32_16( hTdCngEnc->ho_ener_hist_fx[ptr], W_DTX_HO_FX[k] ); /* Q6+15-15->Q6 */ - L_enr = L_add( L_enr, L_tmp1 ); /* Q6 */ + L_ener = L_add( L_ener, L_tmp1 ); /* Q6 */ /*weights += W_DTX_HO[k]; */ weights = add( weights, W_DTX_HO_FX[k] ); /* Q15 */ Copy( &hTdCngEnc->ho_lsp_hist_fx[ptr * M], &tmp[m * M], M ); - IF( L_and( hTdCngEnc->ho_sid_bw, L_shl( (Word32) 0x1, k ) ) == 0 ) + IF( L_and( hTdCngEnc->ho_sid_bw, L_shl( 1, k ) ) == 0 ) { Copy32( &hTdCngEnc->ho_env_hist_fx[ptr * NUM_ENV_CNG], &tmp_env[m1 * NUM_ENV_CNG], NUM_ENV_CNG ); m1 = add( m1, 1 ); @@ -516,10 +1727,10 @@ void CNG_enc_fx( /*enr /= weights; */ exp = norm_s( weights ); tmp1 = div_s( shl( 1, sub( 14, exp ) ), weights ); /* Q(15+14-exp-15) */ - L_tmp1 = Mult_32_16( L_enr, tmp1 ); /* Q(14-exp+6-15)->Q(5-exp) */ - L_enr = L_shl( L_tmp1, add( exp, 1 ) ); /* Q6 */ + L_tmp1 = Mult_32_16( L_ener, tmp1 ); /* Q(14-exp+6-15)->Q(5-exp) */ + L_ener = L_shl( L_tmp1, add( exp, 1 ) ); /* Q6 */ - hTdCngEnc->lp_ener_fx = L_enr; + hTdCngEnc->lp_ener_fx = L_ener; move32(); /* Q6 */ set32_fx( max_val, 0, 2 ); @@ -593,6 +1804,7 @@ void CNG_enc_fx( tmpv = div_s( 1, sub( m, 1 ) ); /*Q15 */ L_tmp = Mpy_32_16_1( L_tmp, tmpv ); /*Q15 */ lsp_tmp[i] = extract_l( L_tmp ); /*Q15 */ + move16(); } } ELSE @@ -609,28 +1821,27 @@ void CNG_enc_fx( tmpv = div_s( 1, sub( m, 2 ) ); /*Q15 */ L_tmp = Mpy_32_16_1( L_tmp, tmpv ); /*Q15 */ lsp_tmp[i] = extract_l( L_tmp ); /*Q15 */ + move16(); } } - dist = 0; /*Q15 */ + dist = 0; /*Q15 */ + move32(); max_dev = 0; /*Q15 */ + move32(); FOR( i = 0; i < M; i++ ) { - dev = abs_s( sub( lsp_tmp[i], lsp_new[i] ) ); /*Q15 */ -#ifdef BASOP_NOGLOB - dist = add_o( dist, dev, &Overflow ); /*Q15 */ -#else - dist = add( dist, dev ); /*Q15 */ -#endif - if ( GT_16( dev, max_dev ) ) + dev = L_abs( L_sub( L_deposit_l( lsp_tmp[i] ), L_deposit_l( lsp_new[i] ) ) ); /*Q15 */ + dist = L_add( dist, dev ); /*Q15 */ + if ( GT_32( dev, max_dev ) ) { max_dev = dev; - move16(); + move32(); } } test(); - IF( GT_16( dist, 13107 ) || GT_16( max_dev, 3277 ) ) + IF( GT_32( dist, 13107 ) || GT_32( max_dev, 3277 ) ) { FOR( i = 0; i < M; i++ ) { @@ -643,7 +1854,7 @@ void CNG_enc_fx( FOR( i = 0; i < M; i++ ) { /* AR low-pass filter */ - hDtxEnc->lspCNG_fx[i] = add( mult_r( 26214, lsp_tmp[i] ), mult_r( 6554, lsp_new[i] ) ); + hDtxEnc->lspCNG_fx[i] = add( mult_r( 26214, lsp_tmp[i] ), mult_r( 6554, lsp_new[i] ) ); /* Q15 */ move16(); } } @@ -682,15 +1893,15 @@ void CNG_enc_fx( #endif } - env[i] = L_tmp; + env[i] = L_tmp; /* Q6*/ move32(); } - Copy32( env, hTdCngEnc->lp_env_fx, NUM_ENV_CNG ); + Copy32( env, hTdCngEnc->lp_env_fx, NUM_ENV_CNG ); /* Q6 */ } } ELSE { - Copy( lsp_new, hDtxEnc->lspCNG_fx, M ); /* use newly analyzed ISFs */ + Copy( lsp_new, hDtxEnc->lspCNG_fx, M ); /* use newly analyzed ISFs */ /* Q15 */ } } IF( st_fx->Opt_AMR_WB != 0 ) @@ -699,7 +1910,9 @@ void CNG_enc_fx( } ELSE { - E_LPC_f_lsp_a_conversion( hDtxEnc->lspCNG_fx, Aq, M ); /* Find A(z) (not interpolated) */ + E_LPC_f_lsp_a_conversion( hDtxEnc->lspCNG_fx, Aq, M ); + exp = sub( Q14, norm_s( Aq[0] ) ); + Scale_sig( Aq, M, sub( Q12, exp ) ); } tmp_loop = shr( st_fx->L_frame, 6 ); @@ -714,22 +1927,22 @@ void CNG_enc_fx( /* calculate the residual signal */ Residu3_fx( Aq, speech, res, st_fx->L_frame, 0 ); - Copy( res, res1, st_fx->L_frame ); + Copy( res, res1, st_fx->L_frame ); /* Q_new */ test(); IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) || EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) { - // PMT("Code to be completed") -#ifdef IVAS_CODE - att = powf( 10.0f, hTdCngEnc->CNG_att / 20.0f ); - v_multc( res1, att, res1, st->L_frame ); -#endif + L_tmp1 = L_mult0( hTdCngEnc->CNG_att_fx, 26214 /* 1/20.0f in Q19 */ ); // Q26 (7 + 19) + L_tmp1 = BASOP_Util_fPow( 1342177280 /*10 in Q27 */, 4, L_tmp1, 5, &exp ); + att = extract_h( L_shl( L_tmp1, exp ) ); // Q15 + v_multc_fixed_16_16( res1, att, res1, st_fx->L_frame ); /* Q_new */ } - ELSE IF( NE_16( st_fx->bwidth, NB ) ) + ELSE IF( st_fx->bwidth != NB ) { test(); IF( EQ_16( st_fx->bwidth, WB ) && hDtxEnc->CNG_mode >= 0 ) { ftmp_fx = HO_ATT_FX[hDtxEnc->CNG_mode]; + move16(); } ELSE { @@ -754,7 +1967,7 @@ void CNG_enc_fx( } /* calculate the spectrum of residual signal */ - Copy( res1, fft_io, st_fx->L_frame ); + Copy( res1, fft_io, st_fx->L_frame ); /* Q_new */ IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) { @@ -789,61 +2002,63 @@ void CNG_enc_fx( /* calculate the residual signal energy */ /*enr = dotp( res, res, L_frame ) / L_frame; */ - maxv = 0; - move16(); - FOR( i = 0; i < st_fx->L_frame; i++ ) - { - maxv = s_max( maxv, abs_s( res[i] ) ); - } - scale = norm_s( maxv ); - pt_res = res; - L_ener = L_deposit_l( 1 ); - IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + w_temp = 1; + move64(); + FOR( j = 0; j < st_fx->L_frame; j++ ) { - FOR( j = 0; j < 128; j++ ) - { - tmpv = shl( *pt_res, scale ); - L_tmp = L_mult0( tmpv, tmpv ); - pt_res++; - tmpv = shl( *pt_res, scale ); -#ifdef BASOP_NOGLOB - L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add_sat( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ -#else - L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ -#endif - } + w_temp = W_mac0_16_16( w_temp, res[j], res[j] ); } - ELSE /* L_FRAME16k */ + exp = W_norm( w_temp ); + + SWITCH( st_fx->L_frame ) { - FOR( j = 0; j < 160; j++ ) - { - tmpv = shl( *pt_res, scale ); - L_tmp = L_mult0( tmpv, tmpv ); - pt_res++; - tmpv = shl( *pt_res, scale ); -#ifdef BASOP_NOGLOB - L_tmp = L_mac0_sat( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add_sat( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ -#else - L_tmp = L_mac0( L_tmp, tmpv, tmpv ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ -#endif - } + case L_FRAME25_6k: + inv_frame_len = ONE_BY_L_FRAME25_6k_Q31; + move16(); + BREAK; + case L_FRAME: + inv_frame_len = ONE_BY_L_FRAME_Q31; + move16(); + BREAK; + case L_FRAME48k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case 240: + inv_frame_len = ONE_BY_240_Q31; + move16(); + BREAK; + case L_FRAME32k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME16k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME8k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + case L_FRAME4k: + inv_frame_len = ONE_BY_L_FRAME48k_Q31; + move16(); + BREAK; + default: + inv_frame_len = divide3216( 1, st_fx->L_frame ); } + L_ener = W_extract_h( W_shl( w_temp, exp ) ); /* Q = 2*Q_new+exp-32 */ + L_ener = Mpy_32_32( L_ener, inv_frame_len ); /* Q = 2*Q_new+exp-32 */ + L_ener = L_shl( L_ener, sub( 33, exp ) ); /* Q = 2*Q_new+1 */ + /* convert log2 of residual signal energy */ /*enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); */ hi = norm_l( L_ener ); lo = Log2_norm_lc( L_shl( L_ener, hi ) ); - hi = sub( 29, hi ); /* log2 exp in Q2*(Q_new+scale) */ - hi = sub( hi, shl( add( Q_new, scale ), 1 ) ); /* Q0 */ - L_tmp = L_Comp( hi, lo ); /* Q16 */ - enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ + hi = sub( 29, hi ); /* log2 exp in Q2*Q_new */ + hi = sub( hi, shl( Q_new, 1 ) ); /* Q0 */ + L_tmp = L_Comp( hi, lo ); /* Q16 */ + enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ /* update the circular buffer of old energies */ hTdCngEnc->cng_ener_hist_fx[hTdCngEnc->cng_hist_ptr] = enr; @@ -920,11 +2135,9 @@ void CNG_enc_fx( /* decrease the energy in case of WB input */ IF( EQ_16( st_fx->element_mode, IVAS_SCE ) || EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) { - // PMT("CNG IVAS_SCE and IVAS_CPE_DFT code missing") - // IVAS_CODE - // enr += hTdCngEnc->CNG_att * FAC_LOG2 / 10.0f; + enr = add( enr, mult( hTdCngEnc->CNG_att_fx, FAC_LOG2_BY10_Q16 ) ); /* Q8 (Q7 + Q16 - Q15)*/ } - ELSE IF( NE_16( st_fx->bwidth, NB ) ) + ELSE IF( st_fx->bwidth != NB ) { IF( EQ_16( st_fx->bwidth, WB ) ) { @@ -951,7 +2164,7 @@ void CNG_enc_fx( /* intialize the energy quantization parameters */ IF( st_fx->Opt_AMR_WB == 0 ) { - step = STEP_SID_FX; + step = STEP_SID_FX; // Q12 move16(); step_inv = ISTEP_SID_FX; move16(); @@ -997,7 +2210,7 @@ void CNG_enc_fx( hTdCngEnc->old_enr_index = enr_index; move16(); - push_indice_fx( hBstr, IND_ENERGY, enr_index, num_bits ); + push_indice( hBstr, IND_ENERGY, enr_index, num_bits ); if ( enr_index == 0 ) { enr_index = -5; @@ -1062,7 +2275,8 @@ void CNG_enc_fx( } /* codebook search */ - min1 = L_add( 1310588928, 0 ); /* Q17 */ + min1 = 1310588928; /* Q17 */ + move32(); min1_idx = 0; move16(); @@ -1082,21 +2296,23 @@ void CNG_enc_fx( L_tmp = L_mult( tmp1, tmp1 ); /*Q(2*exp - 19)*/ #endif L_tmp = L_shr( L_tmp, sub( add( exp, exp ), 36 ) ); /* Q17 */ - d = L_add( d, L_tmp ); + d = L_add( d, L_tmp ); /* Q17 */ } IF( LT_32( d, min1 ) ) { - min1 = L_add( d, 0 ); + min1 = d; + move32(); min1_idx = i; move16(); } } - push_indice_fx( hBstr, IND_CNG_ENV1, min1_idx, 6 ); + push_indice( hBstr, IND_CNG_ENV1, min1_idx, 6 ); /* get quantized res_env_details */ FOR( i = 0; i < NUM_ENV_CNG; i++ ) { q_env[i] = L_deposit_l( CNG_details_codebook_fx[min1_idx][i] ); + move32(); } } /* Update hangover memory during CNG */ @@ -1105,6 +2321,7 @@ void CNG_enc_fx( { /* update the pointer to circular buffer of old LSP vectors */ hTdCngEnc->ho_hist_ptr = add( hTdCngEnc->ho_hist_ptr, 1 ); + move16(); if ( EQ_16( hTdCngEnc->ho_hist_ptr, HO_HIST_SIZE ) ) { hTdCngEnc->ho_hist_ptr = 0; @@ -1138,6 +2355,7 @@ void CNG_enc_fx( Copy32( env, &( hTdCngEnc->ho_env_hist_fx[( hTdCngEnc->ho_hist_ptr ) * NUM_ENV_CNG] ), NUM_ENV_CNG ); } hTdCngEnc->ho_hist_size = add( hTdCngEnc->ho_hist_size, 1 ); + move16(); if ( GT_16( hTdCngEnc->ho_hist_size, HO_HIST_SIZE ) ) { hTdCngEnc->ho_hist_size = HO_HIST_SIZE; @@ -1148,27 +2366,28 @@ void CNG_enc_fx( /* dithering bit for AMR-WB IO mode is always set to 0 */ IF( EQ_32( st_fx->core_brate, SID_1k75 ) ) { - push_indice_fx( hBstr, IND_DITHERING, 0, 1 ); + push_indice( hBstr, IND_DITHERING, 0, 1 ); } IF( EQ_32( st_fx->core_brate, SID_2k40 ) ) { IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) { - push_indice_fx( hBstr, IND_ACELP_16KHZ, 1, 1 ); + push_indice( hBstr, IND_ACELP_16KHZ, 1, 1 ); } ELSE { - push_indice_fx( hBstr, IND_ACELP_16KHZ, 0, 1 ); + push_indice( hBstr, IND_ACELP_16KHZ, 0, 1 ); } - push_indice_fx( hBstr, IND_CNG_HO, s_min( hTdCngEnc->burst_ho_cnt, 7 ), 3 ); + push_indice( hBstr, IND_CNG_HO, s_min( hTdCngEnc->burst_ho_cnt, HO_HIST_SIZE - 1 ), 3 ); hTdCngEnc->num_ho = m; move16(); - push_indice_fx( hBstr, IND_SID_TYPE, 0, 1 ); + push_indice( hBstr, IND_SID_TYPE, 0, 1 ); + test(); IF( LT_32( st_fx->input_Fs, 32000 ) && NE_16( st_fx->element_mode, IVAS_CPE_DFT ) ) { - push_indice_fx( hBstr, IND_SID_BW, 0, 1 ); + push_indice( hBstr, IND_SID_BW, 0, 1 ); *sid_bw = 0; move16(); } @@ -1192,10 +2411,12 @@ void CNG_enc_fx( ELSE { hDtxEnc->cng_cnt = add( hDtxEnc->cng_cnt, 1 ); + move16(); } return; } +#endif /*---------------------------------------------------------------------* * swb_CNG_enc() * @@ -1629,10 +2850,9 @@ void calculate_hangover_attenuation_gain_ivas_fx( test(); IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) { - Word32 exp = Mpy_32_16_1( L_mult( 26214 /*26214 = 1 / 160.f in Q22*/, st->hTdCngEnc->burst_ho_cnt ), st->hTdCngEnc->CNG_att_fx ); /* Q20 */ - - Word32 L_tmp = BASOP_Util_fPow( 1342177280 /* 10 in Q27 */, 4, exp, 11, &result_e ); - *att = extract_h( L_shl( L_tmp, result_e ) ); + Word32 exp = Mpy_32_16_1( L_mult( 26214 /*26214 = 1 / 160.f in Q22*/, st->hTdCngEnc->burst_ho_cnt ), st->hTdCngEnc->CNG_att_fx ); /* Q15 (22 + 1 + 7 - 15) */ + Word32 L_tmp = BASOP_Util_fPow( 1342177280 /* 10 in Q27 */, 4, exp, 16, &result_e ); + *att = extract_h( L_shl_sat( L_tmp, result_e ) ); move16(); } ELSE diff --git a/lib_enc/cod4t64_fast.c b/lib_enc/cod4t64_fast.c index d4a5fefa4c1f7439c57e46662319abaf14d2a4b0..85c5d157f5a98925a8736763778adac0ce821374 100644 --- a/lib_enc/cod4t64_fast.c +++ b/lib_enc/cod4t64_fast.c @@ -35,7 +35,9 @@ #include #include "cnst.h" #include "prot.h" +#include "prot_fx.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "rom_com.h" #include "wmc_auto.h" @@ -46,6 +48,9 @@ #define BETA_BN1 2.0f #define BETA_BN2 2.25f +#define BETA_BN1_FX 2 // Q0 +#define BETA_BN2_FX 9 // Q2 + #define L_SUBFR_MAX 2 * L_SUBFR #define MAX_NUM_INTER 5 #define MAX_PULSES_STEREO 5 @@ -55,6 +60,7 @@ *---------------------------------------------------------------------*/ /*! r: return index (N+1 bits) */ +#ifndef IVAS_FLOAT_FIXED static int16_t quant_1p_N1_L_subfr( const int16_t nb_pos, /* i : number of positions */ const int16_t pos, /* i : position of the pulse */ @@ -74,7 +80,27 @@ static int16_t quant_1p_N1_L_subfr( return index; } +#else +static Word16 quant_1p_N1_L_subfr( + const Word16 nb_pos, /* i : number of positions */ + const Word16 pos, /* i : position of the pulse */ + const Word16 N /* i : number of bits for position */ +) +{ + Word16 mask, index; + + mask = extract_l( L_sub( L_shl( 1, N ), 1 ) ); + + index = s_and( pos, mask ); + + if ( s_and( pos, nb_pos ) != 0 ) + { + index = add( index, shl( 1, N ) ); + } + return index; +} +#endif /*-------------------------------------------------------------------* * Function find_best_pulse() * @@ -110,6 +136,40 @@ static int16_t find_best_pulse( return m; } +static Word16 find_best_pulse_fx( + const Word16 L_subfr, + const Word16 nb_tracks, + const Word16 track, + const Word32 dn[], + const Word16 sign[], + Word16 *s ) +{ + Word16 m, i; + Word32 temp, max_val; + + max_val = MIN_32; + move32(); + m = track; + move16(); + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + temp = imult3216( dn[i], sign[i] ); + + IF( GE_32( temp, max_val ) ) + { + max_val = temp; + move32(); + m = i; + move16(); + } + } + + *s = sign[m]; + move16(); + + return m; +} + /*-------------------------------------------------------------------* * Function acelp_fast() @@ -749,3 +809,894 @@ void acelp_fast( return; } + +/*-------------------------------------------------------------------* + * Function acelp_fast() + * + * Fast algebraic codebook search. + * Supports 10, 15, 17, 20, 24, and 26 bits codebooks. + *-------------------------------------------------------------------*/ + +void acelp_fast_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 cdk_index, /* i : codebook index */ + const Word16 dn_orig[L_SUBFR], + /* i : corr. between target and h[]. */ // Q_new + 1 + Word16 Q_dn, + const Word16 cn[L_SUBFR], + /* i : residual after long term prediction */ // Q_new + 1 + const Word16 H[L_SUBFR], + /* i : impulse response of weighted synthesis filter */ // e(norm_s(H[0])+1) + Word16 code[L_SUBFR], + /* o : algebraic (fixed) codebook excitation */ // Q0 + Word16 y[], + /* o : filtered fixed codebook excitation */ // e(norm_s(H[0])+1) + const Word16 L_subfr /* i : subframe length */ +) +{ + Word16 i, j, q, bits, bits_track, nb_pos, nb_pulse, track, nb_iter, nb_tracks; + Word16 skip_track[MAX_NUM_INTER], skip_track_max; + PulseConfig config; + enum TRACKPOS codetrackpos; + Word16 m[MAX_PULSES_STEREO], s[MAX_PULSES_STEREO], m_max[MAX_PULSES_STEREO], s_max[MAX_PULSES_STEREO]; + Word16 track_order[NB_TRACK_FCB_4T * MAX_NUM_INTER], m0_track[NB_TRACK_FCB_4T]; + Word16 ind_stream[NPMAXPT * NB_TRACK_FCB_4T], idx; + Word16 G, G1, G2, G3, Gn, Gd; + Word16 y_tmp[L_SUBFR_MAX]; + Word32 dn[L_SUBFR_MAX]; + Word32 crit_num, crit_den, crit_num_max, crit_den_max, L_tmp1, L_tmp2; + Word16 q_crit_num, q_crit_den, q_crit_num_max, q_crit_den_max; + Word16 h_buf[4 * L_SUBFR_MAX], *h, *h_inv, *p_hn, alp_buf[2 * L_SUBFR_MAX], *alp, *alp_pos0, *alp_pos1, *alp_pos2, *alp_pos3; + Word32 dndn_fx, cncn_fx, cncn_track[NB_TRACK_FCB_4T]; + Word16 dndn_e, cncn_e, cncn_track_e[NB_TRACK_FCB_4T]; + Word16 s_coef_fx; + Word32 bn_orig_fx[L_SUBFR_MAX]; + Word32 max_val_fx, temp_fx, max_track[MAX_NUM_INTER]; + Word16 sign_fx[L_SUBFR_MAX]; + Word16 beta1_fx, beta2_fx; + Word16 exp, exp1, shift, q_H; + Word64 s64; + Word16 flag = 0; + move16(); + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + nb_iter = NB_TRACK_FCB_4T; + move16(); + nb_tracks = NB_TRACK_FCB_4T; + move16(); + nb_pulse = 0; /* to avoid compilation warnings */ + move16(); + + IF( EQ_16( L_subfr, L_SUBFR ) ) + { + config = PulseConfTable[cdk_index]; + bits = config.bits; + move16(); + nb_pulse = config.nb_pulse; + move16(); + codetrackpos = config.codetrackpos; + move16(); + + IF( EQ_16( cdk_index, 2 ) ) + { + /* 12 bits, 2 pulses, 2 tracks: 11 (used all tracks) */ + nb_tracks = NB_TRACK_FCB_2T; + move16(); + nb_iter = NB_TRACK_FCB_2T; + move16(); + } + ELSE IF( EQ_16( nb_pulse, 2 ) ) + { + /* 10 bits, 2 pulses, 4 tracks: 1010 (used only even tracks) */ + nb_iter = NB_TRACK_FCB_4T - 2; + move16(); + } + ELSE IF( EQ_16( nb_pulse, 3 ) ) + { + IF( EQ_16( codetrackpos, TRACKPOS_FIXED_FIRST ) ) + { + /* 15 bits, 3 pulses, 4 tracks: 1110 (fixed track to first) */ + nb_iter = NB_TRACK_FCB_4T - 1; + move16(); + } + ELSE IF( EQ_16( codetrackpos, TRACKPOS_FREE_THREE ) ) + { + /* 17 bits, 3 pulses, 4 tracks (used all tracks): 1110, 1101, 1011, 0111 */ + nb_iter = NB_TRACK_FCB_4T; + move16(); + } + } + } + ELSE /* L_subfr == 2*L_SUBFFR */ + { + bits = cdk_index; + move16(); + codetrackpos = -1; /* to avoid compilation warnings */ + move16(); + + + IF( EQ_16( cdk_index, 14 ) ) + { + /* 14 bits, 2 pulses, 2 tracks: 11 (used all tracks) */ + nb_pulse = 2; + move16(); + nb_iter = NB_TRACK_FCB_2T; + move16(); + codetrackpos = TRACKPOS_FIXED_TWO; + move16(); + nb_tracks = NB_TRACK_FCB_2T; + move16(); + } + ELSE IF( EQ_16( cdk_index, 12 ) ) + { + /* 12 bits, 2 pulses, 4 tracks: 1010 (used only even tracks) */ + nb_pulse = 2; + move16(); + nb_iter = NB_TRACK_FCB_4T - 2; + move16(); + codetrackpos = TRACKPOS_FIXED_EVEN; + move16(); + } + ELSE IF( EQ_16( cdk_index, 18 ) ) + { + /* 18 bits, 3 pulses, 4 tracks: 1110 (used first three tracks) */ + nb_pulse = 3; + move16(); + nb_iter = NB_TRACK_FCB_4T - 1; + move16(); + codetrackpos = TRACKPOS_FIXED_FIRST; + move16(); + } + ELSE IF( EQ_16( cdk_index, 20 ) ) + { + /* 20 bits, 3 pulses, 4 tracks (used all tracks): 1110, 1101, 1011, 0111 */ + nb_pulse = 3; + move16(); + nb_iter = NB_TRACK_FCB_4T; + move16(); + codetrackpos = TRACKPOS_FREE_THREE; + move16(); + } + ELSE IF( EQ_16( cdk_index, 24 ) ) + { + /* 24 bits, 4 pulses, 4 tracks: 1111 */ + nb_pulse = 4; + move16(); + nb_iter = NB_TRACK_FCB_4T; + move16(); + codetrackpos = TRACKPOS_FIXED_FIRST; + move16(); + } + } + + beta1_fx = BETA_BN1_FX; // Q0 + move16(); + beta2_fx = BETA_BN2_FX; // Q2 + move16(); + + IF( LE_16( cdk_index, 2 ) ) + { + beta1_fx = BETA_BN1_FX * 2; // Q0 + move16(); + beta2_fx = BETA_BN2_FX * 2; // Q2 + move16(); + } + + /*-----------------------------------------------------------------* + * Find signal bn[] and sign pre-selection vector sign[]. + *-----------------------------------------------------------------*/ + + exp = sub( Q31, shl( Q_dn, 1 ) ); + + dndn_fx = 21474836 /*0.01f in Q31 */; + move32(); + dndn_e = 0; + move16(); + FOR( i = 0; i < L_subfr; i++ ) + { + dndn_fx = BASOP_Util_Add_Mant32Exp( dndn_fx, dndn_e, L_mult0( dn_orig[i], dn_orig[i] ), exp, &dndn_e ); // Q(dndn_e) + } + + exp1 = sub( Q31, shl( sub( Q_dn, 1 ), 1 ) ); + + cncn_fx = 214748365 /* 0.1f in Q31 */; + move32(); + cncn_e = 0; + move16(); + + FOR( q = 0; q < nb_tracks; q++ ) + { + cncn_track[q] = 214748365 /* 0.1f in Q31 */; + move32(); + cncn_track_e[q] = 0; + move16(); + + FOR( i = 0; i < L_subfr; i += nb_tracks ) + { + cncn_track[q] = BASOP_Util_Add_Mant32Exp( cncn_track[q], cncn_track_e[q], L_mult0( cn[i + q], cn[i + q] ), exp1, &cncn_track_e[q] ); // Q(cncn_track_e[q]) + move16(); + } + cncn_fx = BASOP_Util_Add_Mant32Exp( cncn_fx, cncn_e, cncn_track[q], cncn_track_e[q], &cncn_e ); // Q(cncn_e) + } + + Word16 tmp; + s_coef_fx = BASOP_Util_Divide3232_Scale( dndn_fx, cncn_fx, &tmp ); + tmp = add( tmp, sub( dndn_e, cncn_e ) ); + s_coef_fx = Sqrt16( s_coef_fx, &tmp ); // Q(15 - tmp) + + + FOR( i = 0; i < L_subfr; i++ ) + { + bn_orig_fx[i] = L_mac0( L_shr( L_mult( s_coef_fx, cn[i] ), sub( 15, tmp ) ), beta1_fx, dn_orig[i] ); // Q_dn + move32(); + + IF( bn_orig_fx[i] >= 0 ) + { + sign_fx[i] = 1; + } + ELSE + { + sign_fx[i] = -1; + } + move16(); + } + + /*-----------------------------------------------------------------* + * Compute buffer h_buf[]. + *-----------------------------------------------------------------*/ + + h = h_buf; + h_inv = h_buf + shl( L_subfr, 1 ); + + FOR( i = 0; i < L_subfr; i++ ) + { + *h++ = 0; + move16(); + *h_inv++ = 0; + move16(); + } + + FOR( i = 0; i < L_subfr; i++ ) + { + h[i] = H[i]; + move16(); + h_inv[i] = -H[i]; + move16(); + } + + /*-----------------------------------------------------------------* + * Approximate FI[i][j] by alp[abs(i-j)] and compute buffer alp_buf[]. + *-----------------------------------------------------------------*/ + q_H = sub( 14, norm_s( H[0] ) ); + shift = sub( shl( q_H, 1 ), 6 ); + + alp = alp_buf + L_subfr; + + FOR( i = 0; i < L_subfr; i++ ) + { + s64 = 0; + move64(); + + FOR( j = i; j < L_subfr; j++ ) + { + s64 = W_mac0_16_16( s64, H[j], H[j - i] ); /* Q = shift + 6*/ + } + *alp = extract_l( W_extract_l( W_shr( s64, shift ) ) ); /*Q6*/ + move16(); + alp_buf[L_subfr - i] = *alp++; /*Q6*/ + move16(); + } + + alp = alp_buf + L_subfr; + + FOR( q = 0; q < nb_tracks; q++ ) + { + max_track[q] = 0; + move32(); + + FOR( i = q; i < L_subfr; i += nb_tracks ) + { + temp_fx = imult3216( bn_orig_fx[i], sign_fx[i] ); // Q_dn + + IF( GE_32( temp_fx, max_track[q] ) ) + { + max_track[q] = temp_fx; // Q_dn + move32(); + m0_track[q] = i; + move16(); + } + } + } + + /*-----------------------------------------------------------------* + * Track re-order + *-----------------------------------------------------------------*/ + + IF( EQ_16( nb_tracks, NB_TRACK_FCB_2T ) ) + { + track_order[0] = 0; + move16(); + track_order[1] = 1; + move16(); + track_order[2] = 1; + move16(); + track_order[3] = 0; + move16(); + } + ELSE + { + test(); + test(); + /* skip certain tracks if number of pulses is lower than number of tracks */ + IF( EQ_16( nb_pulse, 2 ) && EQ_16( nb_tracks, NB_TRACK_FCB_4T ) ) + { + max_track[NB_TRACK_FCB_4T - 3] = L_shl( -1, Q_dn ); // Q_dn + move32(); + max_track[NB_TRACK_FCB_4T - 1] = L_shl( -1, Q_dn ); // Q_dn + move32(); + } + ELSE IF( EQ_16( nb_pulse, 3 ) && EQ_16( codetrackpos, TRACKPOS_FIXED_FIRST ) ) + { + max_track[NB_TRACK_FCB_4T - 1] = L_shl( -1, Q_dn ); // Q_dn + move32(); + } + + FOR( q = 0; q < nb_tracks; q++ ) + { + i = maximum_32_fx( max_track, nb_tracks, &L_tmp1 ); + track_order[q] = i; + move16(); + max_track[i] = L_shl( -1, Q_dn ); // Q_dn + move32(); + } + + track_order[4] = track_order[1]; // Q0 + move16(); + track_order[5] = track_order[0]; // Q0 + move16(); + track_order[6] = track_order[2]; // Q0 + move16(); + track_order[7] = track_order[3]; // Q0 + move16(); + + track_order[8] = track_order[2]; // Q0 + move16(); + track_order[9] = track_order[0]; // Q0 + move16(); + track_order[10] = track_order[1]; // Q0 + move16(); + track_order[11] = track_order[3]; // Q0 + move16(); + + track_order[12] = track_order[3]; // Q0 + move16(); + track_order[13] = track_order[0]; // Q0 + move16(); + track_order[14] = track_order[1]; // Q0 + move16(); + track_order[15] = track_order[2]; // Q0 + move16(); + + IF( EQ_16( cdk_index, 3 ) ) + { + track_order[12] = track_order[2]; // Q0 + move16(); + track_order[13] = track_order[1]; // Q0 + move16(); + track_order[14] = track_order[0]; // Q0 + move16(); + + track_order[16] = track_order[1]; // Q0 + move16(); + track_order[17] = track_order[2]; // Q0 + move16(); + track_order[18] = track_order[0]; // Q0 + move16(); + nb_iter = 5; + move16(); + } + ELSE IF( EQ_16( cdk_index, 4 ) ) + { + track_order[16] = track_order[2]; // Q0 + move16(); + track_order[17] = track_order[3]; // Q0 + move16(); + track_order[18] = track_order[1]; // Q0 + move16(); + track_order[19] = track_order[0]; // Q0 + move16(); + nb_iter = 5; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Main searching loop + *-----------------------------------------------------------------*/ + + crit_num_max = MIN_32; // Q31 + move32(); + q_crit_num_max = Q31; + move16(); + crit_den_max = MAX_32; // Q31 + move32(); + q_crit_den_max = Q31; + move16(); + skip_track_max = -1; + move16(); + + FOR( q = 0; q < nb_iter; q++ ) + { + /*-----------------------------------------------------------------* + * First pulse search + *-----------------------------------------------------------------*/ + + track = track_order[q * nb_tracks]; // Q0 + move16(); + m[0] = m0_track[track]; // Q0 + move16(); + s[0] = sign_fx[m[0]]; // Q0 + move16(); + + /*-----------------------------------------------------------------* + * Second pulse search + *-----------------------------------------------------------------*/ + + IF( EQ_16( nb_tracks, NB_TRACK_FCB_2T ) ) + { + Gn = i_mult( s[0], shr( dn_orig[m[0]], 1 ) ); // Q_dn - 1 + Gd = alp[0]; // Q6 + move16(); + G = BASOP_Util_Divide1616_Scale( Gn, Gd, &exp1 ); // Q_dn -1 - 6 + 15 - exp1 = Q_dn - 6 + 14 - exp1 + G = i_mult( G, s[0] ); // Q_dn - 6 + 14 - exp1 + shift = sub( 14, exp1 ); + + track = track_order[q * nb_tracks + 1]; // Q0 + move16(); + alp_pos0 = alp - m[0] + track; + + FOR( i = track; i < L_subfr; i += NB_TRACK_FCB_2T ) + { + dn[i] = L_sub( L_deposit_l( dn_orig[i] ), L_shr( L_mult0( G, *alp_pos0 ), shift ) ); // Q_dn + move32(); + alp_pos0 = alp_pos0 + NB_TRACK_FCB_2T; + } + + m[1] = find_best_pulse_fx( L_subfr, NB_TRACK_FCB_2T, track, dn, sign_fx, &s[1] ); // Q0 + move16(); + } + ELSE + { + Gn = i_mult( s[0], shr( dn_orig[m[0]], 1 ) ); // Q_dn - 1 + Gd = alp[0]; // Q6 + move16(); + G = Gn; // Q_dn - 1 + move16(); + G = i_mult( G, s[0] ); // Q_dn - 1 + + track = track_order[q * nb_tracks + 1]; // Q0 + move16(); + alp_pos0 = alp - m[0] + track; // exp(shift) + + dndn_fx = 214748365 /* 0.1f in Q31 */; + move32(); + dndn_e = 0; + move16(); + + s64 = 0; + + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + dn[i] = L_shr( L_msu( L_mult0( Gd, dn_orig[i] ), G, *alp_pos0 ), 6 ); // Q_dn + move32(); + alp_pos0 += nb_tracks; + s64 = W_mac_32_32( s64, dn[i], dn[i] ); // 2 * Q_dn + 1 + } + exp1 = W_norm( s64 ); + dndn_fx = W_extract_h( W_shl( s64, exp1 ) ); // 2 * Q_dyn + exp1 - 31 + dndn_e = sub( 31, sub( add( shl( Q_dn, 1 ), exp ), 31 ) ); + + s_coef_fx = BASOP_Util_Divide3232_Scale( dndn_fx, cncn_track[track], &exp1 ); + exp1 = add( exp1, sub( dndn_e, cncn_track_e[track] ) ); + s_coef_fx = Sqrt16( s_coef_fx, &exp1 ); + exp1 = sub( exp1, shift ); + max_val_fx = MIN_16; + move16(); + m[1] = track; // Q0 + move16(); + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + dn[i] = L_add( L_shr( L_mult( s_coef_fx, cn[i] ), sub( 15, exp1 ) ), L_shr( imult3216( dn[i], beta2_fx ), 2 ) ); // Q_dn + move32(); + temp_fx = imult3216( dn[i], sign_fx[i] ); // Q_dn + + IF( GE_32( temp_fx, max_val_fx ) ) + { + max_val_fx = temp_fx; // Q_dn + move16(); + m[1] = i; + move16(); + } + } + + s[1] = sign_fx[m[1]]; + move16(); + } + + /*-----------------------------------------------------------------* + * Third pulse search + *-----------------------------------------------------------------*/ + + IF( GE_16( nb_pulse, 3 ) ) + { + Gn = add( Gn, i_mult( s[1], shr( dn_orig[m[1]], 1 ) ) ); // Q_dn -1 + Gd = add( Gd, add( alp[0], i_mult( i_mult( shl( s[0], 1 ), s[1] ), alp[m[0] - m[1]] ) ) ); // Q6 + G = Gn; // Q_dn - 1 + move16(); + G1 = i_mult( G, s[1] ); // Q_dn-1 + G = i_mult( G, s[0] ); // Q_dn-1 + + track = track_order[q * nb_tracks + 2]; // Q0 + move16(); + alp_pos0 = alp - m[0] + track; + alp_pos1 = alp - m[1] + track; + + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + dn[i] = L_shr( L_msu( L_msu0( L_mult0( Gd, dn_orig[i] ), G, *alp_pos0 ), G1, *alp_pos1 ), 6 ); // Q_dn + move32(); + alp_pos0 += nb_tracks; + alp_pos1 += nb_tracks; + } + + m[2] = find_best_pulse_fx( L_subfr, nb_tracks, track, dn, sign_fx, &s[2] ); // Q0 + move16(); + } + + /*-----------------------------------------------------------------* + * Fourth pulse search + *-----------------------------------------------------------------*/ + + IF( GE_16( nb_pulse, 4 ) ) + { + Gn = add( Gn, i_mult( s[2], shr( dn_orig[m[2]], 1 ) ) ); // Q_dn-1 + Gd = add( Gd, add( add( alp[0], i_mult( i_mult( shl( s[0], 1 ), s[2] ), alp[m[0] - m[2]] ) ), i_mult( i_mult( shl( s[1], 1 ), s[2] ), alp[m[1] - m[2]] ) ) ); // Q6 + G = Gn; // Q_dn-1 + move16(); + G1 = i_mult( G, s[1] ); // Q_dn-1 + G2 = i_mult( G, s[2] ); // Q_dn-1 + G = i_mult( G, s[0] ); // Q_dn-1 + + track = track_order[q * nb_tracks + 3]; + move16(); + alp_pos0 = alp - m[0] + track; + alp_pos1 = alp - m[1] + track; + alp_pos2 = alp - m[2] + track; + + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + dn[i] = L_shr( L_msu( L_msu( L_msu( L_mult0( Gd, dn_orig[i] ), G, *alp_pos0 ), G1, *alp_pos1 ), G2, *alp_pos2 ), 6 ); // Q_dn + move32(); + alp_pos0 += nb_tracks; + alp_pos1 += nb_tracks; + alp_pos2 += nb_tracks; + } + + m[3] = find_best_pulse_fx( L_subfr, nb_tracks, track, dn, sign_fx, &s[3] ); + move16(); + } + ELSE + { + skip_track[q] = track_order[q * nb_tracks + 3]; + move16(); + } + + /*-----------------------------------------------------------------* + * Fifth pulse search + *-----------------------------------------------------------------*/ + + IF( GE_16( nb_pulse, 5 ) ) + { + Gn = add( Gn, i_mult( s[3], shr( dn_orig[m[3]], 1 ) ) ); // Q_dn-1 + Gd = add( Gd, add( add( add( alp[0], i_mult( i_mult( shl( s[0], 1 ), s[3] ), alp[m[0] - m[3]] ) ), i_mult( i_mult( shl( s[1], 1 ), s[3] ), alp[m[1] - m[3]] ) ), i_mult( i_mult( shl( s[2], 1 ), s[3] ), alp[m[2] - m[3]] ) ) ); // Q6 + G = Gn; // Q_dn-1 + G1 = i_mult( G, s[1] ); // Q_dn-1 + G2 = i_mult( G, s[2] ); // Q_dn-1 + G3 = i_mult( G, s[3] ); // Q_dn-1 + G = i_mult( G, s[0] ); // Q_dn-1 + + IF( EQ_16( cdk_index, 6 ) ) + { + track = 0; /* always track 0 */ + move16(); + + alp_pos0 = alp - m[0]; + alp_pos1 = alp - m[1]; + alp_pos2 = alp - m[2]; + alp_pos3 = alp - m[3]; + + FOR( i = track; i < L_subfr; i += nb_tracks ) + { + dn[i] = L_shr( L_msu( L_msu( L_msu( L_msu( L_mult0( Gd, dn_orig[i] ), G, *alp_pos0 ), G1, *alp_pos1 ), G2, *alp_pos2 ), G3, *alp_pos3 ), 6 ); // Q_dn + move32(); + alp_pos0 += nb_tracks; + alp_pos1 += nb_tracks; + alp_pos2 += nb_tracks; + alp_pos3 += nb_tracks; + } + + m[4] = find_best_pulse_fx( L_subfr, nb_tracks, track, dn, sign_fx, &s[4] ); + move16(); + } + ELSE /* cdk_index == 7 (26 bits codebook) */ + { + alp_pos0 = alp - m[0]; + alp_pos1 = alp - m[1]; + alp_pos2 = alp - m[2]; + alp_pos3 = alp - m[3]; + + FOR( i = 0; i < L_subfr; i++ ) + { + dn[i] = L_shr( L_msu( L_msu( L_msu( L_msu( L_mult0( Gd, dn_orig[i] ), G, *alp_pos0 ), G1, *alp_pos1 ), G2, *alp_pos2 ), G3, *alp_pos3 ), 6 ); /*Q_dn*/ + move16(); + alp_pos0++; + alp_pos1++; + alp_pos2++; + alp_pos3++; + } + + i = emaximum_32fx( Q_dn, dn, L_subfr, &L_tmp1 ); + track = i % nb_tracks; + move16(); + + m[4] = find_best_pulse_fx( L_subfr, nb_tracks, track, dn, sign_fx, &s[4] ); + move16(); + } + skip_track[q] = track; + move16(); + } + + /*-----------------------------------------------------------------* + * - Build the filtered codeword and criterion computing. + * - Memorize the best code positions & signs, and the best filtered codevector. + *-----------------------------------------------------------------*/ + + crit_num = 0; + move32(); + set16_fx( y_tmp, 0, L_subfr ); + + FOR( j = 0; j < nb_pulse; j++ ) + { + IF( s[j] > 0 ) + { + p_hn = h - m[j]; + } + ELSE + { + p_hn = h_inv - m[j]; + } + + FOR( i = 0; i < L_subfr; i++ ) + { + y_tmp[i] = add( y_tmp[i], *p_hn++ ); // q_H + move16(); + } + + crit_num = L_mac0( crit_num, s[j], dn_orig[m[j]] ); // Q_dn + } + + s64 = W_mult0_32_32( crit_num, crit_num ); // 2*Q_dn + exp = W_norm( s64 ); + crit_num = W_extract_h( W_shl( s64, exp ) ); // 2*Q_dn + exp - 32 + q_crit_num = add( shl( Q_dn, 1 ), sub( exp, 32 ) ); + + // crit_den = sum2_fx( y_tmp, L_subfr ); // 2*q_H + s64 = 0; + move64(); + FOR( i = 0; i < L_subfr; i++ ) + { + s64 = W_mac0_16_16( s64, y_tmp[i], y_tmp[i] ); + } + exp1 = W_norm( s64 ); + crit_den = W_extract_h( W_shl( s64, exp1 ) ); // 2*q_H + exp1 - 32 + q_crit_den = add( shl( q_H, 1 ), sub( exp1, 32 ) ); + + L_tmp1 = Mpy_32_32( crit_num, crit_den_max ); + exp = sub( add( q_crit_num, q_crit_den_max ), 31 ); + L_tmp2 = Mpy_32_32( crit_den, crit_num_max ); + exp1 = sub( add( q_crit_den, q_crit_num_max ), 31 ); + + IF( GT_16( exp, exp1 ) ) + { + IF( GE_32( L_shr( L_tmp1, sub( exp, exp1 ) ), L_tmp2 ) ) + { + flag = 1; + move16(); + } + ELSE + { + flag = 0; + move16(); + } + } + ELSE + { + IF( GE_32( L_tmp1, L_shr( L_tmp2, sub( exp1, exp ) ) ) ) + { + flag = 1; + move16(); + } + ELSE + { + flag = 0; + move16(); + } + } + + + IF( flag ) + { + crit_num_max = crit_num; + move32(); + q_crit_num_max = q_crit_num; + move16(); + crit_den_max = crit_den; + move32(); + q_crit_den_max = q_crit_den; + move16(); + + FOR( j = 0; j < nb_pulse; j++ ) + { + m_max[j] = m[j]; + move16(); + s_max[j] = s[j]; + move16(); + } + + Copy( y_tmp, y, L_subfr ); // q_H + skip_track_max = skip_track[q]; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Reconstruct the best codevector, + * compute index of codevector and write it into the bitstream. + *-----------------------------------------------------------------*/ + + set16_fx( code, 0, L_subfr ); + FOR( q = 0; q < nb_pulse; q++ ) + { + code[m_max[q]] = add( code[m_max[q]], s_max[q] ); // Q0 + move16(); + } + test(); + IF( EQ_16( bits, 12 ) || EQ_16( bits, 14 ) ) + { + /* 12 bits, 2 pulses, 2 tracks 11 used all tracks */ + i = 6; + move16(); + j = 0x800; + move16(); + q = 0x20; + move16(); + + IF( EQ_16( L_subfr, 2 * L_SUBFR ) ) + { + /* 14 bits, 2 pulses, 2 tracks: 11 (used all tracks) */ + i = 7; + move16(); + j = 0x2000; + move16(); + q = 0x40; + move16(); + } + + IF( EQ_16( m_max[0] % NB_TRACK_FCB_2T, 1 ) ) + { + idx = add( shl( shr( m_max[1], 1 ), i ), shr( m_max[0], 1 ) ); + + if ( s_max[1] < 0 ) + { + idx = add( idx, j ); + } + + if ( s_max[0] < 0 ) + { + idx = add( idx, q ); + } + } + ELSE + { + idx = add( shl( shr( m_max[0], 1 ), i ), shr( m_max[1], 1 ) ); + + if ( s_max[0] < 0 ) + { + idx = add( idx, j ); + } + + if ( s_max[1] < 0 ) + { + idx = add( idx, q ); + } + } + + push_indice( hBstr, IND_ALG_CDBK_2T32, idx, bits ); + } + ELSE + { + /* compute index of codevector */ + set16_fx( ind_stream, -1, i_mult( NPMAXPT, nb_tracks ) ); + + bits_track = 4; + move16(); + nb_pos = NB_POS_FCB_4T; + move16(); + + IF( EQ_16( L_subfr, 2 * L_SUBFR ) ) + { + bits_track = 5; + move16(); + nb_pos = NB_POS_FCB_4T_128; + move16(); + } + + FOR( q = 0; q < nb_pulse; q++ ) + { + i = i_mult( m_max[q] % NB_TRACK_FCB_4T, NPMAXPT ); /* track number */ + if ( ind_stream[i] >= 0 ) + { + i = add( i, 1 ); + } + ind_stream[i] = shr( m_max[q], 2 ); // / NB_TRACK_FCB_4T; /* pos of pulse */ + move16(); + + IF( s_max[q] < 0 ) + { + ind_stream[i] = add( ind_stream[i], nb_pos ); + move16(); + } + } + + test(); + IF( EQ_16( codetrackpos, TRACKPOS_FREE_THREE ) || EQ_16( codetrackpos, TRACKPOS_FREE_ONE ) ) + { + push_indice( hBstr, IND_ALG_CDBK_4T64, skip_track_max, 2 ); + } + + IF( LT_16( nb_pulse, 5 ) ) + { + FOR( q = 0; q < NB_TRACK_FCB_4T; q++ ) + { + j = i_mult( q, NPMAXPT ); + IF( NE_16( ind_stream[j], -1 ) ) + { + idx = quant_1p_N1_L_subfr( nb_pos, ind_stream[j], bits_track ); + push_indice( hBstr, IND_ALG_CDBK_4T64, idx, add( bits_track, 1 ) ); + } + } + } + ELSE + { + FOR( q = 0; q < NB_TRACK_FCB_4T; q++ ) + { + j = i_mult( q, NPMAXPT ); + IF( EQ_16( q, skip_track_max ) ) + { + idx = quant_2p_2N1( ind_stream[j], ind_stream[j + 1], bits_track ); + push_indice( hBstr, IND_ALG_CDBK_4T64, idx, add( shl( bits_track, 1 ), 1 ) ); + } + ELSE + { + idx = quant_1p_N1_L_subfr( nb_pos, ind_stream[j], bits_track ); + push_indice( hBstr, IND_ALG_CDBK_4T64, idx, add( bits_track, 1 ) ); + } + } + } + } + + return; +} diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c index edffd41358c27812810e82788e935a62e50f4ecc..4508bfb64bc3b1c81ca9091215c86bf6a56265f0 100644 --- a/lib_enc/cod_tcx.c +++ b/lib_enc/cod_tcx.c @@ -103,9 +103,656 @@ void HBAutocorrelation( * *-------------------------------------------------------------------*/ -#define SIMILAR_TNS_THRESHOLD ( 0.04f ) -#define TNS_GAIN_THRESHOLD_FOR_WHITE ( 3.0f ) +#define SIMILAR_TNS_THRESHOLD ( 0.04f ) +#define SIMILAR_TNS_THRESHOLD_FX_IN_Q15 ( 1311 ) +#define TNS_GAIN_THRESHOLD_FOR_WHITE ( 3.0f ) +#define TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ( 384 ) +#ifdef IVAS_FLOAT_FIXED +void TNSAnalysisStereo_fx( + Encoder_State **sts, /* i : encoder state handle */ + Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* o : MDST spectrum Qx*/ + const Word16 bWhitenedDomain, /* i : whitened domain flag Q0*/ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : number of tns parameters put into prm Q0*/ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : number of tns bits in the frame Q0*/ + Word16 param_core[][NB_DIV * NPRM_DIV], /* o : TNS parameters Q0*/ + const Word16 mct_on /* i : flag mct block (1) or stereo (0) Q0*/ +) +{ + Word16 ch, k, L_spec, L_frame, nSubframes, iFilter; + Word32 *spectrum_fx; + Encoder_State *st = NULL; + TCX_ENC_HANDLE hTcxEnc = NULL; + Word16 individual_decision[NB_DIV]; + Word16 maxPredictionGain_fx = 0, meanPredictionGain_fx; + move16(); + + individual_decision[0] = 0; + move16(); + individual_decision[1] = 0; + move16(); + L_spec = -1; + move16(); + L_frame = -1; + move16(); + + /* TNS filter analysis, loop over channels */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } + + hTcxEnc = st->hTcxEnc; + + IF( EQ_16( hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; k++ ) + { + /* reset tns on whitened domain flag */ + IF( !bWhitenedDomain ) + { + hTcxEnc->bTnsOnWhithenedSpectra[k] = 0; + move16(); + hTcxEnc->fUseTns[k] = 0; + move16(); + } + test(); + test(); + IF( st->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + spectrum_fx = hTcxEnc->spectrum_fx[k]; + + L_frame = hTcxEnc->L_frameTCX; + move16(); + st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( st->last_core == ACELP_CORE )]; + L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]; + move16(); + /*-----------------------------------------------------------* + * Temporal Noise Shaping analysis * + *-----------------------------------------------------------*/ + + IF( hTcxEnc->transform_type[k] == TCX_5 ) + { + /* rearrange LF sub-window lines prior to TNS analysis & filtering */ + tcx5TnsGrouping_fx( shr( L_frame, 2 ), shr( L_spec, 1 ), spectrum_fx ); + } + + /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */ + + ResetTnsData( &hTcxEnc->tnsData[k] ); + if ( st->hTcxCfg->pCurrentTnsConfig->maxOrder <= 0 ) + { + break; + } + + CalculateTnsFilt_fx( st->hTcxCfg->pCurrentTnsConfig, spectrum_fx, &hTcxEnc->tnsData[k], NULL ); + } + } + } + + IF( !mct_on ) + { + /* TNS decision */ + /* if framing differs between channels, keep the filter decision per channel */ + test(); + test(); + IF( ( NE_16( sts[0]->hTcxEnc->transform_type[0], sts[1]->hTcxEnc->transform_type[0] ) && + NE_16( sts[0]->hTcxEnc->transform_type[1], sts[1]->hTcxEnc->transform_type[1] ) ) || + NE_16( sts[0]->hTcxCfg->fIsTNSAllowed, sts[1]->hTcxCfg->fIsTNSAllowed ) ) + { + individual_decision[0] = individual_decision[1] = 1; + move16(); + move16(); + } + ELSE IF( bWhitenedDomain ) + { + IF( EQ_16( sts[0]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( k = 0; k < nSubframes; k++ ) + { + IF( NE_16( sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k], sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + individual_decision[k] = 1; + move16(); + } + } + } + + /* framing equal, check for similar filters, if very similar (also indicator for and M signal), + * use at least the same decision, maybe use the same filter + */ + { + Word8 isTCX10; + + IF( EQ_16( sts[0]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + isTCX10 = 0; + } + ELSE + { + nSubframes = NB_DIV; + isTCX10 = 1; + } + move16(); + move16(); + FOR( k = 0; k < nSubframes; k++ ) + { + test(); + test(); + test(); + IF( sts[0]->hTcxCfg->fIsTNSAllowed && NE_16( individual_decision[k], 1 ) && ( !bWhitenedDomain || sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + Word16 maxPredGain_fx = -ONE_IN_Q7; + move16(); + sts[0]->hTcxCfg->pCurrentTnsConfig = &sts[0]->hTcxCfg->tnsConfig[sts[0]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[0]->last_core == ACELP_CORE )]; + sts[1]->hTcxCfg->pCurrentTnsConfig = &sts[1]->hTcxCfg->tnsConfig[sts[1]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[1]->last_core == ACELP_CORE )]; + + FOR( iFilter = sub( sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + STnsFilter *pFilter[2]; + struct TnsParameters const *pTnsParameters[2]; + pFilter[0] = sts[0]->hTcxEnc->tnsData[k].filter + iFilter; + pTnsParameters[0] = sts[0]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter; + pFilter[1] = sts[1]->hTcxEnc->tnsData[k].filter + iFilter; + pTnsParameters[1] = sts[1]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter; + + /* if prediction gain and avgSqrCoef are both close we are pretty sure the filters are quite similar, use the avg of + * both filters for the decision + */ + + meanPredictionGain_fx = mac_r( L_mult( pFilter[0]->predictionGain, 16384 ), pFilter[1]->predictionGain, 16384 ); // Q7 + maxPredictionGain_fx = s_max( maxPredictionGain_fx, meanPredictionGain_fx ); // Q7 + + test(); + test(); + test(); + IF( GT_16( pFilter[0]->predictionGain, pTnsParameters[0]->minPredictionGain ) && LT_32( sts[0]->element_brate, IVAS_80k ) && + GT_16( pFilter[1]->predictionGain, pTnsParameters[1]->minPredictionGain ) && EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) + { + pFilter[0]->predictionGain = pFilter[1]->predictionGain = meanPredictionGain_fx; /* more TNS filter sync at 48kbps */ + move16(); + move16(); + } + test(); + IF( LT_16( abs_s( sub( pFilter[0]->predictionGain, pFilter[1]->predictionGain ) ), mult( SIMILAR_TNS_THRESHOLD_FX_IN_Q15, meanPredictionGain_fx ) ) && + ( sts[0]->hTcxEnc->tnsData[k].nFilters == sts[1]->hTcxEnc->tnsData[k].nFilters ) ) + { + Word16 maxAvgSqrCoef_fx = s_max( pFilter[0]->avgSqrCoef, pFilter[1]->avgSqrCoef ); // Q15 + Word16 meanLtpGain_fx = add( shr( sts[0]->hTcxEnc->tcxltp_gain, 1 ), shr( sts[1]->hTcxEnc->tcxltp_gain, 1 ) ); + maxPredGain_fx = s_max( maxPredGain_fx, meanPredictionGain_fx ); + test(); + test(); + IF( GT_16( meanPredictionGain_fx, pTnsParameters[0]->minPredictionGain ) || GT_16( maxAvgSqrCoef_fx, pTnsParameters[0]->minAvgSqrCoef ) ) + { + test(); + test(); + test(); + IF( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 || sts[1]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || LT_16( meanLtpGain_fx, 19660 /* 0.6 in Q15*/ ) ) + { + ++sts[0]->hTcxEnc->tnsData[k].nFilters; + pFilter[0]->filterType = TNS_FILTER_ON; + move16(); + ++sts[1]->hTcxEnc->tnsData[k].nFilters; + pFilter[1]->filterType = TNS_FILTER_ON; + move16(); + } + ELSE + { + Word16 maxEnergyChange_fx; + maxEnergyChange_fx = shr( add( GetTCXMaxenergyChange_ivas_fx( sts[0]->hTranDet, isTCX10, NSUBBLOCKS, 3 ), GetTCXMaxenergyChange_ivas_fx( sts[1]->hTranDet, isTCX10, NSUBBLOCKS, 3 ) ), 1 ); + + IF( GE_16( maxEnergyChange_fx, pTnsParameters[0]->minEnergyChange ) ) + { + ++sts[0]->hTcxEnc->tnsData[k].nFilters; + pFilter[0]->filterType = TNS_FILTER_ON; + move16(); + ++sts[1]->hTcxEnc->tnsData[k].nFilters; + pFilter[1]->filterType = TNS_FILTER_ON; + move16(); + } + ELSE + { + pFilter[0]->filterType = TNS_FILTER_OFF; + move16(); + pFilter[1]->filterType = TNS_FILTER_OFF; + move16(); + } + } + } + ELSE IF( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 && sts[1]->hTcxEnc->tnsData[k].nFilters > 0 ) /* If a previous filter is turned on */ + { + pFilter[0]->filterType = TNS_FILTER_ON_ZERO; + pFilter[1]->filterType = TNS_FILTER_ON_ZERO; + ++sts[0]->hTcxEnc->tnsData[k].nFilters; + ++sts[1]->hTcxEnc->tnsData[k].nFilters; + } + ELSE IF( NE_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) /* sanity check */ + { + assert( 0 ); + } + ELSE + { + pFilter[0]->filterType = TNS_FILTER_OFF; + move16(); + pFilter[1]->filterType = TNS_FILTER_OFF; + move16(); + } + + test(); + test(); + IF( EQ_16( pFilter[0]->filterType, TNS_FILTER_ON ) && EQ_16( pFilter[1]->filterType, TNS_FILTER_ON ) && LT_32( sts[0]->element_brate, IVAS_80k ) ) + { + Word16 tmpIntValue = 0; + move16(); + Word16 tmpCoeff[TNS_MAX_FILTER_ORDER]; + Word16 i, maxOrder = s_max( pFilter[0]->order, pFilter[1]->order ); + + set16_fx( tmpCoeff, 0, TNS_MAX_FILTER_ORDER ); + FOR( i = 0; i < maxOrder; i++ ) + { + tmpIntValue = s_max( tmpIntValue, abs_s( sub( pFilter[0]->coefIndex[i], pFilter[1]->coefIndex[i] ) ) ); + } + + IF( EQ_16( tmpIntValue, 1 ) ) /* the TNS coefficients are sufficiently similar to equalize the two filters */ + { + FOR( i = sub( maxOrder, 1 ); i >= 0; i-- ) + { + IF( LT_16( abs_s( pFilter[0]->coefIndex[i] ), abs_s( pFilter[1]->coefIndex[i] ) ) ) + { + tmpCoeff[i] = pFilter[0]->coefIndex[i]; + } + ELSE + { + tmpCoeff[i] = pFilter[1]->coefIndex[i]; + } + move16(); + IF( ( tmpIntValue > 0 ) && ( tmpCoeff[i] == 0 ) ) + { + maxOrder = sub( maxOrder, 1 ); + } + ELSE + { + tmpIntValue = 0; + move16(); + } + } + /* make sure that maxOrder is non zero and not all coefficients are zero (could happen in rare cases) */ + IF( maxOrder > 0 ) + { + FOR( i = TNS_MAX_FILTER_ORDER - 1; i >= 0; i-- ) + { + pFilter[0]->coefIndex[i] = pFilter[1]->coefIndex[i] = tmpCoeff[i]; + move16(); + move16(); + } + + pFilter[0]->order = pFilter[1]->order = maxOrder; + move16(); + move16(); + } + } + } + } + ELSE + { + individual_decision[k] = 1; + move16(); + } + } + + IF( individual_decision[k] == 0 ) + { + IF( ( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 ) ) + { + sts[0]->hTcxEnc->fUseTns[k] = 1; + } + ELSE + { + sts[0]->hTcxEnc->fUseTns[k] = 0; + } + move16(); + + IF( ( sts[1]->hTcxEnc->tnsData[k].nFilters > 0 ) ) + { + sts[1]->hTcxEnc->fUseTns[k] = 1; + } + ELSE + { + sts[1]->hTcxEnc->fUseTns[k] = 0; + } + move16(); + } + ELSE + { + sts[0]->hTcxEnc->tnsData[k].nFilters = 0; + move16(); + sts[1]->hTcxEnc->tnsData[k].nFilters = 0; + move16(); + sts[0]->hTcxEnc->fUseTns[k] = 0; + move16(); + sts[1]->hTcxEnc->fUseTns[k] = 0; + move16(); + FOR( iFilter = sub( sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + sts[0]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF; + move16(); + sts[1]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF; + move16(); + } + } + test(); + test(); + test(); + IF( !bWhitenedDomain && individual_decision[k] == 0 && LT_16( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ) && NE_16( sts[0]->hTcxEnc->transform_type[k], TCX_5 ) ) + { + sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1; + move16(); + sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1; + move16(); + sts[0]->hTcxEnc->tnsData[k].nFilters = 0; + move16(); + sts[1]->hTcxEnc->tnsData[k].nFilters = 0; + move16(); + sts[0]->hTcxEnc->fUseTns[k] = 0; + move16(); + sts[1]->hTcxEnc->fUseTns[k] = 0; + move16(); + FOR( iFilter = sub( sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + ClearTnsFilterCoefficients( sts[0]->hTcxEnc->tnsData[k].filter + iFilter ); + ClearTnsFilterCoefficients( sts[1]->hTcxEnc->tnsData[k].filter + iFilter ); + } + } + maxPredictionGain_fx = s_max( maxPredictionGain_fx, maxPredGain_fx ); + } + } + } + } + + /* individual decision for each channel */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + Word8 isTCX10; + + IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + isTCX10 = 0; + } + ELSE + { + nSubframes = NB_DIV; + isTCX10 = 1; + } + move16(); + move16(); + + FOR( k = 0; k < nSubframes; k++ ) + { + test(); + test(); + test(); + test(); + IF( sts[ch]->hTcxCfg->fIsTNSAllowed && ( individual_decision[k] || mct_on ) && + ( !bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + Word16 maxPredGain_fx = -ONE_IN_Q7; // Q7 + move16(); + sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[ch]->last_core == ACELP_CORE )]; + + FOR( iFilter = sub( sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + STnsFilter *pFilter; + struct TnsParameters const *pTnsParameters; + pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter; + pTnsParameters = sts[ch]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter; + + maxPredGain_fx = s_max( maxPredGain_fx, pFilter->predictionGain ); + test(); + IF( GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ) || GT_16( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) ) + { + test(); + test(); + IF( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || LT_16( sts[ch]->hTcxEnc->tcxltp_gain, 19660 ) ) + { + ++sts[ch]->hTcxEnc->tnsData[k].nFilters; + pFilter->filterType = TNS_FILTER_ON; + move16(); + } + ELSE + { + Word16 maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( sts[ch]->hTranDet, isTCX10, NSUBBLOCKS, 3 ); + + IF( GE_16( maxEnergyChange_fx, pTnsParameters->minEnergyChange ) ) + { + ++sts[ch]->hTcxEnc->tnsData[k].nFilters; + pFilter->filterType = TNS_FILTER_ON; + } + ELSE + { + pFilter->filterType = TNS_FILTER_OFF; + } + move16(); + } + } + ELSE IF( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 ) /* If a previous filter is turned on */ + { + pFilter->filterType = TNS_FILTER_ON_ZERO; + move16(); + ++sts[ch]->hTcxEnc->tnsData[k].nFilters; + } + ELSE + { + pFilter->filterType = TNS_FILTER_OFF; + move16(); + } + } + + IF( ( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 ) ) + { + sts[ch]->hTcxEnc->fUseTns[k] = 1; + } + ELSE + { + sts[ch]->hTcxEnc->fUseTns[k] = 0; + } + move16(); + test(); + test(); + IF( !bWhitenedDomain && LT_16( maxPredGain_fx, TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ) && NE_16( sts[ch]->hTcxEnc->transform_type[k], TCX_5 ) ) + { + sts[ch]->hTcxEnc->fUseTns[k] = 0; + move16(); + sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1; + move16(); + sts[ch]->hTcxEnc->tnsData[k].nFilters = 0; + move16(); + FOR( iFilter = sub( sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter ); + sts[ch]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF; + move16(); + } + } + maxPredictionGain_fx = s_max( maxPredictionGain_fx, maxPredGain_fx ); + } + } + } + + + /* we have the decision, set filter data accordingly */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( EQ_16( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } + + IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( k = 0; k < nSubframes; k++ ) + { + test(); + test(); + IF( sts[ch]->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[ch]->last_core == ACELP_CORE )]; + + FOR( iFilter = sub( sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + STnsFilter *pFilter; + pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter; + SWITCH( pFilter->filterType ) + { + case TNS_FILTER_OFF: + ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter ); + BREAK; + case TNS_FILTER_ON_ZERO: + /* Since TNS filter of order 0 is not allowed we have to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */ + ClearTnsFilterCoefficients( pFilter ); + pFilter->order = 1; + move16(); + BREAK; + } + } + } + } + } + + /* Apply filters, loop over channels */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; k++ ) + { + test(); + test(); + test(); + test(); + IF( bWhitenedDomain && ( ch > 0 ) && /* test for identical TNS filter data in both channels */ + sts[0]->hTcxCfg->fIsTNSAllowed && sts[0]->hTcxEnc->fUseTns[k] && + sts[1]->hTcxCfg->fIsTNSAllowed && sts[1]->hTcxEnc->fUseTns[k] ) + { + Word16 equalFilterData = 0; + move16(); + test(); + test(); + if ( EQ_16( sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, sts[1]->hTcxCfg->pCurrentTnsConfig->nMaxFilters ) && + EQ_16( sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k], sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) && + EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) + { + equalFilterData = 1; + move16(); + } + + IF( equalFilterData ) + { + FOR( iFilter = sub( st->hTcxCfg->pCurrentTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + const Word16 *pDataCh0 = (const Word16 *) &sts[0]->hTcxEnc->tnsData[k].filter[iFilter]; + const Word16 *pDataCh1 = (const Word16 *) &sts[1]->hTcxEnc->tnsData[k].filter[iFilter]; + Word16 i = 2 + TNS_MAX_FILTER_ORDER; /* excl. informative float data. Portable? */ + + move16(); + test(); + WHILE( ( i >= 0 ) && EQ_16( pDataCh0[i], pDataCh1[i] ) ) + { + i = sub( i, 1 ); + } + if ( i >= 0 ) + { + equalFilterData = 0; + move16(); + break; + } + } + IF( equalFilterData ) + { + st->hTcxEnc->tnsData[k].nFilters = i_mult( st->hTcxEnc->tnsData[k].nFilters, -1 ); /* signals common TNS */ + } + } + } + test(); + test(); + IF( st->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || st->hTcxEnc->bTnsOnWhithenedSpectra[k] ) ) + { + L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]; + move16(); + spectrum_fx = st->hTcxEnc->spectrum_fx[k]; + /* If TNS should be used then get the residual after applying it inplace in the spectrum */ + IF( st->hTcxEnc->fUseTns[k] ) + { + st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[st->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( st->last_core == ACELP_CORE )]; + + ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], spectrum_fx, 1 ); + } + + IF( EQ_16( st->hTcxEnc->transform_type[k], TCX_5 ) ) + { + tcx5TnsUngrouping_fx( shr( L_frame, 2 ), shr( L_spec, 1 ), st->hTcxEnc->spectrum_fx[k], ENC ); + } + + st->hTcxEnc->tnsData[k].tnsOnWhitenedSpectra = st->hTcxEnc->bTnsOnWhithenedSpectra[k]; + + EncodeTnsData_ivas_fx( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], param_core[ch] + k * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, tnsSize[ch] + k, tnsBits[ch] + k ); + } + + IF( EQ_16( st->hTcxEnc->transform_type[k], TCX_5 ) ) + { + tcx5SpectrumInterleaving_fx( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum_fx[k] ); + tcx5SpectrumInterleaving_fx( st->hTcxCfg->tcx5SizeFB, mdst_spectrum_fx[ch][k] ); + } + } + } + return; +} +#endif void TNSAnalysisStereo( Encoder_State **sts, /* i : encoder state handle */ float *mdst_spectrum[CPE_CHANNELS][NB_DIV], /* o : MDST spectrum */ @@ -567,7 +1214,6 @@ void TNSAnalysisStereo( return; } - /*-------------------------------------------------------------------* * TNSAnalysis() * @@ -652,6 +1298,7 @@ void TNSAnalysis( } +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * ShapeSpectrum() * @@ -828,6 +1475,7 @@ void ShapeSpectrum( return; } +#endif /*-------------------------------------------------------------------* @@ -858,6 +1506,7 @@ static int16_t GetTransWidth( } +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------* * EstimateTCXNoiseLevel() * @@ -917,6 +1566,7 @@ static void EstimateTCXNoiseLevel( return; } +#endif /*-----------------------------------------------------------* @@ -1012,6 +1662,7 @@ void EstimateStereoTCXNoiseLevel( } +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------* * DecideTonalSideInfo() * @@ -1560,7 +2211,7 @@ void QuantizeTCXSpectrum( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS if ( st->hTdCngEnc != NULL ) { - st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); } #endif calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); @@ -1970,6 +2621,7 @@ void InternalTCXDecoder( return; } + /*-------------------------------------------------------------------* * QuantizeSpectrum() * @@ -2147,6 +2799,7 @@ void coder_tcx( return; } +#endif /*-------------------------------------------------------------------* * coder_tcx_post() diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index a1282c7e9867030dd2518104cf26cbae72f9ce19..e449b2420f5dbaef56632161f91ecc9af430191e 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -15,9 +15,12 @@ //#include "basop_mpy.h" #include "prot_fx_enc.h" #ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#include +#include "prot.h" #include "ivas_prot.h" #include "ivas_prot_fx.h" #include "ivas_rom_com_fx.h" +#include "prot.h" #endif #ifdef DEBUGGING #include "debug.h" @@ -1046,6 +1049,282 @@ void ShapeSpectrum_fx( PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e ); } } +#ifdef IVAS_FLOAT_FIXED +void ShapeSpectrum_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1], Q = 14 - norm(A[0]) */ + Word16 gainlpc[], /* output: MDCT gains for the previous frame */ + Word16 gainlpc_e[], /* output: MDCT gains exponents */ + Word16 L_frame_glob, /* input: frame length */ + Word16 L_spec, + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + Word8 pfUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State *st, + Word32 *scf /* Q16 */ +) +{ + Word16 L_frame; + Word16 Ap[M + 2]; + Word16 gamma1; + Word16 gainlpc_noinv[FDNS_NPTS]; + Word16 gainlpc_noinv_e[FDNS_NPTS]; + Word32 sns_int_scf[FDNS_NPTS]; + Word16 i; + Word16 q_spectrum; + Word32 max_low_pre = 0, max_high_pre = 0; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + move32(); + move32(); + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + move16(); + gamma1 = st->gamma; + move16(); + if ( st->enableTcxLpc != 0 ) + { + gamma1 = 0x7FFF; + move16(); + } + + /* if past frame is ACELP */ + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) /* in MDCT, this is already done outside the function */ + { + IF( st->last_core == ACELP_CORE ) + { + L_frame = add( L_frame, hTcxCfg->tcx_offset ); + L_spec = add( L_spec, shr( hTcxCfg->tcx_coded_lines, 2 ) ); + IF( hTcxCfg->lfacNext < 0 ) + { + L_frame = sub( L_frame, hTcxCfg->lfacNext ); + move16(); + } + } + } + + test(); + tcxGetNoiseFillingTilt( A, + M, + L_frame, + ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 ), + &hTcxEnc->noiseTiltFactor ); + + /* Calculate Spectrum Flatness Measure for the TCX Concealment */ + IF( st->enablePlcWaveadjust ) + { + hTcxCfg->SFM2 = SFM_Cal_fx( spectrum, s_min( 200, L_frame ) ); + move32(); + } + + test(); + IF( LE_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) + { + max_low_pre = 0; + move32(); + FOR( i = 0; i < L_frame; i++ ) + { + Word32 tmp = L_abs( spectrum[i] ); + if ( GT_32( tmp, max_low_pre ) ) + { + max_low_pre = tmp; + move32(); + } + } + + max_high_pre = 0; + move32(); + FOR( i = 0; i < L_spec - L_frame; i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame + i] ); + if ( GT_32( tmp, max_high_pre ) ) + { + max_high_pre = tmp; + move32(); + } + } + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Word64 W_tmp; + Word16 len; + q_spectrum = sub( 31, *spectrum_e ); + sns_interpolate_scalefactors_fx( &sns_int_scf[0], scf, ENC ); + sns_shape_spectrum_fx( spectrum, &q_spectrum, st->hTcxCfg->psychParamsCurrent, &sns_int_scf[0], Q16, L_frame, &len ); // The output spectrum from sns_shape_spectrum_fx has Q = q_spectrum + 1 + + test(); + test(); + IF( NE_16( len, L_spec ) && LT_16( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) ) + { + scale_sig32( spectrum + len, sub( L_spec, len ), sub( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) ); + } + ELSE IF( NE_16( len, L_spec ) && GT_16( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) ) + { + scale_sig32( spectrum, len, sub( sub( 31, *spectrum_e ), add( q_spectrum, 1 ) ) ); + q_spectrum = sub( 31 - 1, *spectrum_e ); + } + + FOR( i = L_frame; i < L_spec; i++ ) + { + W_tmp = W_mult0_32_32( spectrum[i], sns_int_scf[hTcxCfg->psychParamsCurrent->nBands - 1] ); + W_tmp = W_shr( W_tmp, Q16 ); + spectrum[i] = W_extract_l( W_tmp ); + move32(); + } + *spectrum_e = sub( 31 - 1, q_spectrum ); // As the output spectrum from sns_shape_spectrum_fx has Q = q_spectrum + 1 + move16(); + } + ELSE + { + /*-----------------------------------------------------------* + * Pre-shaping in frequency domain using weighted LPC (Wz) * + *-----------------------------------------------------------*/ + + weight_a_fx( A, Ap, gamma1, M ); + + lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e, FDNS_NPTS, 0 ); + + mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e ); + FOR( i = L_frame; i < L_spec; i++ ) + { + spectrum[i] = L_shl( Mpy_32_16_1( spectrum[i], gainlpc_noinv[FDNS_NPTS - 1] ), gainlpc_noinv_e[FDNS_NPTS - 1] ); + move32(); + } + } + + /* reduce the peaks in the IGF region, to make life of the core-coder easier... */ + test(); + IF( LE_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) + { + Word16 sf_width; + Word16 dist_low, dist_high; + Word16 max_fac_s, max_fac_m; + Word32 max_low, max_low1, max_low2, max_high; + Word16 headroom, shift, tmp16; + + + max_fac_m = 24576; + move16(); + /* max_fac = 3 */ + max_fac_s = 2; + move16(); + if ( hTcxEnc->tcx_lpc_shaped_ari ) + { + /* max_fac = 1.5 */ + max_fac_s = 1; + move16(); + } + + sf_width = shr( L_frame, 1 ); + + max_low2 = 0; + move32(); + dist_low = 0; + move16(); + FOR( i = 0; i < sf_width; i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame - 1 - i] ); + IF( GT_32( tmp, max_low2 ) ) + { + max_low2 = tmp; + move32(); + dist_low = i; + move16(); + } + } + + max_low1 = 0; + move32(); + FOR( i = 0; i < sub( L_frame, sf_width ); i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame - sf_width - 1 - i] ); + if ( GT_32( tmp, max_low1 ) ) + { + max_low1 = tmp; + move32(); + } + IF( GT_32( tmp, max_low2 ) ) + { + dist_low = add( sf_width, i ); + } + } + + max_low = L_max( max_low1, max_low2 ); + + max_high = 0; + move32(); + dist_high = 0; + move16(); + FOR( i = 0; i < sub( L_spec, L_frame ); i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame + i] ); + if ( GT_32( tmp, max_high ) ) + { + max_high = tmp; + move32(); + dist_high = i; + move16(); + } + } + + /* at least 9 bits headroom are needed for below multiplicitions */ + shift = 0; + move16(); + headroom = 31; + move16(); + + tmp16 = norm_l( max_low ); + if ( max_low != 0 ) + headroom = s_min( headroom, tmp16 ); + + tmp16 = norm_l( max_low2 ); + if ( max_low2 != 0 ) + headroom = s_min( headroom, tmp16 ); + + tmp16 = norm_l( max_high ); + if ( max_high != 0 ) + headroom = s_min( headroom, tmp16 ); + + if ( LT_16( headroom, 9 ) ) + { + shift = sub( 9, headroom ); + } + max_low = L_shr( max_low, shift ); + max_low2 = L_shr( max_low2, shift ); + max_high = L_shr( max_high, shift ); + + test(); + test(); + IF( GT_32( imult3216( max_high, dist_high ), imult3216( L_shr( max_low, 2 ), dist_low ) ) && ( GT_32( max_low_pre, L_shr( max_high_pre, 4 ) ) ) && ( GT_32( max_high, L_shl( Mpy_32_16_r( max_low2, max_fac_m ), max_fac_s ) ) ) ) + { + Word16 fac; + fac = divide3232( max_low2, max_high ); + fac = shl( mult_r( fac, max_fac_m ), max_fac_s ); + + FOR( i = 0; i < sub( L_spec, L_frame ); i++ ) + { + spectrum[L_frame + i] = Mpy_32_16_1( spectrum[L_frame + i], fac ); + move32(); + } + } + } + + + test(); + test(); + test(); + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) && st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns ) + { + PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e ); + } +} +#endif + #ifdef ADD_IVAS_TNS /*-----------------------------------------------------------* * EstimateStereoTCXNoiseLevel() @@ -1338,76 +1617,81 @@ static void EstimateTCXNoiseLevel_ivas_fx( *-------------------------------------------------------------------*/ void QuantizeSpectrum_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - const float A[], /* i : quantized coefficients NxAz_q[M+1] */ - const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ - float gainlpc[], /* i : MDCT gains of the previous frame */ - float synth[], /* o : synthesis buffer */ - const int16_t nb_bits, /* i : bit budget */ - const int16_t tnsSize, /* i : number of tns parameters put into prm */ - int16_t prm[], /* o : tcx parameters */ - const int16_t frame_cnt, /* i : frame counter in the super_frame */ - CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ - const int16_t vad_hover_flag /* i : VAD hangover flag */ + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 A_fx[], /* i : quantized coefficients NxAz_q[M+1], Q = 14 - norm_s(A_fx[0]) */ + const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ + Word16 gainlpc_fx[], /* i : MDCT gains of the previous frame */ + Word16 gainlpc_e[], /* i : exponents of MDCT gains of the previous frame */ + Word16 synth[], /* o : synthesis buffer, Q0 */ + const Word16 nb_bits, /* i : bit budget */ + const Word16 tnsSize, /* i : number of tns parameters put into prm */ + Word16 prm[], /* o : tcx parameters */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ ) { - int16_t L_frameTCX; /* full frame length */ - int16_t L_frame; /* frame length */ - int16_t L_spec; /* length of the coded spectrum */ - int16_t tcx_offset; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder; /* noise filling border */ - float quantized_spectrum[N_MAX]; /* quantized MDCT spectrum */ - Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */ - float lf_deemph_fact[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ - int16_t hm_active; /* flag indicating if the harmonic model is active */ - float fac_ns; /* noise filling level */ - Word16 fac_ns_fx; /* noise filling level, Q15 */ - int16_t nf_seed; /* noise filling random seed */ - float ener; /* energy of the quantized spectrum */ - float gain_tcx; /* global gain */ - Word16 gain_tcx_fx; /* global gain */ - Word16 gain_tcx_e; /* global gain */ + Word16 L_frameTCX; /* full frame length */ + Word16 L_frame; /* frame length */ + Word16 L_spec; /* length of the coded spectrum */ + Word16 tcx_offset; /* folding point offset relative to the end of the previous frame */ + Word16 noiseFillingBorder; /* noise filling border */ + Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */ + Word16 quantized_spectrum_e; /* quantized MDCT spectrum */ + Word16 lf_deemph_fact_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ + Word16 hm_active; /* flag indicating if the harmonic model is active */ + Word16 fac_ns_fx; /* noise filling level, Q15 */ + Word16 nf_seed; /* noise filling random seed */ + Word32 ener_fx; /* energy of the quantized spectrum */ + Word16 ener_e; /* energy of the quantized spectrum */ + Word16 gain_tcx_fx; /* global gain */ + Word16 gain_tcx_e; /* global gain */ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + set32_fx( quantized_spectrum_fx, 0, N_MAX ); + /*-----------------------------------------------------------* * Quantize the MDCT spectrum * *-----------------------------------------------------------*/ - QuantizeTCXSpectrum( st, frame_cnt, hTcxEnc->spectrum[frame_cnt], gainlpc, Aqind, tnsSize, nb_bits, vad_hover_flag, - &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum, hm_cfg, &hm_active, lf_deemph_fact, &nf_seed, &ener, &gain_tcx, prm ); + QuantizeTCXSpectrum_fx( st, frame_cnt, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], gainlpc_fx, gainlpc_e, Aqind, tnsSize, nb_bits, vad_hover_flag, + &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum_fx, &quantized_spectrum_e, hm_cfg, &hm_active, lf_deemph_fact_fx, &nf_seed, &ener_fx, &ener_e, &gain_tcx_fx, &gain_tcx_e, prm ); + + Word16 s = sub( getScaleFactor32( st->hTcxEnc->spectrum_fx[frame_cnt], L_frame ), 6 ); + scale_sig32( st->hTcxEnc->spectrum_fx[frame_cnt], L_frame, s ); + st->hTcxEnc->spectrum_e[frame_cnt] = sub( st->hTcxEnc->spectrum_e[frame_cnt], s ); + move16(); + + IF( NE_16( quantized_spectrum_e, hTcxEnc->spectrum_e[frame_cnt] ) ) + { + scale_sig32( quantized_spectrum_fx, s_max( L_frame, L_spec ), sub( quantized_spectrum_e, hTcxEnc->spectrum_e[frame_cnt] ) ); + } /*-----------------------------------------------------------* * Estimate and quantize noise factor * *-----------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); - st->hTcxEnc->tcxltp_gain = float_to_fix16( st->hTcxEnc->tcxltp_gain_flt, Q15 ); - st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); - st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); - floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); - floatToFixed_arrL( quantized_spectrum, quantized_spectrum_fx, 31 - st->hTcxEnc->spectrum_e[0], L_frame ); - gain_tcx_e = 15 - ( Q_factor( gain_tcx ) ); - gain_tcx_fx = float_to_fix16( gain_tcx, 15 - gain_tcx_e ); -#endif EstimateTCXNoiseLevel_ivas_fx( st, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, &fac_ns_fx, &prm[1] ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fac_ns = fix16_to_float( fac_ns_fx, Q15 ); -#endif /*-----------------------------------------------------------* * Internal decoder * *-----------------------------------------------------------*/ - InternalTCXDecoder( st, frame_cnt, L_frameTCX, L_frame, L_spec, tcx_offset, noiseFillingBorder, quantized_spectrum, ener, lf_deemph_fact, fac_ns, nf_seed, A, gainlpc, hm_active, gain_tcx, hTcxEnc->spectrum[frame_cnt], synth, &prm[0] ); + InternalTCXDecoder_fx( st, frame_cnt, L_frameTCX, L_frame, L_spec, tcx_offset, noiseFillingBorder, quantized_spectrum_fx, ener_fx, ener_e, lf_deemph_fact_fx, fac_ns_fx, nf_seed, A_fx, gainlpc_fx, gainlpc_e, hm_active, gain_tcx_fx, &gain_tcx_e, hTcxEnc->spectrum_fx[frame_cnt], &hTcxEnc->spectrum_e[frame_cnt], synth, &prm[0] ); /* Update L_frame_past */ st->L_frame_past = L_frame; + move16(); /* Update overlap */ - if ( ( ( ( L_frameTCX == hTcxEnc->L_frameTCX >> 1 ) && frame_cnt > 0 ) || ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) - { - st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + test(); + test(); + test(); + if ( ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) && frame_cnt > 0 ) || EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) + { + st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); } @@ -3193,213 +3477,1100 @@ void QuantizeSpectrum_fx( move16(); } +#ifdef IVAS_FLOAT_FIXED +static Word16 DecideTonalSideInfo_fx( + Word32 spectrum[], // Qx + const Word16 L_frame_glob, + Word32 SFM2 ) +{ + Word32 SFM, K, K2; + Word16 Tonal_SideInfo; -void coder_tcx_fx( - Word16 n, - TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ - Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ - Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ - Word16 synth[], - Word16 L_frame_glob, /* input: frame length */ - Word16 L_frameTCX_glob, - Word16 L_spec, - Word16 nb_bits, /*input: bit budget*/ - Word8 tcxonly, /*input: only TCX flag*/ - Word32 spectrum[], /* i/o: MDCT spectrum */ - Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ - Word16 prm[], /* output: tcx parameters */ - Encoder_State *st, - CONTEXT_HM_CONFIG *hm_cfg ) + SFM = SFM_Cal_fx( spectrum, s_min( 200, L_frame_glob ) ); + test(); + IF( LE_16( L_frame_glob, 256 ) ) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE IF( EQ_16( L_frame_glob, 320 ) || EQ_16( L_frame_glob, 512 ) ) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE /*FrameSize_Core == 640*/ + { + K = 0x2CCCCCCD; + move32(); + K2 = 0x51EB852; + move32(); + } + + + Tonal_SideInfo = 0; + move16(); + if ( LT_32( SFM, K ) ) + { + Tonal_SideInfo = 1; + move16(); + } + if ( LT_32( SFM2, K2 ) ) + { + Tonal_SideInfo = 1; + move16(); + } + + return Tonal_SideInfo; +} +#endif + +#ifdef IVAS_FLOAT_FIXED +void QuantizeTCXSpectrum_fx( + Encoder_State *st, /* i : state handle */ + const Word16 frame_cnt, /* i : frame counter in the super_frame Q0 */ + Word32 *x_orig_fx, /* i : shaped MDCT spectrum */ + const Word16 x_orig_e, /* i : exp of shaped MDCT spectrum */ + Word16 *gainlpc_fx, /* i : FDNS gains */ + Word16 *gainlpc_e, /* i : exp of FDNS gains */ + const Word16 *Aqind, /* i : frame-independent quantized coefficients (M+1) Q0 */ + const Word16 tnsSize, /* i : number of tns parameters put into prm Q0 */ + const Word16 nb_bits, /* i : bit budget Q0 */ + const Word16 vad_hover_flag, /* i : VAD hangover flag Q0 */ + Word16 *pL_frameTCX, /* o : full frame length Q0 */ + Word16 *pL_frame, /* o : frame length Q0 */ + Word16 *pL_spec, /* o : length of the coded spectrum Q0 */ + Word16 *ptcx_offset, /* o : folding point offset relative to the end of the previous frame Q0 */ + Word16 *pnoiseFillingBorder, /* o : noise filling border Q0 */ + Word32 spectrum_fx[], /* o : quantized MDCT spectrum */ + Word16 *spectrum_e, /* o : exp of quantized MDCT spectrum */ + CONTEXT_HM_CONFIG *hm_cfg, /* o : Context-based harmonic model configuration */ + Word16 *hm_active, /* o : flag indicating if the harmonic model is active */ + Word16 lf_deemph_fact_fx[], /* o : low frequency deemphasis factors Q14*/ + Word16 *nf_seed, /* o : noise filling random seed Q0*/ + Word32 *ener_fx, /* o : energy of the quantized spectrum */ + Word16 *ener_e, /* o : exp of energy of the quantized spectrum */ + Word16 *gain_tcx_fx, /* o : global gain */ + Word16 *gain_tcx_e, /* o : exp of global gain */ + Word16 prm[] /* o : tcx parameters Q0 */ +) { - Word16 L_frame; - Word16 left_overlap, right_overlap; - Word16 tnsSize; /* number of tns parameters put into prm */ - Word16 tnsBits; /* number of tns bits in the frame */ - Word16 ltpBits; - Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS]; - Word16 win[N_MAX + L_MDCT_OVLP_MAX]; - Word32 powerSpec[N_MAX]; - Word16 powerSpec_e; - Word16 winMDST[N_MAX + L_MDCT_OVLP_MAX]; - Word16 *pWinMDST; - Word16 left_overlap_mode, right_overlap_mode; - LPD_state_HANDLE hLPDmem = st->hLPDmem; TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; - - left_overlap = right_overlap = -1; + Word16 i, L_frame, L_frameTCX, L_spec, tcx_offset; + Word16 noiseFillingBorder, LtpPitchLag, PeriodicityIndex; + Word16 lastnzCtxHm, lastnz; + Word16 stop; + Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector; + Word16 nEncoded, sqBits_noStop; + Word16 NumIndexBits, signaling_bits, sqTargetBits, sqBits, ctxHmBits, resQBits, resQTargetBits; + Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *sqQ, *prm_target; + Word32 total_brate, tmp32; + Word16 RelativeScore_fx, sqGain_fx, sqGain_e, gain_tcx_opt_fx, gain_tcx_opt_e; + Word16 tmp1, tmp2, max_iter, minSqGain; + CONTEXT_HM_CONFIG *phm_cfg; + Word16 att_fx = 0; move16(); +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; move16(); - tnsSize = 0; + Flag Carry = 0; move16(); - tnsBits = 0; +#endif + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + sqGain_fx = MAX_16; move16(); - ltpBits = 0; + sqGain_e = 0; + move16(); + minSqGain = 0; + move16(); + resQTargetBits = 0; move16(); - L_frame = L_frameTCX_glob; + NumIndexBits = 0; + move16(); + sqBits = 0; move16(); + ctxHmBits = 0; + move16(); + resQBits = 0; + move16(); + prm_ltp = &prm[1 + NOISE_FILL_RANGES]; + prm_tns = prm_ltp + LTPSIZE; + prm_hm = prm_tns + tnsSize; + prm_lastnz = prm_hm + 2; + sqQ = prm_hm + NPRM_CTX_HM; + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + total_brate = st->element_brate; + } + ELSE + { + total_brate = st->total_brate; + } + move32(); /*-----------------------------------------------------------* - * Windowing * + * Init lengths * *-----------------------------------------------------------*/ - IF( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) - { - WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, - hTcxEnc->speech_TCX, &L_frame, win, 1, 1 ); + /******************************************************************************************/ - /*-----------------------------------------------------------* - * Compute MDCT * - *-----------------------------------------------------------*/ + L_frame = st->L_frame; + move16(); + L_frameTCX = hTcxEnc->L_frameTCX; + move16(); + L_spec = st->hTcxCfg->tcx_coded_lines; + move16(); + tcx_offset = st->hTcxCfg->tcx_offset; + move16(); - *spectrum_e = 16; - move16(); - TCX_MDCT( win, spectrum, spectrum_e, left_overlap, sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, st->element_mode ); + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + L_frame = shr( L_frame, 1 ); + L_frameTCX = shr( L_frameTCX, 1 ); + L_spec = shr( L_spec, 1 ); } - ELSE + ELSE IF( st->last_core == ACELP_CORE ) { - Word32 tmp_buf[L_FRAME_PLUS]; - Word16 Q, tmp1, tmp2, i; - - Q = 0; + st->hTcxCfg->last_aldo = 0; move16(); + L_frame = add( L_frame, tcx_offset ); + L_frameTCX = add( L_frameTCX, st->hTcxCfg->tcx_offsetFB ); + L_spec = add( L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) ); - wtda_fx( hTcxEnc->new_speech_TCX, &Q, tmp_buf, NULL, NULL, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, L_frame ); - - left_overlap_mode = hTcxCfg->tcx_last_overlap_mode; - move16(); - if ( EQ_16( left_overlap_mode, ALDO_WINDOW ) ) + IF( st->hTcxCfg->lfacNext < 0 ) { - left_overlap_mode = FULL_OVERLAP; + L_frame = sub( L_frame, st->hTcxCfg->lfacNext ); + L_frameTCX = sub( L_frameTCX, st->hTcxCfg->lfacNextFB ); + tcx_offset = st->hTcxCfg->lfacNext; move16(); } - right_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; - move16(); - if ( EQ_16( right_overlap_mode, ALDO_WINDOW ) ) + ELSE { - right_overlap_mode = FULL_OVERLAP; + tcx_offset = 0; move16(); } - - WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1 ); - - /* scale by NORM_MDCT_FACTOR / L */ - tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */ - tmp2 = 4; + hTcxEnc->noiseLevelMemory_cnt = 0; move16(); - tmp1 = ISqrt16( tmp1, &tmp2 ); - - FOR( i = 0; i < L_frame; i++ ) - { - tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 ); - move32(); - } - Q = sub( Q, tmp2 ); - - /* DCT */ - edct_fx( tmp_buf, spectrum, L_frame, &Q ); - *spectrum_e = sub( 31, Q ); } + *pL_frameTCX = L_frameTCX; + move16(); + *pL_frame = L_frame; + move16(); + *pL_spec = L_spec; + move16(); + *ptcx_offset = tcx_offset; + move16(); - /*-----------------------------------------------------------* - * Attenuate upper end of NB spectrum, * - * to simulate ACELP behavior * - *-----------------------------------------------------------*/ + /* target bitrate for SQ */ + sqTargetBits = sub( nb_bits, NBITS_TCX_GAIN + NBITS_NOISE_FILL_LEVEL ); - IF( st->narrowBand != 0 ) + IF( st->enablePlcWaveadjust ) { - attenuateNbSpectrum_fx( L_frame, spectrum ); + Word16 L_frame_glob; + IF( EQ_16( st->core, TCX_20_CORE ) ) + { + L_frame_glob = st->L_frame; + } + ELSE + { + L_frame_glob = shr( st->L_frame, 1 ); + } + move16(); + st->Tonal_SideInfo = DecideTonalSideInfo_fx( x_orig_fx, L_frame_glob, st->hTcxCfg->SFM2 ); } + /* Start with the pre-shaped spectrum*/ + Copy32( x_orig_fx, spectrum_fx, L_spec ); + *spectrum_e = x_orig_e; + move16(); + /*-----------------------------------------------------------* - * Compute noise-measure flags for spectrum filling * - * and quantization (0: tonal, 1: noise-like). * - * Detect low pass if present. * + * Bandwidth Limitation * *-----------------------------------------------------------*/ - pWinMDST = winMDST; + noiseFillingBorder = L_spec; move16(); - if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + IF( st->igf ) { - pWinMDST = win; + noiseFillingBorder = st->hIGFEnc->infoStartLine; move16(); } + *pnoiseFillingBorder = noiseFillingBorder; + move16(); - AnalyzePowerSpectrum_fx( st, - round_fx( L_shl( Mpy_32_16_1( L_mult0( L_frame, st->L_frame ) /*Q0*/, - getInvFrameLen( hTcxEnc->L_frameTCX ) /*Q21*/ ) /*Q6*/, - 16 - 6 ) ), - L_frame, - left_overlap, right_overlap, - spectrum, *spectrum_e, - pWinMDST, - powerSpec, &powerSpec_e ); - IF( hTcxCfg->fIsTNSAllowed != 0 ) + IF( st->igf ) { - test(); - test(); - SetTnsConfig( hTcxCfg, sub( L_frame_glob, st->L_frame ) == 0, st->last_core == 0 ); - - TNSAnalysis_fx( hTcxCfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns, &st->hIGFEnc->tns_predictionGain ); + FOR( i = st->hIGFEnc->infoStopLine; i < s_max( L_frame, L_frameTCX ); i++ ) + { + spectrum_fx[i] = 0; + move32(); + } } ELSE { - hTcxEnc->fUseTns[0] = hTcxEnc->fUseTns[1] = 0; - move16(); - move16(); + FOR( i = noiseFillingBorder; i < s_max( L_frame, L_frameTCX ); i++ ) + { + spectrum_fx[i] = 0; + move32(); + } } - IF( st->igf ) - { - ProcessIGF_fx( st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns[0], ( st->last_core == ACELP_CORE ), 0 ); - } + /*-----------------------------------------------------------* + * Quantization * + *-----------------------------------------------------------*/ - ShapeSpectrum_fx( hTcxCfg, A, gainlpc, gainlpc_e, - L_frame_glob, - L_spec, - spectrum, - hTcxEnc->fUseTns[0], - st ); - if ( st->igf ) - { - nb_bits = sub( nb_bits, st->hIGFEnc->infoTotalBitsPerFrameWritten ); - } - IF( hTcxCfg->fIsTNSAllowed != 0 ) + IF( !hTcxEnc->tcx_lpc_shaped_ari ) { - EncodeTnsData_fx( hTcxCfg->pCurrentTnsConfig, hTcxEnc->tnsData, prm + 1 + NOISE_FILL_RANGES + LTPSIZE, &tnsSize, &tnsBits ); - } + /* context based arithmetic coder */ - QuantizeSpectrum_fx( hTcxCfg, - A, - Aqind, - gainlpc, gainlpc_e, - synth, - L_frame_glob, - L_frameTCX_glob, - L_spec, - sub( sub( nb_bits, tnsBits ), ltpBits ), - tcxonly, - spectrum, spectrum_e, - hTcxEnc->tnsData, - hTcxEnc->fUseTns[0], - tnsSize, - prm, - n, - st, - hm_cfg ); + /* initialize signaling to default, i.e. context based AC is inactive */ + prm_hm[0] = 0; + move16(); + prm_hm[1] = -1; + move16(); - hLPDmem->nbits = add( hLPDmem->nbits, add( tnsBits, ltpBits ) ); -} + /* Fast estimation of the scalar quantizer step size */ + test(); + IF( st->hTcxCfg->ctx_hm && ( st->last_core != ACELP_CORE ) ) + { + LtpPitchLag = -1; + move16(); + test(); + IF( ( st->tcxonly == 0 ) && ( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) ) + { + tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 ); + tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr ); + LtpPitchLag = div_l( tmp32, tmp1 ); + } -/*-------------------------------------------------------------------* - * coder_tcx_post_fx() - * - * - *-------------------------------------------------------------------*/ + ctxHmBits = add( ctxHmBits, 1 ); /* ContextHM flag */ + sqTargetBits = sub( sqTargetBits, 1 ); /* ContextHM flag */ -void coder_tcx_post_fx( + Word16 LtpGain; + IF( hTcxEnc->tcxltp ) + { + LtpGain = hTcxEnc->tcxltp_gain; + } + ELSE + { + LtpGain = -MAX_16; + } + move16(); + PeriodicityIndex = SearchPeriodicityIndex_fx( spectrum_fx, NULL, L_spec, sqTargetBits, LtpPitchLag, LtpGain, &RelativeScore_fx ); + + NumIndexBits = CountIndexBits_fx( (Word16) GE_16( L_spec, (Word16) 256 ), PeriodicityIndex ); + + IF( st->element_mode > EVS_MONO ) + { + ConfigureContextHm( L_spec, sub( sqTargetBits, NumIndexBits ), PeriodicityIndex, LtpPitchLag, hm_cfg ); + } + ELSE + { + ConfigureContextHm( L_spec, sqTargetBits, PeriodicityIndex, LtpPitchLag, hm_cfg ); + } + + /* Quantize original spectrum */ + sqGain_fx = SQ_gain_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + + /* Estimate original bitrate */ + stop = 0; + move16(); + IF( st->element_mode > EVS_MONO ) + { + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, NULL ); + } + + /* Estimate context mapped bitrate */ + stopCtxHm = 0; + move16(); + + /* Context Mapping */ + IF( st->element_mode > EVS_MONO ) + { + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + } + + /* Decide whether or not to use context mapping */ + Selector = sub( s_max( stop, sqBits ), ( add( s_max( stopCtxHm, sqBitsCtxHm ), NumIndexBits ) ) ); + + test(); + test(); + IF( GT_16( Selector, 2 ) || ( LE_16( abs_s( Selector ), 2 ) && LT_16( kCtxHmOlRSThr, RelativeScore_fx ) ) ) + { + /* CtxHm is likely better */ + sqTargetBits = sub( sqTargetBits, NumIndexBits ); + ctxHmBits = add( ctxHmBits, NumIndexBits ); + prm_hm[0] = 1; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + ELSE + { + /* Original is better or not much difference */ + prm_hm[0] = 0; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + + sqBits_noStop = sqBits; + move16(); + } + + if ( stop != 0 ) + { + sqBits = stop; + move16(); + } + } + ELSE + { + /* no context hm*/ + PeriodicityIndex = -1; + move16(); + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + sqGain_fx = SQ_gain_estimate_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + } + ELSE + { + sqGain_fx = SQ_gain_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + } + /* Quantize spectrum */ + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + + /* Estimate bitrate */ + stop = 0; + move16(); + + IF( st->element_mode > EVS_MONO ) + { + sqBits_noStop = sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + move16(); + } + ELSE + { + sqBits_noStop = sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, NULL ); + move16(); + } + + if ( stop != 0 ) + { + sqBits = stop; + move16(); + } + } /* end of if (ctx_hm) */ + + /* Adjust correction factor */ + tmp1 = sqBits; + move16(); + + if ( s_and( L_spec, sub( L_spec, 1 ) ) == 0 ) /* power-of-2 */ + { + tmp1 = add( tmp1, 1 ); + } + + tmp1 = BASOP_Util_Divide1616_Scale( sqTargetBits, tmp1, &tmp2 ); + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + hTcxEnc->tcx_target_bits_fac = shl_o( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2, &Overflow ); +#else /* BASOP_NOGLOB */ + hTcxEnc->tcx_target_bits_fac = shl( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2 ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + if ( GT_16( hTcxEnc->tcx_target_bits_fac, 20480 ) ) + { + hTcxEnc->tcx_target_bits_fac = 20480; + move16(); + } + if ( LT_16( hTcxEnc->tcx_target_bits_fac, 12288 ) ) + { + hTcxEnc->tcx_target_bits_fac = 12288; + move16(); + } + + /* Refine quantizer step size with a rate-control-loop (optional) */ + phm_cfg = NULL; + move16(); + if ( PeriodicityIndex >= 0 ) + { + phm_cfg = hm_cfg; + move16(); + } + + max_iter = 4; + move16(); + if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + max_iter = 2; + move16(); + } + sqBits = tcx_scalar_quantization_rateloop_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, &sqGain_fx, &sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, prm_lastnz, /* lastnz */ sqTargetBits, &nEncoded, &stop, sqBits_noStop, sqBits, st->hTcxCfg->tcxRateLoopOpt, st->tcxonly, phm_cfg, max_iter, st->element_mode ); + + IF( ctxHmBits > 0 ) + { + /* Mapping tool is enabled */ + /* Truncate spectrum */ + FOR( i = nEncoded; i < L_spec; i++ ) + { + IF( st->element_mode > EVS_MONO ) + { + break; + } + ELSE + { + sqQ[i] = 0; + move16(); + } + } + + IF( PeriodicityIndex >= 0 ) + { + /* Mapping is used */ + /* Estimate non-mapped bitrate */ + stopCtxHm = 1; + move16(); + IF( st->element_mode > EVS_MONO ) + { + /* Fix: Use updated value for target bits (sqTargetBits + NumIndexBits) before computing non-mapped estimate */ + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits + NumIndexBits, &stopCtxHm, 0, NULL ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits, &stopCtxHm, NULL ); + } + + /* Decide whether or not to revert mapping */ + Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) ); + + IF( st->element_mode > EVS_MONO ) + { + test(); + test(); + IF( ( stopCtxHm == 0 && Selector > 0 ) || stop ) /* If overflow occured with mapped, select non-mapped */ + { + /* Non-mapped is better */ + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + prm_hm[0] = 0; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + ELSE + { + test(); + IF( stopCtxHm == 0 && Selector > 0 ) + { + /* Non-mapped is better */ + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + prm_hm[0] = 0; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + } + ELSE + { + /* Mapping is not used */ + IF( st->element_mode > EVS_MONO ) + { + /* Truncate Spectrum */ + FOR( i = nEncoded; i < L_spec; i++ ) + { + sqQ[i] = 0; + move16(); + } + } + /* Estimate mapped bitrate */ + stopCtxHm = 1; + move16(); + IF( st->element_mode > EVS_MONO ) + { + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + } + + /* Decide whether or not to use mapping */ + Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) ); + test(); + IF( stopCtxHm == 0 && Selector > 0 ) + { + /* Mapped is better */ + sqTargetBits = sub( sqTargetBits, NumIndexBits ); + ctxHmBits = add( ctxHmBits, NumIndexBits ); + prm_hm[0] = 1; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + PeriodicityIndex = prm_hm[1]; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + } + + /* Limit low sqGain for avoiding saturation of the gain quantizer*/ + /*(float) sqrt( (float) NORM_MDCT_FACTOR / (float) L_spec ) in Q14 */ + SWITCH( L_spec ) + { + case 80: + minSqGain = 23170; + BREAK; + case 100: + minSqGain = 20724; + BREAK; + case 160: + minSqGain = 16384; + BREAK; + case 200: + minSqGain = 14654; + BREAK; + case 240: + minSqGain = 13377; + BREAK; + case 300: + minSqGain = 11965; + BREAK; + case 320: + minSqGain = 11585; + BREAK; + case 400: + minSqGain = 10362; + BREAK; + case 480: + minSqGain = 9459; + BREAK; + case 600: + minSqGain = 8461; + BREAK; + case 640: + minSqGain = 8192; + BREAK; + case 800: + minSqGain = 7327; + BREAK; + case 960: + minSqGain = 6689; + BREAK; + case 1200: + minSqGain = 5983; + BREAK; + case 1440: + minSqGain = 5461; + BREAK; + case 1800: + minSqGain = 4885; + BREAK; + case 2048: + minSqGain = 4579; + BREAK; + default: + assert( 0 ); + } + move16(); + Word16 shift_tmp = s_max( sqGain_e, 1 ); + test(); + IF( LT_16( st->hTcxCfg->tcxRateLoopOpt, 3 ) && LT_16( shl( sqGain_fx, sub( sqGain_e, shift_tmp ) ), shl( minSqGain, sub( 1, shift_tmp ) ) ) ) + { + sqGain_fx = minSqGain; + move16(); + sqGain_e = 1; + move16(); + + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + stop = 1; + IF( st->element_mode > EVS_MONO ) + { + /* Ensure non-mapped estimation is used for limiting low sqGain considering that this refinement occurs very rarely */ + PeriodicityIndex = -1; + move16(); + IF( prm_hm[0] == 1 ) + { + prm_hm[0] = 0; + move16(); + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + } + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, PeriodicityIndex >= 0 ? hm_cfg : NULL ); + } + } + + /* Truncate spectrum (for CBR) */ + IF( stop ) + { + FOR( i = nEncoded; i < L_spec; i++ ) + { + sqQ[i] = 0; + move16(); + } + } + + /* Save quantized Values */ + *nf_seed = 0; + move16(); + FOR( i = 0; i < L_spec; i++ ) + { + spectrum_fx[i] = (Word32) sqQ[i]; + /* noise filling seed */ + *nf_seed = (Word16) L_add( *nf_seed, L_mult0( abs_s( sqQ[i] ), shl( i, 1 ) ) ); + } + + tmp32 = L_deposit_l( 0 ); + FOR( i = 0; i < L_spec; i++ ) + { + spectrum_fx[i] = L_mult( sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) ); + move32(); + /* noise filling seed */ +#ifdef BASOP_NOGLOB + tmp32 = L_macNs_co( tmp32, abs_s( sqQ[i] ), i, &Carry, &Overflow ); +#else /* BASOP_NOGLOB */ + tmp32 = L_macNs( tmp32, abs_s( sqQ[i] ), i ); +#endif /* BASOP_NOGLOB */ + } + *spectrum_e = SPEC_EXP_DEC; + move16(); + + *nf_seed = extract_l( tmp32 ); + } + ELSE + { + /* low rates: envelope based arithmetic coder */ + + AdaptLowFreqEmph_fx( spectrum_fx, *spectrum_e, NULL, 0, 0, 1, gainlpc_fx, gainlpc_e, L_frame ); + + prm_target = sqQ; + sqQ = prm_target + 1; + + LtpPitchLag = -1; + move16(); + + IF( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) + { + tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 ); + tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr ); + LtpPitchLag = div_l( tmp32, tmp1 ); + } + + Word8 tmp8 = 1; + move16(); + if ( ( st->last_core == ACELP_CORE ) ) + { + tmp8 = 0; + move16(); + } + Word16 low_complexiety = 0; + move16(); + if ( GT_16( st->bwidth, WB ) ) + { + low_complexiety = 1; + move16(); + } + tcx_arith_encode_envelope_fx( spectrum_fx, spectrum_e, hm_cfg->indexBuffer, L_frame, L_spec, st, Aqind, sqTargetBits, sqQ, tmp8, prm_hm, /* HM parameter area */ LtpPitchLag, &sqBits, &signaling_bits, nf_seed, low_complexiety ); + + sqTargetBits = sub( sqTargetBits, signaling_bits ); + *prm_target = sqTargetBits; + move16(); + + /* Noise filling seed */ + } + + *hm_active = prm_hm[0]; + move16(); + + /*-----------------------------------------------------------* + * Compute optimal TCX gain. * + *-----------------------------------------------------------*/ + + IF( lf_deemph_fact_fx != NULL ) + { + /* initialize LF deemphasis factors in lf_deemph_fact */ + FOR( i = 0; i < L_spec; i++ ) + { + lf_deemph_fact_fx[i] = ONE_IN_Q14; + move16(); + } + } + + IF( !st->tcxonly ) + { + AdaptLowFreqDeemph( spectrum_fx, *spectrum_e, hTcxEnc->tcx_lpc_shaped_ari, gainlpc_fx, gainlpc_e, L_frame, lf_deemph_fact_fx ); + } + + assert( x_orig_fx != spectrum_fx ); + + tcx_get_gain( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, &gain_tcx_opt_fx, &gain_tcx_opt_e, ener_fx, ener_e ); + + IF( gain_tcx_opt_fx <= 0 ) + { + gain_tcx_opt_fx = sqGain_fx; + move16(); + gain_tcx_opt_e = sqGain_e; + move16(); + } + *gain_tcx_fx = gain_tcx_opt_fx; + move16(); + *gain_tcx_e = gain_tcx_opt_e; + move16(); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); + *gain_tcx_fx = mult( *gain_tcx_fx, att_fx ); + } + + /*-----------------------------------------------------------* + * Quantize TCX gain * + *-----------------------------------------------------------*/ + + /* gain quantization here in case of VBR unvoiced coding; fixes problems of uninitialized global gain values */ + test(); + IF( GE_32( total_brate, ACELP_13k20 ) && st->rf_mode == 0 ) + { + QuantizeGain( L_spec, gain_tcx_fx, gain_tcx_e, &prm[0] ); + } + + /*-----------------------------------------------------------* + * Residual Quantization * + *-----------------------------------------------------------*/ + + IF( st->hTcxCfg->resq ) + { + resQTargetBits = sub( sqTargetBits, sqBits ); + + IF( hTcxEnc->tcx_lpc_shaped_ari ) + { + /* envelope based arithmetic coder */ + Word16 *prm_resq; + + prm_resq = sqQ + sub( sqTargetBits, resQTargetBits ); + + resQBits = tcx_ari_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, hm_cfg->indexBuffer, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, prm_resq, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx ); + + /* Transmit zeros when there bits remain after RESQ */ + FOR( i = resQBits; i < resQTargetBits; ++i ) + { + prm_resq[i] = 0; + move16(); + } + } + ELSE + { + /* context based arithmetic coder */ + resQBits = tcx_res_Q_gain_fx( gain_tcx_opt_fx, gain_tcx_opt_e, gain_tcx_fx, gain_tcx_e, sqQ + L_spec, resQTargetBits ); + IF( st->tcxonly ) + { + resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, NULL ); + } + ELSE + { + resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx ); + } + } + } + + tmp1 = norm_s( *gain_tcx_fx ); + *gain_tcx_fx = shl( *gain_tcx_fx, tmp1 ); + move16(); + *gain_tcx_e = sub( *gain_tcx_e, tmp1 ); + move16(); + + /*-----------------------------------------------------------* + * ALFE tcx only bitrates * + *-----------------------------------------------------------*/ + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IF( st->tcxonly ) + { + test(); + test(); + IF( hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !hTcxEnc->fUseTns[frame_cnt] ) + { + PsychAdaptLowFreqDeemph( spectrum_fx, gainlpc_fx, gainlpc_e, NULL ); + } + } + } + + return; +} +#endif + +void coder_tcx_fx( + Word16 n, + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + Word16 synth[], + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX_glob, + Word16 L_spec, + Word16 nb_bits, /*input: bit budget*/ + Word8 tcxonly, /*input: only TCX flag*/ + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + Word16 prm[], /* output: tcx parameters */ + Encoder_State *st, + CONTEXT_HM_CONFIG *hm_cfg ) +{ + Word16 L_frame; + Word16 left_overlap, right_overlap; + Word16 tnsSize; /* number of tns parameters put into prm */ + Word16 tnsBits; /* number of tns bits in the frame */ + Word16 ltpBits; + Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS]; + Word16 win[N_MAX + L_MDCT_OVLP_MAX]; + Word32 powerSpec[N_MAX]; + Word16 powerSpec_e; + Word16 winMDST[N_MAX + L_MDCT_OVLP_MAX]; + Word16 *pWinMDST; + Word16 left_overlap_mode, right_overlap_mode; + LPD_state_HANDLE hLPDmem = st->hLPDmem; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + left_overlap = right_overlap = -1; + move16(); + move16(); + tnsSize = 0; + move16(); + tnsBits = 0; + move16(); + ltpBits = 0; + move16(); + + L_frame = L_frameTCX_glob; + move16(); + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + IF( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + + WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap, + hTcxEnc->speech_TCX, &L_frame, win, 1, 1 ); + + /*-----------------------------------------------------------* + * Compute MDCT * + *-----------------------------------------------------------*/ + + *spectrum_e = 16; + move16(); + TCX_MDCT( win, spectrum, spectrum_e, left_overlap, sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, st->element_mode ); + } + ELSE + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q, tmp1, tmp2, i; + + Q = 0; + move16(); + + wtda_fx( hTcxEnc->new_speech_TCX, &Q, tmp_buf, NULL, NULL, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, L_frame ); + + left_overlap_mode = hTcxCfg->tcx_last_overlap_mode; + move16(); + if ( EQ_16( left_overlap_mode, ALDO_WINDOW ) ) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + right_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; + move16(); + if ( EQ_16( right_overlap_mode, ALDO_WINDOW ) ) + { + right_overlap_mode = FULL_OVERLAP; + move16(); + } + + WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1 ); + + /* scale by NORM_MDCT_FACTOR / L */ + tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = ISqrt16( tmp1, &tmp2 ); + + FOR( i = 0; i < L_frame; i++ ) + { + tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 ); + move32(); + } + Q = sub( Q, tmp2 ); + + /* DCT */ + edct_fx( tmp_buf, spectrum, L_frame, &Q ); + *spectrum_e = sub( 31, Q ); + } + + + /*-----------------------------------------------------------* + * Attenuate upper end of NB spectrum, * + * to simulate ACELP behavior * + *-----------------------------------------------------------*/ + + IF( st->narrowBand != 0 ) + { + attenuateNbSpectrum_fx( L_frame, spectrum ); + } + + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + + pWinMDST = winMDST; + move16(); + if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + pWinMDST = win; + move16(); + } + + AnalyzePowerSpectrum_fx( st, + round_fx( L_shl( Mpy_32_16_1( L_mult0( L_frame, st->L_frame ) /*Q0*/, + getInvFrameLen( hTcxEnc->L_frameTCX ) /*Q21*/ ) /*Q6*/, + 16 - 6 ) ), + L_frame, + left_overlap, right_overlap, + spectrum, *spectrum_e, + pWinMDST, + powerSpec, &powerSpec_e ); + IF( hTcxCfg->fIsTNSAllowed != 0 ) + { + test(); + test(); + SetTnsConfig( hTcxCfg, sub( L_frame_glob, st->L_frame ) == 0, st->last_core == 0 ); + + TNSAnalysis_fx( hTcxCfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns, &st->hIGFEnc->tns_predictionGain ); + } + ELSE + { + hTcxEnc->fUseTns[0] = hTcxEnc->fUseTns[1] = 0; + move16(); + move16(); + } + + IF( st->igf ) + { + ProcessIGF_fx( st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns[0], ( st->last_core == ACELP_CORE ), 0 ); + } + + ShapeSpectrum_fx( hTcxCfg, A, gainlpc, gainlpc_e, + L_frame_glob, + L_spec, + spectrum, + hTcxEnc->fUseTns[0], + st ); + if ( st->igf ) + { + nb_bits = sub( nb_bits, st->hIGFEnc->infoTotalBitsPerFrameWritten ); + } + IF( hTcxCfg->fIsTNSAllowed != 0 ) + { + EncodeTnsData_fx( hTcxCfg->pCurrentTnsConfig, hTcxEnc->tnsData, prm + 1 + NOISE_FILL_RANGES + LTPSIZE, &tnsSize, &tnsBits ); + } + + QuantizeSpectrum_fx( hTcxCfg, + A, + Aqind, + gainlpc, gainlpc_e, + synth, + L_frame_glob, + L_frameTCX_glob, + L_spec, + sub( sub( nb_bits, tnsBits ), ltpBits ), + tcxonly, + spectrum, spectrum_e, + hTcxEnc->tnsData, + hTcxEnc->fUseTns[0], + tnsSize, + prm, + n, + st, + hm_cfg ); + + hLPDmem->nbits = add( hLPDmem->nbits, add( tnsBits, ltpBits ) ); +} + + +/*-------------------------------------------------------------------* + * coder_tcx_post_fx() + * + * + *-------------------------------------------------------------------*/ + +void coder_tcx_post_fx( Encoder_State *st, LPD_state *LPDmem, TCX_CONFIG_HANDLE hTcxCfg, @@ -3417,11 +4588,845 @@ void coder_tcx_post_fx( /*-----------------------------------------------------------* - * Memory update * + * Memory update * + *-----------------------------------------------------------*/ + + /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ + tcx_encoder_memory_update_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new, shift ); + + return; +} +#ifdef IVAS_FLOAT_FIXED +void coder_tcx_post_ivas_fx( + Encoder_State *st, + LPD_state *LPDmem, + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 *synth, + const Word16 *A, + const Word16 *Ai, + Word16 *wsig, + Word16 Q_new ) +{ + Word16 xn_buf[L_FRAME_MAX]; + + /* TCX output */ + Copy( synth, xn_buf, st->L_frame ); + + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ + tcx_encoder_memory_update_ivas_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new ); + + return; +} + + +/*-------------------------------------------------------------------* + * InternalTCXDecoder_fx() + * + * + *-------------------------------------------------------------------*/ + +void InternalTCXDecoder_fx( + Encoder_State *st, /* i/o: state handle */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + const Word16 L_frameTCX, /* i : full frame length */ + const Word16 L_frame, /* i : frame length */ + const Word16 L_spec, /* i : length of the coded spectrum */ + const Word16 tcx_offset, /* i : folding point offset relative to the end of the previous frame */ + const Word16 noiseFillingBorder, /* i : noise filling border */ + const Word32 *x_quant_fx, /* i : quantized spectrum, exponent same as spectrum_e */ + const Word32 ener_fx, /* i : energy of the quantized spectrum */ + const Word16 ener_e, /* i : exponent of energy of the quantized spectrum */ + Word16 lf_deemph_fact_fx[], /* i/o: low frequency deemphasis factors */ + const Word16 fac_ns_fx, /* i : noise filling level, Q15 */ + const Word16 nf_seed, /* i : noise filling random seed, Q0 */ + const Word16 *A_fx, /* i : LPC representation of the FDNS gains, Q = 14 - norm_s(A_fx[0]) */ + Word16 gainlpc_fx[], /* i/o: FDNS gains */ + Word16 gainlpc_e[], /* i/o: FDNS gains exponents */ + const Word16 hm_active, /* i : flag indicating if the harmonic model is active */ + Word16 gain_tcx_fx, /* i/o: global gain / quantized global gain */ + Word16 *gain_tcx_e, /* i/o: global gain / quantized global gain exponent */ + Word32 spectrum_fx[], /* o : dequantized spectrum */ + Word16 *spectrum_e, /* o : exponent of dequantized spectrum */ + Word16 synth[], /* o : time domain signal */ + Word16 *gain_tcx_q /* o : quantized global gain (at low bitrates), Q0 */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 i, iStart, noiseTransWidth; + Word16 tcx_last_overlap_mode, overlap; + Word16 nz; /* non-zero length in ALDO window*/ + Word16 aldo; /* ALDO flag in current frame*/ + Word16 tmp1, tmp2, tmp3, tmp4, s; + Word16 *tmpP16; + Word16 q_spec, len; + Word32 tmp32; + Word32 xn_buf32[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + Word16 Aq_old_fx[M + 1]; + Word32 sns_interpolated_scalefactors_fx[FDNS_NPTS], A_fx32[M + 1]; + Word16 *xn_buf16 = (Word16 *) xn_buf32; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + Copy32( x_quant_fx, spectrum_fx, s_max( L_frame, L_spec ) ); + + /* Replication of ACELP formant enhancement for low rates */ + test(); + IF( st->total_brate < ACELP_13k20 || st->rf_mode ) + { + tcxFormantEnhancement( lf_deemph_fact_fx, gainlpc_fx, gainlpc_e, spectrum_fx, spectrum_e, L_frame, L_spec ); + } + + /*-----------------------------------------------------------* + * Noise Filling. * + *-----------------------------------------------------------*/ + + IF( fac_ns_fx > 0 ) + { + tmp1 = 0; + move16(); + test(); + if ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 ) + { + tmp1 = 1; + move16(); + } + iStart = tcxGetNoiseFillingTilt( A_fx, M, L_frame, tmp1, &hTcxEnc->noiseTiltFactor ); + + tmp1 = 0; + move16(); + test(); + test(); + if ( st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active ) + { + tmp1 = 1; + move16(); + } + noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame, shr( st->L_frame, 1 ) ), hTcxEnc->tcxltp_gain, tmp1 ); + assert( st->element_mode != IVAS_CPE_MDCT ); + tcx_noise_filling( spectrum_fx, *spectrum_e, nf_seed, iStart, noiseFillingBorder, noiseTransWidth, L_frame, hTcxEnc->noiseTiltFactor, fac_ns_fx, NULL, st->element_mode ); + } + + test(); + IF( LT_32( st->total_brate, ACELP_13k20 ) || st->rf_mode != 0 ) + { + /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */ + s = sub( getScaleFactor32( spectrum_fx, L_spec ), 4 ); + tmp32 = L_deposit_l( 1 ); + + FOR( i = 0; i < L_spec; i++ ) + { + tmp1 = round_fx( L_shl( spectrum_fx[i], s ) ); + tmp32 = L_mac0( tmp32, tmp1, tmp1 ); + } + + tmp1 = BASOP_Util_Divide3232_Scale( ener_fx, tmp32, &tmp2 ); + tmp2 = add( tmp2, sub( ener_e, add( shl( sub( *spectrum_e, s ), 1 ), 1 ) ) ); + tmp1 = Sqrt16( tmp1, &tmp2 ); + + gain_tcx_fx = mult( gain_tcx_fx, tmp1 ); + *gain_tcx_e = add( *gain_tcx_e, tmp2 ); + move16(); + + QuantizeGain( L_spec, &gain_tcx_fx, gain_tcx_e, gain_tcx_q ); + } + + /*end of noise filling*/ + + /*-----------------------------------------------------------* + * Noise shaping in frequency domain (1/Wz) * + *-----------------------------------------------------------*/ + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Copy_Scale_sig_16_32( A_fx, A_fx32, M + 1, add( norm_s( A_fx[0] ), 2 ) ); // Copying the Word16 A_fx buffer to a temporary Word32 buffer in Q16 + + q_spec = sub( 31, *spectrum_e ); + sns_interpolate_scalefactors_fx( sns_interpolated_scalefactors_fx, A_fx32, DEC ); + sns_shape_spectrum_fx( spectrum_fx, &q_spec, st->hTcxCfg->psychParamsCurrent, sns_interpolated_scalefactors_fx, Q16, L_frame, &len ); + + test(); + test(); + IF( NE_16( len, L_frame ) && LT_16( q_spec, sub( 31, *spectrum_e ) ) ) + { + scale_sig32( spectrum_fx + len, sub( L_frame, len ), sub( q_spec, sub( 15, *spectrum_e ) ) ); + } + ELSE IF( NE_16( len, L_frame ) && GT_16( q_spec, sub( 31, *spectrum_e ) ) ) + { + scale_sig32( spectrum_fx, len, sub( sub( 15, *spectrum_e ), q_spec ) ); + q_spec = sub( 31, *spectrum_e ); + } + *spectrum_e = sub( 31, q_spec ); + move16(); + } + ELSE + { + mdct_shaping( spectrum_fx, L_frame, gainlpc_fx, gainlpc_e ); + } + /*-----------------------------------------------------------* + * Apply gain * + *-----------------------------------------------------------*/ + + IF( EQ_16( st->hTcxCfg->coder_type, INACTIVE ) ) + { + gain_tcx_fx = mult_r( gain_tcx_fx, st->hTcxCfg->na_scale ); + } + + FOR( i = 0; i < L_spec; i++ ) + { + spectrum_fx[i] = Mpy_32_16_1( spectrum_fx[i], gain_tcx_fx ); + move32(); + } + *spectrum_e = add( *spectrum_e, *gain_tcx_e ); + move16(); + + tcx_last_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + move16(); + + test(); + IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) ) + { + Word16 L = L_frame; + move16(); + + test(); + test(); + if ( ( ( st->hTcxCfg->fIsTNSAllowed != 0 ) && ( hTcxEnc->fUseTns[frame_cnt] != 0 ) ) || ( GT_16( L_spec, L_frame ) ) ) + { + L = L_spec; + move16(); + } + + tcxInvertWindowGrouping( st->hTcxCfg, + xn_buf32, + spectrum_fx, + L, + hTcxEnc->fUseTns[frame_cnt], + st->last_core, + tcx_last_overlap_mode, + frame_cnt, + 0 ); + } + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + + IF( st->hTcxCfg->fIsTNSAllowed ) + { + test(); + SetTnsConfig( st->hTcxCfg, (Word16) EQ_16( st->core, TCX_20_CORE ), ( st->last_core == ACELP_CORE ) && ( frame_cnt == 0 ) ); + + /* Apply TNS to get the reconstructed signal */ + IF( hTcxEnc->fUseTns[frame_cnt] != 0 ) + { + ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frame_cnt], spectrum_fx, 0 ); + + test(); + IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) ) + { + test(); + test(); + test(); + IF( ( st->hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) || + ( ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( tcx_last_overlap_mode == 0 ) ) ) + { + const Word16 L_win = shr( L_spec, 1 ); + /* undo rearrangement of LF sub-window lines for TNS synthesis filter */ + IF( GT_16( L_frame, L_spec ) ) + { + assert( 0 ); + } + ELSE + { + Copy32( spectrum_fx + 8, xn_buf32, L_win ); + Copy32( xn_buf32, spectrum_fx + L_win, 8 ); + Copy32( xn_buf32 + 8, spectrum_fx + 8, L_win - 8 ); + } + } + } + } + } + + + /*-----------------------------------------------------------* + * Compute inverse MDCT of spectrum[]. * *-----------------------------------------------------------*/ - /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ - tcx_encoder_memory_update_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new, shift ); + E_LPC_f_lsp_a_conversion( st->lsp_old_fx, Aq_old_fx, M ); + overlap = st->hTcxCfg->tcx_mdct_window_length; + nz = NS2SA_FX2( st->sr_core, N_ZERO_MDCT_NS ); + aldo = 0; + move16(); + move16(); + + /* normalize spectrum to minimize IMDCT noise */ + s = getScaleFactor32( spectrum_fx, L_frame ); + FOR( i = 0; i < L_frame; i++ ) + { + spectrum_fx[i] = L_shl( spectrum_fx[i], s ); + move32(); + } + *spectrum_e = sub( *spectrum_e, s ); + move16(); + + test(); + IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) ) + { + IF( st->hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) + { + Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2]; + Word16 L_win, L_spec_TCX5, L_ola, w; + + /* minimum or half overlap, two transforms, grouping into one window */ + L_win = shr( L_frame, 1 ); + L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 ); + L_ola = st->hTcxCfg->tcx_mdct_window_half_length; + move16(); + if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) ) + { + L_ola = st->hTcxCfg->tcx_mdct_window_min_length; + move16(); + } + + set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 ); + set16_fx( xn_buf16, 0, add( tcx_offset, shr( L_ola, 1 ) ) ); /* zero left end of buffer */ + + FOR( w = 0; w < 2; w++ ) + { + + IF( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) ) + { + TCX_MDCT_Inverse( spectrum_fx + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), + win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode ); + } + ELSE + { + TCX_MDCT_Inverse( spectrum_fx + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), win, + L_ola, sub( L_win, L_ola ), L_ola, st->element_mode ); + } + + tmp1 = st->hTcxCfg->tcx_last_overlap_mode; + move16(); + test(); + test(); + if ( ( w > 0 ) || ( ( w == 0 ) && ( EQ_16( tcx_last_overlap_mode, 2 ) ) ) ) + { + tmp1 = MIN_OVERLAP; + move16(); + } + + tmp2 = 0; + move16(); + test(); + if ( ( w == 0 ) && ( st->last_core == ACELP_CORE ) ) + { + tmp2 = 1; + move16(); + } + + tmp3 = st->last_core; + move16(); + if ( w > 0 ) + { + tmp3 = 1; + move16(); + } + + tmp4 = 0; + move16(); + if ( tcx_offset < 0 ) + { + tmp4 = negate( tcx_offset ); + } + + tcx_windowing_synthesis_current_frame( win, + st->hTcxCfg->tcx_aldo_window_2, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + L_ola, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + tmp2, + tmp1, + hTcxEnc->acelp_zir, + hTcxEnc->Txnq, + NULL, + Aq_old_fx, + st->hTcxCfg->tcx_mdct_window_trans, + L_win, + tmp4, + tmp3, + 0, + 0 ); + + tmp1 = add( tcx_offset, imult1616( w, L_win ) ); + move16(); + tmpP16 = xn_buf16 + sub( tmp1, shr( L_ola, 1 ) ); + + IF( w > 0 ) + { + tcx_windowing_synthesis_past_frame( tmpP16, + st->hTcxCfg->tcx_aldo_window_1_trunc, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + L_ola, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + 2 ); + } + /* add part of current sub-window overlapping with previous window */ + FOR( i = 0; i < L_ola; i++ ) + { +#ifdef BASOP_NOGLOB + tmpP16[i] = add_sat( tmpP16[i], win[i] ); +#else + tmpP16[i] = add( tmpP16[i], win[i] ); +#endif + move16(); + } + /* copy new sub-window region not overlapping with previous window */ + Copy( win + L_ola, xn_buf16 + add( tmp1, shr( L_ola, 1 ) ), L_win ); + } + /* To assure that no garbage values are copied to hLPDmem->Txnq */ + set16_fx( xn_buf16 + add( add( L_frame, tcx_offset ), shr( L_ola, 1 ) ), + 0, sub( sub( overlap, tcx_offset ), shr( L_ola, 1 ) ) ); + } + ELSE IF( s_and( frame_cnt == 0, ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) ) + { + /* special overlap attempt, two transforms, grouping into one window */ + Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2]; + Word16 L_win, L_spec_TCX5, L_ola, w; + + L_win = shr( L_frame, 1 ); + L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 ); + L_ola = st->hTcxCfg->tcx_mdct_window_min_length; + move16(); + + set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 ); + + /* Resize overlap (affect only asymmetric window)*/ + overlap = st->hTcxCfg->tcx_mdct_window_delay; + /* 1st TCX-5 window, special MDCT with minimum overlap on right side */ + TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), + win + L_win, 0, sub( L_win, shr( L_ola, 1 ) ), L_ola, st->element_mode ); + + /* copy new sub-window region not overlapping with previous window */ + Copy( win + L_win, xn_buf16 + shr( overlap, 1 ), add( L_win, shr( L_ola, 1 ) ) ); + + /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */ + + TCX_MDCT_Inverse( spectrum_fx + L_spec_TCX5, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), + win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode ); + + tmp4 = 0; + move16(); + if ( tcx_offset < 0 ) + { + tmp4 = negate( tcx_offset ); + } + tcx_windowing_synthesis_current_frame( win, + st->hTcxCfg->tcx_aldo_window_2, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + L_ola, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + 0, /* left_rect */ + 2, /* left_mode */ + hTcxEnc->acelp_zir, + hTcxEnc->Txnq, + NULL, + Aq_old_fx, + st->hTcxCfg->tcx_mdct_window_trans, + L_win, + tmp4, + 1, /* not LPDmem->mode */ + 0, + 0 ); + + + move16(); + tmpP16 = xn_buf16 + add( sub( L_win, shr( L_ola, 1 ) ), shr( overlap, 1 ) ); + + tcx_windowing_synthesis_past_frame( tmpP16, + st->hTcxCfg->tcx_aldo_window_1_trunc, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + L_ola, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + 2 ); + + /* add part of current sub-window overlapping with previous window */ + FOR( i = 0; i < L_ola; i++ ) + { +#ifdef BASOP_NOGLOB + tmpP16[i] = add_sat( tmpP16[i], win[i] ); +#else + tmpP16[i] = add( tmpP16[i], win[i] ); +#endif + move16(); + } + + /* copy new sub-window region not overlapping with previous window */ + Copy( win + L_ola, + xn_buf16 + add( add( shr( overlap, 1 ), shr( L_ola, 1 ) ), L_win ), + L_win ); + + /* extra folding-out on left side of win, for perfect reconstruction */ + FOR( w = shr( overlap, 1 ); w < overlap; w++ ) + { + xn_buf16[overlap - 1 - w] = negate( xn_buf16[w] ); + move16(); + } + + tmp4 = 0; + move16(); + if ( tcx_offset < 0 ) + { + tmp4 = negate( tcx_offset ); + } + tcx_windowing_synthesis_current_frame( xn_buf16, + st->hTcxCfg->tcx_aldo_window_2, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + overlap, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + st->last_core == ACELP_CORE, + 0, + hTcxEnc->acelp_zir, + hTcxEnc->Txnq, + NULL, + Aq_old_fx, + st->hTcxCfg->tcx_mdct_window_trans, + L_win, + tmp4, + st->last_core, + 0, + 0 ); + } + ELSE /* default, i.e. maximum overlap, single transform, no grouping */ + { + + TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), + xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode ); + + tmp1 = tcx_last_overlap_mode; + move16(); + test(); + test(); + if ( ( frame_cnt > 0 ) && ( tcx_last_overlap_mode == 0 ) && ( st->last_core != ACELP_CORE ) ) + { + tmp1 = 2; + move16(); + } + + tmp4 = 0; + move16(); + if ( tcx_offset < 0 ) + { + tmp4 = negate( tcx_offset ); + } + tcx_windowing_synthesis_current_frame( xn_buf16, + st->hTcxCfg->tcx_aldo_window_2, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + overlap, /*hTcxCfg->tcx_mdct_window_length*/ + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + st->last_core == ACELP_CORE, + tmp1, + hTcxEnc->acelp_zir, + hTcxEnc->Txnq, + NULL, + Aq_old_fx, + st->hTcxCfg->tcx_mdct_window_trans, + shr( st->L_frame, 2 ), + tmp4, + st->last_core, + 0, + 0 ); + + } /* tcx_last_overlap_mode > 0 */ + } + ELSE /* frame is TCX-20 or not TCX-only */ + { + IF( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q; + + /* DCT */ + Q = sub( 31, *spectrum_e ); + edct_fx( spectrum_fx, tmp_buf, L_frame, &Q ); + + /* scale by sqrt(L / NORM_MDCT_FACTOR) */ + tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = Sqrt16( tmp1, &tmp2 ); + + FOR( i = 0; i < L_frame; i++ ) + { + tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 ); + move32(); + } + Q = sub( Q, tmp2 ); + + + window_ola_fx( tmp_buf, + xn_buf16, + &Q, + hTcxEnc->old_out_fx, + &hTcxEnc->Q_old_out, + L_frame, + st->hTcxCfg->tcx_last_overlap_mode, + st->hTcxCfg->tcx_curr_overlap_mode, + 0, + 0, + NULL ); + + /* scale output */ + FOR( i = 0; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shr_o( xn_buf16[i], Q, &Overflow ); +#else /* BASOP_NOGLOB */ + xn_buf16[i] = shr( xn_buf16[i], Q ); +#endif /* BASOP_NOGLOB */ + move16(); + } + + aldo = 1; + move16(); + } + ELSE + { + + TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), + xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode ); + + /*-----------------------------------------------------------* + * Windowing, overlap and add * + *-----------------------------------------------------------*/ + + /* Window current frame */ + tmp4 = 0; + move16(); + if ( tcx_offset < 0 ) + { + tmp4 = negate( tcx_offset ); + } + tcx_windowing_synthesis_current_frame( xn_buf16, + st->hTcxCfg->tcx_aldo_window_2, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + overlap, /*hTcxCfg->tcx_mdct_window_length*/ + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + st->last_core == ACELP_CORE, + st->hTcxCfg->tcx_last_overlap_mode, /*left mode*/ + hTcxEnc->acelp_zir, + hTcxEnc->Txnq, + NULL, + Aq_old_fx, + st->hTcxCfg->tcx_mdct_window_trans, + shr( st->L_frame, 1 ), + tmp4, + st->last_core, + 0, + 0 ); + } + } /* TCX-10 and TCX-only */ + + /* Window and overlap-add past frame if past frame is TCX */ + test(); + test(); + test(); + IF( ( st->last_core > ACELP_CORE ) && ( ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) && ( st->tcxonly != 0 ) ) || ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) ) + { + + IF( st->hTcxCfg->last_aldo != 0 ) + { + tmp2 = add( hTcxEnc->Q_old_out, TCX_IMDCT_HEADROOM ); + + tmp1 = sub( overlap, st->hTcxCfg->tcx_mdct_window_min_length ); + FOR( i = 0; i < tmp1; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], shr_sat( hTcxEnc->old_out_fx[i + nz], tmp2 ) ), TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( add( xn_buf16[i], shr( hTcxEnc->old_out_fx[i + nz], tmp2 ) ), TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + + /* fade truncated ALDO window */ + tmp1 = sub( overlap, shr( st->hTcxCfg->tcx_mdct_window_min_length, 1 ) ); + FOR( ; i < tmp1; i++ ) + { + tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), st->hTcxCfg->tcx_mdct_window_minimum[i - overlap + st->hTcxCfg->tcx_mdct_window_min_length].v.re ); +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( add( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + FOR( ; i < overlap; i++ ) + { + tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), st->hTcxCfg->tcx_mdct_window_minimum[overlap - 1 - i].v.im ); +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( add( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + + FOR( ; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( xn_buf16[i], TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + } + ELSE + { + test(); + test(); + test(); + if ( ( frame_cnt > 0 ) && ( tcx_last_overlap_mode == 0 ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( st->last_core != ACELP_CORE ) ) + { + tcx_last_overlap_mode = 2; /* use minimum overlap between the two TCX-10 windows */ + move16(); + } + + tmp1 = tcx_last_overlap_mode; + move16(); + test(); + if ( ( tcx_last_overlap_mode == 0 ) || ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) ) ) + { + tmp1 = st->hTcxCfg->tcx_last_overlap_mode; + move16(); + } + + tcx_windowing_synthesis_past_frame( hTcxEnc->Txnq, st->hTcxCfg->tcx_aldo_window_1_trunc, st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, overlap, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, tmp1 ); + + BASOP_SATURATE_WARNING_OFF_EVS; + FOR( i = 0; i < overlap; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( add( xn_buf16[i], hTcxEnc->Txnq[i] ), TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( add( xn_buf16[i], hTcxEnc->Txnq[i] ), TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + + IF( LT_16( i, L_frame ) ) + { + FOR( ; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM ); +#else + xn_buf16[i] = shl( xn_buf16[i], TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + } + BASOP_SATURATE_WARNING_ON_EVS; + } + } + ELSE + { + IF( aldo == 0 ) + { + BASOP_SATURATE_WARNING_OFF_EVS; + FOR( i = 0; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + xn_buf16[i] = shl_o( xn_buf16[i], TCX_IMDCT_HEADROOM, &Overflow ); +#else /* BASOP_NOGLOB */ + xn_buf16[i] = shl( xn_buf16[i], TCX_IMDCT_HEADROOM ); +#endif + move16(); + } + BASOP_SATURATE_WARNING_ON_EVS; + } + } + + test(); + test(); + test(); + IF( ( aldo == 0 ) && + ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) && frame_cnt > 0 ) || + NE_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) ) + { + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + FOR( i = 0; i < nz; i++ ) + { + hTcxEnc->old_out_fx[i] = shr( xn_buf16[L_frame - nz + i], TCX_IMDCT_HEADROOM ); + move16(); + } + Copy( xn_buf16 + L_frame, hTcxEnc->old_out_fx + nz, overlap ); + set16_fx( hTcxEnc->old_out_fx + nz + overlap, 0, nz ); + + tcx_windowing_synthesis_past_frame( hTcxEnc->old_out_fx + nz, + st->hTcxCfg->tcx_aldo_window_1_trunc, + st->hTcxCfg->tcx_mdct_window_half, + st->hTcxCfg->tcx_mdct_window_minimum, + overlap, + st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, + st->hTcxCfg->tcx_curr_overlap_mode ); + + /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */ + IF( EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) + { + FOR( i = 0; i < nz; i++ ) + { + hTcxEnc->old_out_fx[nz + overlap + i] = shr( mult_r( xn_buf16[L_frame - 1 - i], st->hTcxCfg->tcx_aldo_window_1[nz - 1 - i] ), TCX_IMDCT_HEADROOM ); + move16(); + } + } + + hTcxEnc->Q_old_out = -TCX_IMDCT_HEADROOM; + move16(); + } + st->hTcxCfg->last_aldo = aldo; + move16(); + + /* Update Txnq */ + IF( st->hTcxCfg->last_aldo == 0 ) + { + Copy( xn_buf16 + L_frame, hTcxEnc->Txnq, overlap ); + } + + tmp1 = L_frame; + move16(); + if ( EQ_16( st->core, TCX_20_CORE ) ) + { + tmp1 = st->L_frame; + move16(); + } + + /* Output */ + Copy( xn_buf16 + shr( overlap, 1 ) - tcx_offset, synth, tmp1 ); return; } +#endif diff --git a/lib_enc/core_enc_2div.c b/lib_enc/core_enc_2div.c index 870f6e50cd98201a5be3ede97887d8b02c68dff4..019a5658638fc50c6970a00d8346215ef22a88ce 100644 --- a/lib_enc/core_enc_2div.c +++ b/lib_enc/core_enc_2div.c @@ -41,6 +41,7 @@ #include "rom_com.h" #include "wmc_auto.h" +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * core_encode_twodiv() * @@ -241,3 +242,4 @@ void core_encode_twodiv( return; } +#endif diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index 98483e7f8cbcd5eefbc0a99cbae586932614fc0a..887fb759b425dc60845f80054fe88da166afcee2 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -44,6 +44,10 @@ #include "prot_fx.h" #include "prot_fx_enc.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ @@ -440,6 +444,11 @@ void init_coder_ace_plus( set_zero( hTcxEnc->Txnq_flt, L_FRAME32k / 2 + 64 ); hTcxEnc->acelp_zir_flt = hTcxEnc->Txnq_flt + L_FRAME / 2; hTcxEnc->tcx_target_bits_fac_flt = 1.0f; + +#ifdef IVAS_FLOAT_FIXED + set16_fx( hTcxEnc->Txnq, 0, L_FRAME32k / 2 + 64 ); + hTcxEnc->acelp_zir = hTcxEnc->Txnq + L_FRAME / 2; +#endif } } @@ -701,7 +710,8 @@ static void init_tcx_ivas_fx( hTcxEnc->kernel_switch_corr_past = 0; hTcxEnc->kernel_symmetry_past = 0; /* MDCT_IV & 1 */ hTcxEnc->enc_ste_pre_corr_past = 0; - hTcxEnc->tfm_mem_fx = 12288 /*0.75 in Q14*/; + // hTcxEnc->tfm_mem_fx = 12288 /*0.75 in Q14*/; + hTcxEnc->tfm_mem_fx = 1610612736; #ifdef IVAS_FLOAT_FIXED_CONVERSIONS hTcxEnc->tfm_mem = 0.75f; #endif @@ -985,7 +995,7 @@ static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_ol { set16_fx( hTcxEnc->buf_speech_ltp, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); } - set16_fx( st->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + set16_fx( st->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); /* increased by 320 to avoid memory overlap in ivas_find_wsp() and also to accomodate for the wspeech_enc */ } ELSE { @@ -1061,8 +1071,13 @@ static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_ol if ( st->hTcxEnc != NULL ) { - hTcxEnc->new_speech_TCX = st->input_buff_fx + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) - NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ); - hTcxEnc->speech_TCX = hTcxEnc->new_speech_TCX - st->encoderLookahead_FB; + st->hTcxEnc->new_speech_TCX_flt = st->input_buff + st->input_Fs / FRAMES_PER_SEC; /* note: in EVS st->new_speech_TCX == st->input - 0.9375ms; in IVAS st->new_speech_TCX == st->input */ + st->hTcxEnc->speech_TCX_flt = st->hTcxEnc->new_speech_TCX_flt - st->encoderLookahead_FB; + +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->new_speech_TCX = st->input_buff_fx + Mpy_32_32( st->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ); + st->hTcxEnc->speech_TCX = st->hTcxEnc->new_speech_TCX - st->encoderLookahead_FB; +#endif } st->speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc; st->speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc; @@ -1227,6 +1242,11 @@ static void init_acelp( { set_zero( st->hTcxEnc->Txnq_flt, L_FRAME32k / 2 + 64 ); st->hTcxEnc->acelp_zir_flt = st->hTcxEnc->Txnq_flt + ( st->L_frame / 2 ); + +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->hTcxEnc->Txnq, 0, L_FRAME32k / 2 + 64 ); + st->hTcxEnc->acelp_zir = st->hTcxEnc->Txnq + ( st->L_frame / 2 ); +#endif } } else /*Rate switching*/ @@ -1242,6 +1262,10 @@ static void init_acelp( lerp_flt( st->hTcxEnc->Txnq_flt, st->hTcxEnc->Txnq_flt, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_length_old ); } st->hTcxEnc->acelp_zir_flt = st->hTcxEnc->Txnq_flt + ( st->L_frame / 2 ); + +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->acelp_zir = st->hTcxEnc->Txnq + ( st->L_frame / 2 ); +#endif } /* Rate switching */ @@ -1474,7 +1498,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh /*AMR-WBIO->MODE2*/ IF( EQ_16( st->last_core, AMR_WB_CORE ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->last_core = ACELP_CORE; move16(); @@ -1484,7 +1508,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->last_core, HQ_CORE ) ) { /*Reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); @@ -1587,7 +1611,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh ELSE IF( ( NE_16( st->L_frame, L_frame_old ) ) ) { /*Partial reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index 58657bb6b78f737852110fc86262ef8ab352ae90..06eb4fc5b798449b360eeea63ec5a496dc48b996 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -136,7 +136,7 @@ void init_coder_ace_plus_fx( } - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); test(); test(); @@ -639,7 +639,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s /*AMR-WBIO->MODE2*/ IF( EQ_16( st->last_core, AMR_WB_CORE ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->last_core = ACELP_CORE; move16(); @@ -649,7 +649,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->last_core, HQ_CORE ) ) { /*Reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); @@ -740,7 +740,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s ELSE IF( ( NE_16( st->L_frame, L_frame_old ) ) ) { /*Partial reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); diff --git a/lib_enc/core_enc_ol.c b/lib_enc/core_enc_ol.c index 85c1c0b04ce03a0109f12d923ca54dc84961b96a..562e28d7706d742b74ad5a501996a728ca909882 100644 --- a/lib_enc/core_enc_ol.c +++ b/lib_enc/core_enc_ol.c @@ -42,7 +42,12 @@ #include "rom_com.h" #include "basop_proto_func.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#include "prot_fx_enc.h" +#endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * Local function prototypes *-------------------------------------------------------------------*/ @@ -260,7 +265,14 @@ void core_encode_openloop( /* reset TBE buffers previous frame frame wasn't ACELP*/ if ( st->last_core != ACELP_CORE ) { +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif +#else + TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif } /* Run ACELP encoder */ @@ -1174,3 +1186,4 @@ static void BITS_ALLOC_TCX_config_rf( int16_t *rf_frame_type, int16_t *rf_target } return; } +#endif diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c index e5bf41ca4a85add9a0b79eeeaffabf4724bab242..ba125469f1643fad4b32e0f025fc5ca2d757ccc7 100644 --- a/lib_enc/core_enc_switch.c +++ b/lib_enc/core_enc_switch.c @@ -39,8 +39,10 @@ #include "prot.h" #include "rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" #include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* @@ -272,8 +274,7 @@ void core_coder_mode_switch_ivas_fx( return; } -#endif - +#else void core_coder_mode_switch( Encoder_State *st, /* i/o: encoder state structure */ const int32_t last_total_brate, /* i : last bitrate */ @@ -387,7 +388,14 @@ void core_coder_mode_switch( ( st->bwidth == SWB && st->last_extl != SWB_TBE ) || ( st->bwidth == FB && st->last_extl != FB_TBE ) ) { +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif +#else TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif } else { @@ -422,3 +430,4 @@ void core_coder_mode_switch( return; } +#endif diff --git a/lib_enc/core_enc_updt.c b/lib_enc/core_enc_updt.c index bfd845b496e4c8bb1cb495119a53845f29ff5fb9..a388365f601d0c3da953e481684d19d62fca94e9 100644 --- a/lib_enc/core_enc_updt.c +++ b/lib_enc/core_enc_updt.c @@ -40,6 +40,9 @@ #include "rom_com.h" #include "cnst.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif /*-------------------------------------------------------------------* * core_encode_update() @@ -104,6 +107,79 @@ void core_encode_update( } +#ifdef IVAS_FLOAT_FIXED +void core_encode_update_ivas_fx( + Encoder_State *st /* i/o: Encoder state structure */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 n; + + /* Update Input Signal Buffers */ + n = add( st->encoderPastSamples_enc, st->encoderLookahead_enc ); + + Copy( st->buf_speech_enc_pe + st->L_frame, st->buf_speech_enc_pe, n ); + Copy( st->buf_speech_enc + st->L_frame, st->buf_speech_enc, n ); + + IF( !st->tcxonly ) + { + n = add( st->L_frame, shr( st->L_frame, 2 ) ); + Copy( st->buf_wspeech_enc + st->L_frame, st->buf_wspeech_enc, n ); + } + + IF( hTcxEnc != NULL ) + { + test(); + test(); + test(); + IF( EQ_16( st->core, ACELP_CORE ) || EQ_16( st->core, AMR_WB_CORE ) || EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) + { + Word16 max_e = s_max( st->hTcxEnc->exp_buf_speech_ltp, hTcxEnc->exp_buf_speech_ltp ); + Scale_sig( hTcxEnc->buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k, -( max_e - st->hTcxEnc->exp_buf_speech_ltp ) ); + Copy_Scale_sig( st->buf_speech_enc + st->L_frame, hTcxEnc->buf_speech_ltp + st->L_frame, st->L_frame, -( max_e - st->exp_buf_speech_enc ) ); + st->hTcxEnc->exp_buf_speech_ltp = max_e; + } + } + + n = add( st->encoderPastSamples_enc, st->encoderLookahead_enc ); + Copy( st->buf_synth + st->L_frame, st->buf_synth, st->L_frame + L_SUBFR ); + IF( hTcxEnc != NULL ) + { + Copy( hTcxEnc->buf_speech_ltp + st->L_frame, hTcxEnc->buf_speech_ltp, n ); + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + st->hTcxEnc->kernel_switch_corr_past = 0; + st->hTcxEnc->kernel_type[0] = MDCT_IV; + st->hTcxEnc->kernel_symmetry_past = 0; + st->hTcxEnc->enc_ste_pre_corr_past = 0; + + move16(); + move16(); + move16(); + move16(); + } + } + +#ifdef NON_BE_1055_RESET_LP_MEMORIES + test(); + test(); + test(); + test(); + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) +#else + if ( ( st->Opt_DTX_ON && st->core_brate <= SID_2k40 && st->cng_type == FD_CNG ) || ( st->tcxonly && st->codec_mode == MODE2 ) ) +#endif + { + /* reset LP memories */ + set16_fx( st->mem_MA_fx, 0, M ); + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); // 2.56 scaling + } + return; +} +#endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * core_encode_update_cng() * @@ -204,3 +280,4 @@ void core_encode_update_cng( return; } +#endif diff --git a/lib_enc/core_switching_enc.c b/lib_enc/core_switching_enc.c index 075868e79569c1f2ea3b279ff9732337186e1447..3362ca589a2f65631b84ac95fdc9b67ada00c6ab 100644 --- a/lib_enc/core_switching_enc.c +++ b/lib_enc/core_switching_enc.c @@ -42,12 +42,13 @@ #include "rom_com.h" #include "prot.h" #include "wmc_auto.h" - #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot_fx.h" #endif + /*---------------------------------------------------------------------* * core_switching_pre_enc() * @@ -761,10 +762,13 @@ void core_switching_pre_enc_ivas_fx( *---------------------------------------------------------------------*/ void core_switching_post_enc( - Encoder_State *st, /* i/o: encoder state structure */ - const float *old_inp_12k8, /* i : old input signal @12.8kHz */ - const float *old_inp_16k, /* i : old input signal @16kHz */ - const float A[] /* i : unquant. LP filter coefs. */ + Encoder_State *st, /* i/o: encoder state structure */ + // const float *old_inp_12k8, /* i : old input signal @12.8kHz */ + float *old_inp_12k8, /* i : old input signal @12.8kHz */ + // const float *old_inp_16k, /* i : old input signal @16kHz */ + float *old_inp_16k, /* i : old input signal @16kHz */ + // const float A[] /* i : unquant. LP filter coefs. */ + float A[] /* i : unquant. LP filter coefs. */ ) { if ( st->core == HQ_CORE ) @@ -773,9 +777,53 @@ void core_switching_post_enc( if ( ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) && st->element_mode == EVS_MONO ) /* core switching ==> ACELP subframe encoding */ { +#ifndef IVAS_FLOAT_FIXED acelp_core_switch_enc( st, old_inp_12k8 + L_INP_MEM - NS2SA( INT_FS_12k8, ACELP_LOOK_NS ), old_inp_16k + L_INP_MEM - NS2SA( INT_FS_16k, ACELP_LOOK_NS ), A ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from float to fix + Word16 Q_new; + Q_new = Q_factor_arr( old_inp_12k8, L_INP_12k8 ); + Word16 old_inp_12k8_fx[L_INP_12k8]; + Word16 old_inp_16k_fx[L_INP]; + Word16 A_fx[NB_SUBFR16k * ( M + 1 )]; + floatToFixed_arr( st->old_input_signal, st->old_input_signal_fx, 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + floatToFixed_arr( old_inp_12k8, old_inp_12k8_fx, Q_new, L_INP_12k8 ); + floatToFixed_arr( old_inp_16k, old_inp_16k_fx, Q_new, L_INP ); + floatToFixed_arr( A, A_fx, 12, NB_SUBFR16k * ( M + 1 ) ); + float temp = (float) st->clip_var[0] * ( 2.56f ); + st->clip_var_fx[0] = float_to_fix16( temp, 0 ); + st->clip_var_fx[1] = float_to_fix16( st->clip_var[1], 14 ); + st->clip_var_fx[2] = float_to_fix16( st->clip_var[2], 8 ); + st->clip_var_fx[3] = float_to_fix16( st->clip_var[3], 0 ); + st->clip_var_fx[4] = float_to_fix16( st->clip_var[4], 14 ); + st->clip_var_fx[5] = float_to_fix16( st->clip_var[5], 14 ); + floatToFixed_arr( st->voicing, st->voicing_fx, 15, 3 ); + st->hLPDmem->tilt_code = float_to_fix16( st->hLPDmem->tilt_code_flt, 15 ); + floatToFixed_arr( st->old_Aq_12_8, st->old_Aq_12_8_fx, 12, M + 1 ); + st->old_Es_pred_fx = float_to_fix16( st->old_Es_pred, 8 ); + st->hLPDmem->mem_w0 = float_to_fix16( st->hLPDmem->mem_w0_flt, Q_new - 1 ); + floatToFixed_arr( st->hLPDmem->mem_syn_flt, st->hLPDmem->mem_syn, Q_new - 1, M ); + +#endif + acelp_core_switch_enc_ivas_fx( st, old_inp_12k8_fx + L_INP_MEM - NS2SA( INT_FS_12k8, ACELP_LOOK_NS ), old_inp_16k_fx + L_INP_MEM - NS2SA( INT_FS_16k, ACELP_LOOK_NS ), A_fx, 0, Q_new ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from fix to float + fixedToFloat_arr( st->old_input_signal_fx, st->old_input_signal, 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + temp = (float) fix16_to_float( st->clip_var_fx[0], 0 ) / 2.56f; + st->clip_var[0] = temp; + st->clip_var[1] = fix16_to_float( st->clip_var_fx[1], 14 ); + st->clip_var[2] = fix16_to_float( st->clip_var_fx[2], 8 ); + st->clip_var[3] = fix16_to_float( st->clip_var_fx[3], 0 ); + st->clip_var[4] = fix16_to_float( st->clip_var_fx[4], 14 ); + st->clip_var[5] = fix16_to_float( st->clip_var_fx[5], 14 ); + st->hLPDmem->tilt_code = float_to_fix16( st->hLPDmem->tilt_code_flt, 15 ); + st->hLPDmem->mem_w0_flt = fix16_to_float( st->hLPDmem->mem_w0, Q_new - 1 ); +#endif +#endif } + st->hBWE_TD->bwe_non_lin_prev_scale = 0.0; st->hBWE_FD->mem_deemph_old_syn = 0.0f; } @@ -789,8 +837,15 @@ void core_switching_post_enc( /* reset SWB TBE buffers */ if ( st->extl == WB_TBE && st->last_extl != WB_TBE ) { +#ifdef IVAS_FLOAT_FIXED + wb_tbe_extras_reset_fx( st->hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, st->hBWE_TD->mem_genSHBexc_filt_down_wb3_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + set_f( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set_f( st->hBWE_TD->mem_genSHBexc_filt_down_wb3, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); +#endif +#else wb_tbe_extras_reset( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, st->hBWE_TD->mem_genSHBexc_filt_down_wb3 ); - +#endif if ( st->last_extl != WB_BWE ) { set_f( st->hBWE_TD->decim_state1, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); @@ -806,10 +861,24 @@ void core_switching_post_enc( ( st->last_core == HQ_CORE || st->L_frame != st->last_L_frame || ( st->last_extl != SWB_TBE && st->last_extl != FB_TBE && st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE ) ) ) { set_f( st->hBWE_TD->state_ana_filt_shb, 0.0f, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBufferStates_fx( st->hBWE_TD, NULL ); + swb_tbe_reset_fx( st->hBWE_TD->mem_csfilt_fx, st->hBWE_TD->mem_genSHBexc_filt_down_shb_fx, st->hBWE_TD->state_lpc_syn_fx, st->hBWE_TD->syn_overlap_fx, st->hBWE_TD->state_syn_shbexc_fx, &( st->hBWE_TD->tbe_demph_fx ), &( st->hBWE_TD->tbe_premph_fx ), st->hBWE_TD->mem_stp_swb_fx, &( st->hBWE_TD->gain_prec_swb_fx ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* To be removed later when the function is converted to fixed*/ + InitSWBencBufferStates( st->hBWE_TD, NULL ); + swb_tbe_reset( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_genSHBexc_filt_down_shb, st->hBWE_TD->state_lpc_syn, st->hBWE_TD->syn_overlap, st->hBWE_TD->state_syn_shbexc, &( st->hBWE_TD->tbe_demph ), &( st->hBWE_TD->tbe_premph ), st->hBWE_TD->mem_stp_swb, &( st->hBWE_TD->gain_prec_swb ) ); +#endif +#else InitSWBencBufferStates( st->hBWE_TD, NULL ); swb_tbe_reset( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_genSHBexc_filt_down_shb, st->hBWE_TD->state_lpc_syn, st->hBWE_TD->syn_overlap, st->hBWE_TD->state_syn_shbexc, &( st->hBWE_TD->tbe_demph ), &( st->hBWE_TD->tbe_premph ), st->hBWE_TD->mem_stp_swb, &( st->hBWE_TD->gain_prec_swb ) ); +#endif set_f( st->hBWE_TD->dec_2_over_3_mem, 0.0f, L_FILT_2OVER3 ); set_f( st->hBWE_TD->dec_2_over_3_mem_lp, 0.0f, L_FILT_2OVER3_LP ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->hBWE_TD->dec_2_over_3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( st->hBWE_TD->dec_2_over_3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); +#endif } else if ( ( st->extl == SWB_TBE || st->extl == FB_TBE ) && ( ( st->element_mode == IVAS_CPE_TD && st->last_extl != SWB_TBE && st->last_extl != FB_TBE ) || ( st->element_mode != IVAS_CPE_TD && st->last_total_brate != st->total_brate ) || ( st->last_bwidth != st->bwidth ) || ( st->last_codec_mode != MODE1 ) || ( st->rf_mode_last != st->rf_mode ) ) ) { @@ -821,7 +890,14 @@ void core_switching_post_enc( } else if ( st->last_core == TCX_20_CORE || st->last_core == TCX_10_CORE ) { +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif +#else + TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#endif } /* Interp_3_2 CNG buffers reset */ @@ -829,7 +905,14 @@ void core_switching_post_enc( { set_f( st->hBWE_TD->fb_state_lpc_syn, 0, LPC_SHB_ORDER ); st->hBWE_TD->fb_tbe_demph = 0; +#ifdef IVAS_FLOAT_FIXED + fb_tbe_reset_enc_fx( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx, &st->hBWE_TD->prev_fb_energy_fx, st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, &st->hBWE_TD->prev_fb_energy_fx_Q ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS fb_tbe_reset_enc( st->hBWE_TD->elliptic_bpf_2_48k_mem, &st->hBWE_TD->prev_fb_energy ); +#endif +#else + fb_tbe_reset_enc( st->hBWE_TD->elliptic_bpf_2_48k_mem, &st->hBWE_TD->prev_fb_energy ); +#endif } /* Fade towards init value for non HQ_CORE */ if ( st->hHQ_core != NULL ) diff --git a/lib_enc/corr_xh_fx.c b/lib_enc/corr_xh_fx.c index 86ba92c7a7c28d0cd2e92e551d1b6d195ab784c7..a999b893029c93c6cdfdb8018fa91c5a7ff9b5fa 100644 --- a/lib_enc/corr_xh_fx.c +++ b/lib_enc/corr_xh_fx.c @@ -80,3 +80,32 @@ void corr_xh_fx( } return; } + +void corr_xh_ivas_fx( + const Word16 *x, /* i : target signal Q_new - 1 */ + Word16 *y, /* o : correlation between x[] and h[] Q_new + 1 */ + const Word16 *h, /* i : impulse response (of weighted synthesis filter) e(norm_s(h1[0])+1) */ + const Word16 L_subfr /* i : length of the subframe */ +) +{ + Word16 i, j; + Word32 s; + Word32 y32[2 * L_SUBFR]; + + Word16 shift = add( norm_s( h[0] ), 1 ); + FOR( i = 0; i < L_subfr; i++ ) + { + s = 0; + move32(); + FOR( j = i; j < L_subfr; j++ ) + { + s = L_add( s, shl( mult( x[j], h[j - i] ), shift ) ); // Q_new - 1 + } + + y32[i] = s; // Q_new - 1 + move32(); + } + Copy_Scale_sig32_16( y32, y, L_subfr, 18 ); // Q_new + 1 + + return; +} diff --git a/lib_enc/decision_matrix_enc.c b/lib_enc/decision_matrix_enc.c index e6363d0cc42d5ad3fa9d08bbaa20980edfb0ccd7..addccb333d06cb2d2866e55f6131c6693c14f191 100644 --- a/lib_enc/decision_matrix_enc.c +++ b/lib_enc/decision_matrix_enc.c @@ -38,6 +38,7 @@ #include #include "options.h" #include "prot.h" +#include "prot_fx_enc.h" #include "stat_enc.h" #include "stat_dec.h" #include "rom_com.h" diff --git a/lib_enc/decision_matrix_enc_fx.c b/lib_enc/decision_matrix_enc_fx.c index 922883ffc4b46ffb89a5e85986cf8a4f489b95ae..517a5e2af37f1df1e6894eb54aaf27e84d8da8cb 100644 --- a/lib_enc/decision_matrix_enc_fx.c +++ b/lib_enc/decision_matrix_enc_fx.c @@ -736,7 +736,82 @@ void signalling_enc_fx( * * write channel-aware signalling information into the bitstream *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void signaling_enc_rf_fx( + Encoder_State *st /* i : encoder state structure */ +) +{ + Word16 i; + Word16 sfr; + RF_ENC_HANDLE hRF = st->hRF; + + /* write partial copy into bitstream */ + IF( EQ_16( st->rf_mode, 1 ) ) + { + enc_prm_rf_ivas_fx( st, hRF->rf_indx_frametype[st->rf_fec_offset], st->rf_fec_offset ); + hRF->rf_indx_tbeGainFr[0] = hRF->RF_bwe_gainFr_ind; + move16(); + } + + /* Shift the RF indices such that the partial copy associated with + (n-fec_offset)th frame is included in the bitstream in nth frame. */ + IF( hRF != NULL ) + { + FOR( i = st->rf_fec_offset; i >= 0; i-- ) + { + /* rf frame type */ + hRF->rf_indx_frametype[i + 1] = hRF->rf_indx_frametype[i]; + move16(); + /* rf target bits buffer */ + hRF->rf_targetbits_buff[i + 1] = hRF->rf_targetbits_buff[i]; + move16(); + /* lsf indx */ + hRF->rf_indx_lsf[i + 1][0] = hRF->rf_indx_lsf[i][0]; + hRF->rf_indx_lsf[i + 1][1] = hRF->rf_indx_lsf[i][1]; + hRF->rf_indx_lsf[i + 1][2] = hRF->rf_indx_lsf[i][2]; + move16(); + move16(); + move16(); + /* ES pred energy */ + hRF->rf_indx_EsPred[i + 1] = hRF->rf_indx_EsPred[i]; + move16(); + /* LTF mode, sfr params: pitch, fcb and gain */ + FOR( sfr = 0; sfr < st->nb_subfr; sfr++ ) + { + hRF->rf_indx_ltfMode[i + 1][sfr] = hRF->rf_indx_ltfMode[i][sfr]; + hRF->rf_indx_pitch[i + 1][sfr] = hRF->rf_indx_pitch[i][sfr]; + hRF->rf_indx_fcb[i + 1][sfr] = hRF->rf_indx_fcb[i][sfr]; + hRF->rf_indx_gain[i + 1][sfr] = hRF->rf_indx_gain[i][sfr]; + move16(); + move16(); + move16(); + move16(); + } + + /* shift the nelp indices */ + hRF->rf_indx_nelp_iG1[i + 1] = hRF->rf_indx_nelp_iG1[i]; + hRF->rf_indx_nelp_iG2[i + 1][0] = hRF->rf_indx_nelp_iG2[i][0]; + hRF->rf_indx_nelp_iG2[i + 1][1] = hRF->rf_indx_nelp_iG2[i][1]; + hRF->rf_indx_nelp_fid[i + 1] = hRF->rf_indx_nelp_fid[i]; + move16(); + move16(); + move16(); + move16(); + /* tbe gain Fr shift */ + hRF->rf_indx_tbeGainFr[i + 1] = hRF->rf_indx_tbeGainFr[i]; + hRF->rf_clas[i + 1] = hRF->rf_clas[i]; + hRF->rf_gain_tcx[i + 1] = hRF->rf_gain_tcx[i]; + hRF->rf_tcxltp_param[i + 1] = hRF->rf_tcxltp_param[i]; + move16(); + move16(); + move16(); + move16(); + } + } + return; +} +#endif void signalling_enc_rf( Encoder_State *st /* i : encoder state structure */ ) diff --git a/lib_enc/dtx.c b/lib_enc/dtx.c index 86dd4ad059e2731097f6c3d60e750311f0e3e070..f47d87bd15840a2cfcb256fd320495aa906c0a2b 100644 --- a/lib_enc/dtx.c +++ b/lib_enc/dtx.c @@ -753,7 +753,7 @@ void dtx_hangover_control( * * *-------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED void td_cng_enc_init( TD_CNG_ENC_HANDLE hTdCngEnc, /* i/o: DTX/TD CNG data handle */ const int16_t Opt_DTX_ON, /* i : flag indicating DTX operation */ @@ -806,6 +806,9 @@ void td_cng_enc_init( set_f( hTdCngEnc->exc_mem1, 0.0f, 30 ); set_f( hTdCngEnc->exc_mem2, 0.0f, 30 ); set_f( hTdCngEnc->old_env, 0.0f, NUM_ENV_CNG ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float fixed conversions + set_f( hTdCngEnc->cng_exc2_buf_flt, 0.0f, HO_HIST_SIZE * L_FFT ); +#endif /* SWB CNG/DTX */ hTdCngEnc->last_wb_cng_ener = -6.02f; @@ -820,7 +823,74 @@ void td_cng_enc_init( return; } +#else +void td_cng_enc_init( + TD_CNG_ENC_HANDLE hTdCngEnc, /* i/o: DTX/TD CNG data handle */ + const int16_t Opt_DTX_ON, /* i : flag indicating DTX operation */ + const int16_t max_bwidth /* i : maximum encoded bandwidth */ +) +{ + + hTdCngEnc->cng_seed = RANDOM_INITSEED; + hTdCngEnc->cng_ener_seed = RANDOM_INITSEED; + hTdCngEnc->cng_ener_seed1 = RANDOM_INITSEED; + hTdCngEnc->lp_ener = 0.0f; + hTdCngEnc->old_enr_index = -1; + hTdCngEnc->Enew = 0.0f; + + hTdCngEnc->lp_sp_enr = 0.0f; + hTdCngEnc->last_allow_cn_step = 0; + + hTdCngEnc->CNG_att = 0.0f; + + if ( Opt_DTX_ON ) + { + hTdCngEnc->cng_hist_ptr = -1; + set_f( hTdCngEnc->cng_lsp_hist, 0, DTX_HIST_SIZE * M ); + set_f( hTdCngEnc->cng_ener_hist, 0, DTX_HIST_SIZE ); + hTdCngEnc->ho_hist_ptr = -1; + hTdCngEnc->ho_sid_bw = 0; + set_f( hTdCngEnc->ho_lsp_hist, 0, HO_HIST_SIZE * M ); + set_f( hTdCngEnc->ho_ener_hist, 0, HO_HIST_SIZE ); + set_f( hTdCngEnc->ho_env_hist, 0, HO_HIST_SIZE * NUM_ENV_CNG ); + hTdCngEnc->ho_hist_size = 0; + hTdCngEnc->act_cnt = 0; + } + set_s( hTdCngEnc->ho_16k_lsp, 0, HO_HIST_SIZE ); + hTdCngEnc->act_cnt2 = 0; + hTdCngEnc->num_ho = 0; + + hTdCngEnc->ho_circ_ptr = -1; + set_f( hTdCngEnc->ho_lsp_circ, 0, HO_HIST_SIZE * M ); + set_f( hTdCngEnc->ho_ener_circ, 0, HO_HIST_SIZE ); + set_f( hTdCngEnc->ho_env_circ, 0, HO_HIST_SIZE * NUM_ENV_CNG ); + hTdCngEnc->ho_circ_size = 0; + hTdCngEnc->burst_ho_cnt = 0; + hTdCngEnc->cng_buf_cnt = 0; + + + set_f( hTdCngEnc->lp_env, 0.0f, 20 ); + set_f( hTdCngEnc->cng_res_env, 0.0f, 20 * 8 ); + set_f( hTdCngEnc->exc_mem, 0.0f, 24 ); + set_f( hTdCngEnc->exc_mem1, 0.0f, 30 ); + set_f( hTdCngEnc->exc_mem2, 0.0f, 30 ); + set_f( hTdCngEnc->old_env, 0.0f, NUM_ENV_CNG ); + + /* SWB CNG/DTX */ + hTdCngEnc->last_wb_cng_ener = -6.02f; + hTdCngEnc->last_shb_cng_ener = -6.02f; + hTdCngEnc->mov_wb_cng_ener = -6.02f; + hTdCngEnc->mov_shb_cng_ener = -6.02f; + hTdCngEnc->shb_cng_ini_cnt = 1; + hTdCngEnc->shb_NO_DATA_cnt = 0; + hTdCngEnc->last_SID_bwidth = min( max_bwidth, SWB ); + hTdCngEnc->last_vad = 0; + hTdCngEnc->last_idx_ener = 0; + + return; +} +#endif /*-------------------------------------------------------------------* * dtx_enc_init() diff --git a/lib_enc/dtx_fx.c b/lib_enc/dtx_fx.c index afc6fbe38c21d881a7a4d2600fe2e4c1dc11e412..c94ff10c2a4e80d69b0ecadf70b51f816c6b9891 100644 --- a/lib_enc/dtx_fx.c +++ b/lib_enc/dtx_fx.c @@ -90,8 +90,14 @@ void dtx_ivas_fx( ELSE { /* _DIFF_FLOAT_FIX_ : lp_noise_fx threshold is different between float (15) and fix (5*256) */ + test(); + test(); + test(); last_br_cng_flag = LE_32( st_fx->last_total_brate_cng, ACELP_24k40 ) || LT_16( st_fx->lp_noise_fx, LP_NOISE_LV * 256 ) || ( EQ_16( st_fx->element_mode, IVAS_SCE ) && LE_32( st_fx->last_total_brate_cng, ACELP_32k ) ); + test(); + test(); + test(); last_br_flag = LE_32( st_fx->last_total_brate, ACELP_24k40 ) || LT_16( st_fx->lp_noise_fx, LP_NOISE_LV * 256 ) || ( EQ_16( st_fx->element_mode, IVAS_SCE ) && LE_32( st_fx->last_total_brate, ACELP_32k ) ); br_dtx_flag = 0; move16(); @@ -105,6 +111,8 @@ void dtx_ivas_fx( st_fx->cng_type = FD_CNG; move16(); test(); + test(); + test(); if ( ( EQ_16( st_fx->codec_mode, MODE1 ) || st_fx->Opt_AMR_WB ) && EQ_16( st_fx->element_mode, IVAS_SCE ) && EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) ) { st_fx->cng_type = LP_CNG; @@ -113,6 +121,9 @@ void dtx_ivas_fx( } test(); test(); + test(); + test(); + test(); IF( st_fx->Opt_DTX_ON && vad == 0 && GT_16( st_fx->ini_frame, 2 ) && /* CNG coding starts after 2 frames */ st_fx->fd_cng_reset_flag == 0 && @@ -159,7 +170,7 @@ void dtx_ivas_fx( test(); test(); test(); - if ( st_fx->rf_mode && st_fx->rf_fec_offset > 0 && EQ_32( st_fx->total_brate, ACELP_13k20 ) && NE_16( st_fx->bwidth, NB ) ) + if ( st_fx->rf_mode && st_fx->rf_fec_offset > 0 && EQ_32( st_fx->total_brate, ACELP_13k20 ) && ( st_fx->bwidth != NB ) ) { st_fx->Opt_RF_ON = 1; move16(); @@ -168,7 +179,7 @@ void dtx_ivas_fx( move16(); st_fx->bwidth = st_fx->last_bwidth; move32(); - IF( GT_16( st_fx->element_mode, EVS_MONO ) ) + IF( st_fx->element_mode > EVS_MONO ) { st_fx->codec_mode = MODE1; move16(); @@ -176,6 +187,7 @@ void dtx_ivas_fx( ELSE { st_fx->codec_mode = get_codec_mode( st_fx->total_brate ); + move16(); } } } @@ -183,15 +195,19 @@ void dtx_ivas_fx( /*------------------------------------------------------------------------* * Select SID or FRAME_NO_DATA frame if DTX is enabled *------------------------------------------------------------------------*/ - if ( st_fx->dtx_sce_sba == 0 ) + IF( st_fx->dtx_sce_sba == 0 ) { + test(); + test(); + test(); + test(); #if 0 br_dtx_flag = LE_32( st_fx->total_brate, ACELP_24k40 ) || LT_16( st_fx->lp_noise_fx, LP_NOISE_LV * 256 ) || ( EQ_16( st_fx->element_mode, IVAS_SCE ) && LE_32( st_fx->total_brate, ACELP_32k ) ) || EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) || ( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) && ( LE_32( st_fx->element_brate, IVAS_64k ) || LT_16( st_fx->lp_noise_fx, 15 * 256 ) ) ); #else - br_dtx_flag = ( EQ_16( st_fx->element_mode, EVS_MONO ) && LE_32( st_fx->total_brate, MAX_BRATE_DTX_EVS ) ) || - ( NE_16( st_fx->element_mode, EVS_MONO ) && LE_32( ivas_total_brate, MAX_BRATE_DTX_IVAS ) ) || - LT_16( st_fx->lp_noise_fx, shl( 15, Q8 ) ); + br_dtx_flag = ( ( st_fx->element_mode == EVS_MONO ) && LE_32( st_fx->total_brate, MAX_BRATE_DTX_EVS ) ) || + ( ( st_fx->element_mode != EVS_MONO ) && LE_32( ivas_total_brate, MAX_BRATE_DTX_IVAS ) ) || + LT_16( st_fx->lp_noise_fx, 3840 /*15 in Q8*/ ); #endif } test(); @@ -210,14 +226,18 @@ void dtx_ivas_fx( IF( st_fx->Opt_AMR_WB ) { st_fx->last_total_brate_cng = -1; + move16(); st_fx->last_rf_mode_cng = st_fx->rf_mode; move16(); } ELSE { st_fx->last_total_brate_cng = st_fx->total_brate; + move16(); st_fx->last_bwidth_cng = st_fx->bwidth; + move16(); st_fx->last_codec_mode_cng = st_fx->codec_mode; + move16(); } IF( hDtxEnc->cnt_SID == 0 ) @@ -243,18 +263,26 @@ void dtx_ivas_fx( test(); test(); - IF( EQ_32( st_fx->core_brate, FRAME_NO_DATA ) && NE_16( st_fx->last_core, ACELP_CORE ) && !st_fx->Opt_AMR_WB ) + if ( ( st_fx->core_brate == FRAME_NO_DATA ) && ( st_fx->last_core != ACELP_CORE ) && !st_fx->Opt_AMR_WB ) { /* force SID frame when switching from HQ core or AMR-WB IO mode into inactive frame in ACELP core when DTX is on */ st_fx->core_brate = SID_2k40; move32(); } // PMT("dtx_sce_sba code is missing") - IF( ( NE_16( st_fx->last_core, ACELP_CORE ) || EQ_16( st_fx->cng_type, FD_CNG ) ) && EQ_16( st_fx->dtx_sce_sba, 1 ) ) + test(); + test(); + IF( ( ( st_fx->last_core != ACELP_CORE ) || EQ_16( st_fx->cng_type, FD_CNG ) ) && EQ_16( st_fx->dtx_sce_sba, 1 ) ) { st_fx->cng_type = FD_CNG; move16(); - if ( EQ_16( st_fx->element_mode, EVS_MONO ) && ( EQ_32( st_fx->total_brate, ACELP_9k60 ) || EQ_32( st_fx->total_brate, ACELP_16k40 ) || EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_48k ) || EQ_32( st_fx->total_brate, HQ_96k ) || EQ_32( st_fx->total_brate, HQ_128k ) ) ) + test(); + test(); + test(); + test(); + test(); + test(); + if ( ( st_fx->element_mode == EVS_MONO ) && ( EQ_32( st_fx->total_brate, ACELP_9k60 ) || EQ_32( st_fx->total_brate, ACELP_16k40 ) || EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_48k ) || EQ_32( st_fx->total_brate, HQ_96k ) || EQ_32( st_fx->total_brate, HQ_128k ) ) ) { st_fx->codec_mode = MODE2; move16(); @@ -266,11 +294,12 @@ void dtx_ivas_fx( test(); test(); test(); - IF( ( EQ_16( st_fx->cng_type, FD_CNG ) && ( LE_32( st_fx->total_brate, ACELP_24k40 ) || ( NE_16( st_fx->element_mode, EVS_MONO ) && LE_32( st_fx->total_brate, ACELP_32k ) ) ) ) || ( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) ) ) /* at highest bitrates, use exclusively LP_CNG */ + IF( ( EQ_16( st_fx->cng_type, FD_CNG ) && ( LE_32( st_fx->total_brate, ACELP_24k40 ) || ( ( st_fx->element_mode != EVS_MONO ) && LE_32( st_fx->total_brate, ACELP_32k ) ) ) ) || ( EQ_16( st_fx->element_mode, IVAS_CPE_MDCT ) ) ) /* at highest bitrates, use exclusively LP_CNG */ { test(); test(); - IF( EQ_16( st_fx->element_mode, EVS_MONO ) && ( EQ_32( st_fx->total_brate, ACELP_9k60 ) || EQ_32( st_fx->total_brate, ACELP_16k40 ) || EQ_32( st_fx->total_brate, ACELP_24k40 ) ) ) + test(); + if ( ( st_fx->element_mode == EVS_MONO ) && ( EQ_32( st_fx->total_brate, ACELP_9k60 ) || EQ_32( st_fx->total_brate, ACELP_16k40 ) || EQ_32( st_fx->total_brate, ACELP_24k40 ) ) ) { st_fx->codec_mode = MODE2; move16(); @@ -280,7 +309,7 @@ void dtx_ivas_fx( { st_fx->cng_type = LP_CNG; move16(); - IF( st_fx->codec_mode == MODE2 ) + if ( EQ_16( st_fx->codec_mode, MODE2 ) ) { hTdCngEnc->lp_cng_mode2 = 1; move16(); @@ -290,6 +319,7 @@ void dtx_ivas_fx( } } /* reset the bitstream (IVAS format signalling was already written) */ + test(); IF( NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) && st_fx->hBstr != NULL ) { @@ -303,7 +333,7 @@ void dtx_ivas_fx( /* NB core bit rate can be "-1" at startup , so one can not use core_brate_fx <=2400 */ test(); test(); - IF( ( NE_32( st_fx->core_brate, SID_2k40 ) ) && ( NE_32( st_fx->core_brate, SID_1k75 ) ) && ( NE_32( st_fx->core_brate, FRAME_NO_DATA ) ) ) + IF( ( NE_32( st_fx->core_brate, SID_2k40 ) ) && ( NE_32( st_fx->core_brate, SID_1k75 ) ) && ( st_fx->core_brate != FRAME_NO_DATA ) ) { IF( hDtxEnc != NULL ) { @@ -323,7 +353,7 @@ void dtx_ivas_fx( move16(); /* first SID update is only 3 frames after the active speech end */ } - IF( LT_16( hDtxEnc->interval_SID, hDtxEnc->max_SID ) ) + if ( LT_16( hDtxEnc->interval_SID, hDtxEnc->max_SID ) ) { hDtxEnc->max_SID = hDtxEnc->interval_SID; move16(); /* change SID update rate */ @@ -333,6 +363,7 @@ void dtx_ivas_fx( move16(); /* reset the counter of CNG frames for averaging */ } test(); + test(); IF( GE_16( st_fx->active_fr_cnt_fx, CNG_TYPE_HO ) && st_fx->Opt_AMR_WB == 0 && NE_16( st_fx->element_mode, IVAS_CPE_MDCT ) ) { IF( EQ_16( st_fx->element_mode, IVAS_SCE ) ) @@ -342,24 +373,32 @@ void dtx_ivas_fx( test(); IF( st_fx->Opt_DTX_ON && EQ_16( st_fx->dtx_sce_sba, 1 ) ) { - lp_thresh = L_shl( 5, Q27 ); - fd_thresh = L_shl( 2, Q27 ); + lp_thresh = 327680; // 5 in Q16 + move32(); + fd_thresh = 131072; // 2 in Q16 + move32(); } ELSE - { - lp_thresh = L_shl( 10, Q27 ); - fd_thresh = L_shl( 5, Q27 ); + lp_thresh = 655360; // 10 in Q16 + move32(); + fd_thresh = 327680; // 5 in Q16 + move32(); } /*More conservative selection of LP-CNG for SCE*/ - if ( st_fx->cng_type == LP_CNG && ( st_fx->bckr_tilt_lt > lp_thresh ) ) + test(); + test(); + test(); + IF( st_fx->cng_type == LP_CNG && ( GT_32( st_fx->bckr_tilt_lt, lp_thresh ) ) ) { st_fx->cng_type = FD_CNG; + move16(); } - else if ( st_fx->cng_type == FD_CNG && ( st_fx->bckr_tilt_lt < fd_thresh ) && ( st_fx->lp_noise > L_shl( 2, Q27 ) ) ) + ELSE IF( EQ_16( st_fx->cng_type, FD_CNG ) && ( LT_32( st_fx->bckr_tilt_lt, fd_thresh ) ) && ( GT_16( st_fx->lp_noise_fx, 512 /* 2 in Q8 */ ) ) ) { st_fx->cng_type = LP_CNG; + move16(); } } ELSE @@ -372,18 +411,19 @@ void dtx_ivas_fx( test(); test(); test(); - IF( EQ_16( st_fx->cng_type, LP_CNG ) && ( ( EQ_16( st_fx->input_bwidth, NB ) && GT_32( st_fx->bckr_tilt_lt, 589824l /*9.f Q16*/ ) ) || ( GT_16( st_fx->input_bwidth, NB ) && GT_32( st_fx->bckr_tilt_lt, 2949120l /*45.f Q16*/ ) ) ) ) + IF( ( st_fx->cng_type == LP_CNG ) && ( ( ( st_fx->input_bwidth == NB ) && GT_32( st_fx->bckr_tilt_lt, 589824 /*9.f Q16*/ ) ) || ( ( st_fx->input_bwidth > NB ) && GT_32( st_fx->bckr_tilt_lt, 2949120l /*45.f Q16*/ ) ) ) ) { st_fx->cng_type = FD_CNG; move16(); } - ELSE IF( EQ_16( st_fx->cng_type, FD_CNG ) && ( ( EQ_16( st_fx->input_bwidth, NB ) && LT_32( st_fx->bckr_tilt_lt, 131072l /*2.f Q16*/ ) ) || ( GT_16( st_fx->input_bwidth, NB ) && LT_32( st_fx->bckr_tilt_lt, 655360l /*10.f Q16*/ ) ) ) ) + ELSE IF( EQ_16( st_fx->cng_type, FD_CNG ) && ( ( ( st_fx->input_bwidth == NB ) && LT_32( st_fx->bckr_tilt_lt, 131072l /*2.f Q16*/ ) ) || ( ( st_fx->input_bwidth > NB ) && LT_32( st_fx->bckr_tilt_lt, 655360l /*10.f Q16*/ ) ) ) ) { st_fx->cng_type = LP_CNG; move16(); } } st_fx->last_total_brate_cng = -1; + move16(); } ELSE IF( st_fx->Opt_AMR_WB ) { @@ -391,7 +431,9 @@ void dtx_ivas_fx( move16(); } st_fx->active_fr_cnt_fx = add( st_fx->active_fr_cnt_fx, 1 ); + move16(); st_fx->active_fr_cnt_fx = s_min( st_fx->active_fr_cnt_fx, 200 ); + move16(); } /*------------------------------------------------------------------------* @@ -426,6 +468,7 @@ void dtx_ivas_fx( Word16 guard_bits = find_guarded_bits_fx( L_FRAME ); // Word16 Q_frame_ener = 2 * Q_speech; hDtxEnc->frame_ener_fx = sum2_f_16_gb_fx( speech, L_FRAME, guard_bits ); // 2*Q_speech-guard_bits + move32(); /* Active speech (voiced) */ @@ -443,10 +486,13 @@ void dtx_ivas_fx( L_tmp = L_sub( hDtxEnc->lt_ener_voiced_fx, hDtxEnc->frame_ener_fx ); L_tmp = Mult_32_16( L_tmp, alpha ); hDtxEnc->lt_ener_voiced_fx = L_add( L_tmp, hDtxEnc->frame_ener_fx ); /*2*Q_speech-guard_bits */ + move32(); hDtxEnc->VarDTX_cnt_voiced = add( hDtxEnc->VarDTX_cnt_voiced, 1 ); + move16(); hDtxEnc->VarDTX_cnt_voiced = s_min( hDtxEnc->VarDTX_cnt_voiced, MIN_CNT ); + move16(); } /* Background noise */ ELSE IF( !st_fx->Opt_AMR_WB ) @@ -466,8 +512,10 @@ void dtx_ivas_fx( move32(); /*2*Q_speech-guard_bits */ hDtxEnc->VarDTX_cnt_noise = add( hDtxEnc->VarDTX_cnt_noise, 1 ); + move16(); hDtxEnc->VarDTX_cnt_noise = s_min( hDtxEnc->VarDTX_cnt_noise, MIN_CNT ); + move16(); } } } @@ -478,7 +526,7 @@ void dtx_ivas_fx( /* Update encoded bandwidth */ test(); test(); - IF( st_fx->Opt_DTX_ON && ( st_fx->core_brate == SID_2k40 || st_fx->core_brate == FRAME_NO_DATA ) ) + IF( st_fx->Opt_DTX_ON && ( EQ_32( st_fx->core_brate, SID_2k40 ) || ( st_fx->core_brate == FRAME_NO_DATA ) ) ) { st_fx->bwidth = st_fx->last_bwidth; @@ -492,7 +540,7 @@ void dtx_ivas_fx( test(); test(); - IF( st_fx->Opt_RF_ON && ( EQ_32( st_fx->total_brate, ACELP_13k20 ) ) && ( EQ_16( st_fx->bwidth, NB ) ) ) + IF( st_fx->Opt_RF_ON && ( EQ_32( st_fx->total_brate, ACELP_13k20 ) ) && ( ( st_fx->bwidth == NB ) ) ) { st_fx->codec_mode = MODE1; move16(); @@ -503,7 +551,6 @@ void dtx_ivas_fx( move16(); } - test(); test(); IF( st_fx->Opt_RF_ON && NE_32( st_fx->total_brate, ACELP_13k20 ) ) { @@ -532,7 +579,7 @@ void dtx_ivas_fx( BREAK; } } - if ( n == FRAME_SIZE_NB ) + IF( EQ_16( n, FRAME_SIZE_NB ) ) { assert( !"Bitrate not supported: not part of EVS" ); } @@ -540,8 +587,10 @@ void dtx_ivas_fx( if ( EQ_16( st_fx->rf_mode, 1 ) ) { tmpbandwidthMin = WB; + move16(); } st_fx->bwidth = s_max( s_min( st_fx->bwidth, FrameSizeConfig[n].bandwidth_max ), tmpbandwidthMin ); + move16(); } } diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c index 5e0a1d004123271c84f988ba0d03e03449a1cc43..2b5acec573399fd65c5443424d0b4ef510c8c5c6 100644 --- a/lib_enc/enc_acelp_tcx_main.c +++ b/lib_enc/enc_acelp_tcx_main.c @@ -40,6 +40,7 @@ #include "rom_com.h" #include "wmc_auto.h" +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * enc_acelp_tcx_main() * @@ -129,3 +130,4 @@ void enc_acelp_tcx_main( pop_wmops(); return; } +#endif diff --git a/lib_enc/enc_nelp_fx.c b/lib_enc/enc_nelp_fx.c index 4be45c7e9d7ca2dce71cc0f1ea4620d6df486c69..cbc8c02ab4d005ccb402ffa951204ba12cdf7077 100644 --- a/lib_enc/enc_nelp_fx.c +++ b/lib_enc/enc_nelp_fx.c @@ -174,3 +174,149 @@ void encod_nelp_fx( return; } + +#ifdef IVAS_FLOAT_FIXED +void encod_nelp_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 *speech_fx, + /* i : input speech */ /* Q_new-1 */ + const Word16 Aw_fx[], + /* i : weighted A(z) unquantized for subframes */ /*exp(norm_s(Aw_fx[0])+1)*/ + const Word16 Aq_fx[], + /* i : 12k8 Lp coefficient */ /*exp(norm_s(Aw_fx[0])+1)*/ + Word16 *res_fx, + /* o : residual signal */ /* Q_new */ + Word16 *synth_fx, + /* o : core synthesis */ /* Q_new */ + Word16 *tmp_noise_fx, + /* o : long-term noise energy */ /* Q8 */ + Word16 *exc_fx, + /* i/o: current non-enhanced excitation */ /* Q_new */ + Word16 *exc2_fx, + /* i/o: current enhanced excitation */ /* Q_new */ + Word16 *pitch_buf_fx, + /* o : floating pitch values for each subframe */ /* Q6 */ + Word16 *voice_factors_fx, + /* o : voicing factors */ /* Q15 */ + Word16 *bwe_exc_fx, + /* o : excitation for SWB TBE */ /* Q_new */ + Word16 Q_new, + Word16 shift ) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 h1_fx[L_SUBFR]; /* Impulse response vector */ + Word16 exc_nelp_fx[L_FRAME]; + + Word16 i_subfr, j; + + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */ + Word16 saved_Q_new = Q_new; + move16(); + + Word16 reduce_gains = 0; + move16(); + LPD_state_HANDLE hLPDmem = st_fx->hLPDmem; + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + + test(); + IF( EQ_16( st_fx->bwidth, NB ) && GE_32( st_fx->input_Fs, 16000 ) ) + { + IF( hSC_VBR->last_nelp_mode == 0 ) + { + set16_fx( hSC_VBR->nelp_lp_fit_mem, 0, NELP_LP_ORDER * 2 ); + } + Scale_sig( hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER * 2, sub( Q_new, st_fx->prev_Q_new ) ); + + pz_filter_sp_fx( num_nelp_lp_fx, den_nelp_lp_fx, res_fx, res_fx, hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER, NELP_LP_ORDER, L_FRAME, 3 ); /*16-Q of filter coeff*/ + } + + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + + + FOR( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + /*----------------------------------------------------------------* + * - Bandwidth expansion of A(z) filter coefficients + * - Find the excitation search target "xn" and innovation + * target in residual domain "cn" + * - Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + Copy( &res_fx[i_subfr], &exc_fx[i_subfr], L_SUBFR ); + + find_targets_ivas_fx( speech_fx, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL, h1_fx ); + + /* scale xn[] and h1[] to avoid overflow in dot_product12() */ + Scale_sig( xn_fx, L_SUBFR, shift ); /* scaling of xn[] to limit dynamic at 12 bits */ + + IF( i_subfr == 0 ) + { + test(); + IF( EQ_16( hSC_VBR->Local_VAD, 1 ) && EQ_16( st_fx->bwidth, NB ) ) + { + reduce_gains = 1; + move16(); + } + + nelp_encoder_ivas_fx( st_fx, res_fx, exc_nelp_fx, &Q_new, reduce_gains ); + + Scale_sig( exc_nelp_fx, L_FRAME, ( saved_Q_new - Q_new ) ); + } + + + *tmp_noise_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + Syn_filt_s( 1, p_Aq_fx, M, &exc_nelp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 ); + + p_Aw_fx += ( M + 1 ); + p_Aq_fx += ( M + 1 ); + *pitch_buf_fx = L_SUBFR_Q6; + move16(); + + pitch_buf_fx++; + } + + Copy( exc_nelp_fx, exc_fx, L_FRAME ); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + +#ifdef BASOP_NOGLOB + hLPDmem->mem_w0 = sub_sat( shr_sat( xn_fx[L_SUBFR - 1], shift ), shr( exc_fx[L_FRAME - 1], 1 ) ); +#else + hLPDmem->mem_w0 = sub( shr( xn_fx[L_SUBFR - 1], shift ), shr( exc_fx[L_FRAME - 1], 1 ) ); +#endif + move16(); /*Q_new-1 */ + hLPDmem->tilt_code = 0; + move16(); /* purely unvoiced */ + hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code; + move16(); + + Copy( exc_fx, exc2_fx, L_FRAME ); + + hSC_VBR->prev_ppp_gain_pit_fx = 0; + move16(); + + hLPDmem->dm_fx.prev_state = 0; + move16(); + hLPDmem->dm_fx.prev_gain_pit[0] = hSC_VBR->prev_ppp_gain_pit_fx; + move16(); + + FOR( j = 1; j < 5; j++ ) + { + hLPDmem->dm_fx.prev_gain_pit[j] = hLPDmem->dm_fx.prev_gain_pit[j - 1]; + move16(); + } + interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME ); + set16_fx( voice_factors_fx, 0, NB_SUBFR16k ); + + return; +} +#endif diff --git a/lib_enc/enc_prm_fx.c b/lib_enc/enc_prm_fx.c index 92386c2259b9ddf41b68372bdcbb1be81d62fceb..52d7dc8ddcc4d918d57a637a10bd90373c5c9271 100644 --- a/lib_enc/enc_prm_fx.c +++ b/lib_enc/enc_prm_fx.c @@ -101,7 +101,178 @@ static void enc_prm_hm_ivas_fx( * * * encode RF parameters for ACELP and TCX partial copy * *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + +void enc_prm_rf_ivas_fx( Encoder_State *st, + const Word16 rf_frame_type, + const Word16 fec_offset ) +{ + Word16 sfr, nb_subfr, n, index; + Word16 ltp_mode, ltf_mode, gains_mode; + RF_ENC_HANDLE hRF = st->hRF; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + BSTR_ENC_HANDLE hBstr = st->hBstr; + + nb_subfr = st->nb_subfr; + move16(); + /* partial copy bitstream writing */ + test(); + IF( GE_16( rf_frame_type, RF_TCXFD ) && LE_16( rf_frame_type, RF_TCXTD2 ) ) + { + /* TCX frames partial copy write */ + + /* LSF indices */ + IF( EQ_16( rf_frame_type, RF_TCXFD ) ) + { + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], lsf_numbits[0] ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], lsf_numbits[1] ); /* VQ 2 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][2], lsf_numbits[2] ); /* VQ 3 */ + } + + /* classification */ + test(); + IF( EQ_16( hRF->rf_clas[fec_offset], UNVOICED_CLAS ) ) + { + index = 0; + move16(); + } + ELSE IF( ( EQ_16( hRF->rf_clas[fec_offset], VOICED_TRANSITION ) ) || ( EQ_16( hRF->rf_clas[fec_offset], UNVOICED_TRANSITION ) ) ) + { + index = 1; + move16(); + } + ELSE IF( EQ_16( hRF->rf_clas[fec_offset], VOICED_CLAS ) ) + { + index = 2; + move16(); + } + ELSE + { + index = 3; + move16(); + } + push_next_indice_fx( hBstr, index, 2 ); + + IF( EQ_16( rf_frame_type, RF_TCXFD ) ) + { + /* TCX global gain = 7 bits */ + push_next_indice( hBstr, hRF->rf_gain_tcx[fec_offset], 7 ); + /*window info + 1 bit for long overlap + 2 if minimum or half overlap*/ + } + ELSE + { + /*gains adapt + gains inov*/ + + /*LPC on full rate -> excitation */ + /* pitch and gain */ + /* LTP data */ + test(); + test(); + IF( ( EQ_16( rf_frame_type, RF_TCXTD1 ) || EQ_16( rf_frame_type, RF_TCXTD2 ) ) && hTcxEnc->tcxltp != 0 ) + { + push_next_indice( hBstr, hRF->rf_tcxltp_param[fec_offset], 9 ); + } + } + } + ELSE IF( EQ_16( rf_frame_type, 7 ) ) /* NELP bitstream writing */ + { + /* LSF indices */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8 ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8 ); /* VQ 2 */ + + /* NELP gain indices */ + push_next_indice( hBstr, hRF->rf_indx_nelp_iG1[fec_offset], 5 ); + push_next_indice( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][0], 6 ); + push_next_indice( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][1], 6 ); + + /* NELP filter selection index */ + push_next_indice( hBstr, hRF->rf_indx_nelp_fid[fec_offset], 2 ); + + /* tbe gainFr */ + push_next_indice( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 5 ); + } + ELSE IF( GE_16( rf_frame_type, 4 ) ) /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6 */ + { + /* LSF indices */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8 ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8 ); /* VQ 2 */ + + /* ES pred */ + push_next_indice( hBstr, hRF->rf_indx_EsPred[fec_offset], 3 ); + + ltp_mode = ACELP_LTP_MODE[1][1][rf_frame_type]; + ltf_mode = ACELP_LTF_MODE[1][1][rf_frame_type]; + gains_mode = ACELP_GAINS_MODE[1][1][rf_frame_type]; + move16(); + move16(); + move16(); + /* Subframe parameters */ + FOR( sfr = 0; sfr < nb_subfr; sfr++ ) + { + /* Pitch lag (5, or 8 bits) */ + n = ACELP_LTP_BITS_SFR[ltp_mode][sfr]; + move16(); + IF( n != 0 ) + { + push_next_indice( hBstr, hRF->rf_indx_pitch[fec_offset][sfr], n ); + } + + /* Adaptive codebook filtering (1 bit) */ + IF( EQ_16( ltf_mode, 2 ) ) + { + push_next_indice( hBstr, hRF->rf_indx_ltfMode[fec_offset][sfr], 1 ); + } + + /*Innovative codebook*/ + test(); + test(); + test(); + IF( ( EQ_16( rf_frame_type, RF_NOPRED ) ) || + ( EQ_16( rf_frame_type, RF_GENPRED ) && + ( sfr == 0 || EQ_16( sfr, 2 ) ) ) ) + { + push_next_indice( hBstr, hRF->rf_indx_fcb[fec_offset][sfr], 7 ); + } + + /* Gains (5b, 6b or 7b / subfr) */ + test(); + IF( sfr == 0 || EQ_16( sfr, 2 ) ) + { + n = ACELP_GAINS_BITS[gains_mode]; + move16(); + push_next_indice( hBstr, hRF->rf_indx_gain[fec_offset][sfr], n ); + } + } + /* tbe gainFr */ + push_next_indice( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 2 ); + } + + /***************/ + /*IMPORTANT: The last three bits are always the rf_frame_type in the bitstream (for both acelp and tcx partial copy); + the rf_frame_type indicates the length of the partial copy payload at the decoder. + The 2 bits before the rf_frame_type contains the fec_offset */ + + /***************/ + /* write FEC offset just before the rf_frame_type */ + test(); + test(); + IF( EQ_16( fec_offset, 2 ) ) + { + push_next_indice( hBstr, 0, 2 ); + } + ELSE IF( EQ_16( fec_offset, 3 ) || EQ_16( fec_offset, 5 ) || EQ_16( fec_offset, 7 ) ) + { + push_next_indice( hBstr, shr( sub( fec_offset, 1 ), 1 ), 2 ); + } + + /* write RF frame type last in the bitstream */ + push_next_indice( hBstr, rf_frame_type, 3 ); +} +#endif void enc_prm_rf_fx( Encoder_State *st, const Word16 rf_frame_type, const Word16 fec_offset ) diff --git a/lib_enc/evs_enc.c b/lib_enc/evs_enc.c index dadacb4089fc4000dff305422fee076a66503ac2..8c8557c0079dac0e70742f73cb243c6e0079060f 100644 --- a/lib_enc/evs_enc.c +++ b/lib_enc/evs_enc.c @@ -42,8 +42,12 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "prot_fx.h" +#include "prot_fx_enc.h" #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * Local function prototypes *-------------------------------------------------------------------*/ @@ -54,7 +58,6 @@ static void writeFrameHeader( Encoder_State *st ); static void initFrameHeader( Encoder_State *st ); - /*-------------------------------------------------------------------* * evs_enc() * @@ -236,7 +239,7 @@ ivas_error evs_enc( if ( st->core == ACELP_CORE ) { - if ( ( error = acelp_core_enc( st, inp, ener, A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, bwe_exc_extended, voice_factors, old_syn_12k8_16k, pitch_buf, &unbits, NULL, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = acelp_core_enc( st, inp, /*ener,*/ A, Aw, epsP, lsp_new, lsp_mid, vad_hover_flag, attack_flag, bwe_exc_extended, voice_factors, old_syn_12k8_16k, pitch_buf, &unbits, NULL, NULL ) ) != IVAS_ERR_OK ) { return error; } @@ -248,7 +251,180 @@ ivas_error evs_enc( if ( st->core == HQ_CORE ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + PWord16 *p; + Word16 q = 0; + Word16 overlap, tmp; + Word16 left_overlap, right_overlap; + IF( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) + { + left_overlap = st->hTcxCfg->tcx_mdct_window_lengthFB; + right_overlap = st->hTcxCfg->tcx_mdct_window_delayFB; + Word16 L_frame1 = 640; + + p = st->hTcxCfg->tcx_mdct_window_minimumFB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + + Word16 q1 = Q_factor_arr( st->hTcxCfg->tcx_mdct_window_minimumFB_flt, tmp ); + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimumFB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimumFB_flt[i + tmp], q1 ); + } + + p = st->hTcxCfg->tcx_mdct_window_transFB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_transFB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_transFB_flt[i + tmp], q1 ); + } + + p = st->hTcxCfg->tcx_aldo_window_2_FB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_delayFB, 1 ); + + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_FB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_FB_flt[i + tmp], q1 ); + } + + tmp = st->hTcxCfg->tcx_mdct_window_min_length / 2; + p = st->hTcxCfg->tcx_mdct_window_minimum; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimum_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimum_flt[i + tmp], q1 ); + } + + + Word16 l1 = ( shr( left_overlap, 1 ) * 2 ) + sub( L_frame1, shr( add( left_overlap, right_overlap ), 1 ) ) + ( shr( right_overlap, 1 ) * 2 ) - shr( left_overlap, 1 ) + st->hTcxCfg->tcx_offsetFB; + q = Q_factor_arr( st->hTcxEnc->speech_TCX_flt, l1 ) - 1; + st->hTcxEnc->q_speech_TCX = q; + + Word16 offset, overlap1; + offset = negate( shr( st->hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); + overlap1 = st->hTcxCfg->tcx_mdct_window_trans_lengthFB; + + floatToFixed_arr( st->hTcxEnc->speech_TCX_flt - overlap1 / 2 + offset, st->hTcxEnc->speech_TCX - overlap1 / 2 + offset, q, l1 ); + floatToFixed_arr( st->hTcxEnc->speech_TCX_flt - overlap1 / 2 + offset, st->hTcxEnc->speech_TCX - overlap1 / 2 + offset, q, 2 * L_FRAME48k + 960 ); + + q1 = 15; + tmp = st->hTcxCfg->tcx_mdct_window_half_length / 2; + p = st->hTcxCfg->tcx_mdct_window_half; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_half_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_half_flt[i + tmp], q1 ); + } + + tmp = st->hTcxCfg->tcx_mdct_window_min_length / 2; + p = st->hTcxCfg->tcx_mdct_window_trans; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_trans_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_trans_flt[i + tmp], q1 ); + } + + overlap = st->hTcxCfg->tcx_mdct_window_length; + tmp = overlap / 2; + p = st->hTcxCfg->tcx_aldo_window_2; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_flt[i + tmp], q1 ); + } + + tmp = overlap / 2; + p = st->hTcxCfg->tcx_aldo_window_1_trunc; + FOR( i = -NS2SA( st->sr_core, N_ZERO_MDCT_NS ); i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_1_trunc_flt[i], q1 ); + } + FOR( i = -NS2SA( st->sr_core, N_ZERO_MDCT_NS ); i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_1_trunc_flt[i + tmp], q1 ); + } + + FOR( i = 0; i < L_FRAME32k / 2 + 64; i++ ) + { + st->hTcxEnc->Txnq[i] = float_to_fix16( st->hTcxEnc->Txnq_flt[i], 0 ); + } + } + ELSE + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + st->hTcxEnc->old_out_fx[i] = float_to_fix16( st->hTcxEnc->old_out[i], 0 ); + } + } + + IF( NE_16( hq_core_type, LOW_RATE_HQ_CORE ) ) + { + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + Word16 temp_e; + + f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); + st->hHQ_core->crest_lp_q = sub( Q31, temp_e ); + f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); + st->hHQ_core->crest_mod_lp_q = sub( Q31, temp_e ); + } + } + + floatToFixed_arr( st->input - delay, st->input_fx - delay, 0, 960 ); +#endif + hq_core_enc_ivas_fx( st, st->input_fx - delay, input_frame, hq_core_type, Voicing_flag, vad_hover_flag ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( EQ_16( hq_core_type, LOW_RATE_HQ_CORE ) ) + { + fixedToFloat_arrL( st->hHQ_core->last_ni_gain_fx, st->hHQ_core->last_ni_gain, Q17, BANDS_MAX ); + fixedToFloat_arr( st->hHQ_core->last_env_fx, st->hHQ_core->last_env, Q1, BANDS_MAX ); + } + ELSE + { + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + + st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); + st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); + } + } + IF( st->element_mode > EVS_MONO ) + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + st->hLPDmem->old_exc_flt[i] = fix16_to_float( st->hLPDmem->old_exc[i], 0 ); + } + } +#endif +#else hq_core_enc( st, st->input - delay, input_frame, hq_core_type, Voicing_flag, vad_hover_flag ); +#endif } /*---------------------------------------------------------------------* @@ -642,3 +818,4 @@ static void configure_core_coder( return; } +#endif diff --git a/lib_enc/evs_enc_fx.c b/lib_enc/evs_enc_fx.c index ae2dd4aedc7a72fddbbce6ef725a300137d4e8d2..7a86e177ba50a02bf7de22c324f4f7b2960a7309 100644 --- a/lib_enc/evs_enc_fx.c +++ b/lib_enc/evs_enc_fx.c @@ -92,6 +92,7 @@ ivas_error evs_enc_fx( error = IVAS_ERR_OK; + push_wmops( "evs_enc_fx" ); Q_shb_spch = 0; move16(); /* to avoid compiler warnings */ @@ -612,6 +613,8 @@ ivas_error evs_enc_fx( dbgwrite( &st->vad_flag, sizeof( short ), 1, input_frame, "res/vad_flag" ); #endif + pop_wmops(); + return error; } diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c index 47dadb33d00528d4aa08e40e48c40cc6e8eb007c..e7688dfbaef1ece0033ed624d3d4ff2a3d31f678 100644 --- a/lib_enc/ext_sig_ana.c +++ b/lib_enc/ext_sig_ana.c @@ -52,6 +52,7 @@ * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void core_signal_analysis_high_bitrate( const float *new_samples, const int16_t T_op[3], /* i : open-loop pitch values for quantiz. */ @@ -96,6 +97,17 @@ void core_signal_analysis_high_bitrate( int16_t alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1; float alw_voicing[2], alw_voicing_wc = -1; int16_t disable_ltp = 0; +#ifdef IVAS_FLOAT_FIXED + Word16 q_fac; + Word16 buf_speech_enc_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 buf_wspeech_enc_fx[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320]; + Word16 buf_speech_ltp_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 *speech_ltp_fx = NULL; + Word16 *wspeech_fx = NULL; + Word16 *speech_fx = NULL; + q_fac = 0; + move16(); +#endif if ( last_element_mode != st->element_mode ) { @@ -117,7 +129,65 @@ void core_signal_analysis_high_bitrate( /*--------------------------------------------------------------* * TCX-LTP *---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->element_mode == IVAS_CPE_DFT ) + { + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + floatToFixed_arr( st->buf_wspeech_enc_flt, buf_wspeech_enc_fx, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + if ( st->element_mode > EVS_MONO ) + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + L_SUBFR; + } + else + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + idiv1616( st->L_frame, st->nb_subfr ); + } + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + floatToFixed_arr( st->buf_speech_enc_flt, buf_speech_enc_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_fx = buf_speech_enc_fx + +st->encoderPastSamples_enc; + + floatToFixed_arr( st->hTcxEnc->buf_speech_ltp_flt, buf_speech_ltp_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_ltp_fx = buf_speech_ltp_fx + st->encoderPastSamples_enc; + } +#endif + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, wspeech_fx, NULL, wspeech_fx, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + ELSE IF( st->element_mode != IVAS_CPE_MDCT ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, speech_fx + st->encoderLookahead_enc, speech_ltp_fx + st->encoderLookahead_enc, speech_fx + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->element_mode == IVAS_CPE_DFT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( buf_wspeech_enc_fx, st->buf_wspeech_enc_flt, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( buf_speech_ltp_fx, st->hTcxEnc->buf_speech_ltp_flt, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } +#endif +#else if ( st->element_mode == IVAS_CPE_DFT ) { tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->wspeech_enc_flt, NULL, st->wspeech_enc_flt, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); @@ -126,6 +196,7 @@ void core_signal_analysis_high_bitrate( { tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->speech_enc_flt + st->encoderLookahead_enc, hTcxEnc->speech_ltp_flt + st->encoderLookahead_enc, st->speech_enc_flt + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); } +#endif if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) { @@ -476,6 +547,528 @@ void core_signal_analysis_high_bitrate( a2lsp_stab( A, lsp[nSubframes - 1 - frameno], st->lspold_enc ); } + if ( st->igf ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( hTcxEnc->spectrum[frameno], hTcxEnc->L_frameTCX / nSubframes ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->infoStopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( hTcxEnc->spectrum[frameno], hTcxEnc->spectrum_fx[frameno], q_spectrum, hTcxEnc->L_frameTCX / nSubframes ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, st->hIGFEnc->infoStopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + Word32 powerSpec_fx[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + Word16 q_powerSpec; + q_powerSpec = L_get_q_buf1( powerSpec, L_subframe ); + floatToFixed_arrL32( powerSpec, powerSpec_fx, q_powerSpec, L_subframe ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); + } + } +#endif + ProcessIGF_ivas_fx( st, hTcxEnc->spectrum_fx[frameno], hTcxEnc->spectrum_fx[frameno], &q_spectrum, powerSpec_fx, &q_powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( hTcxEnc->spectrum_fx[frameno], hTcxEnc->spectrum[frameno], q_spectrum, hTcxEnc->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( powerSpec_fx, powerSpec, q_powerSpec, L_subframe ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); + me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->infoStopLine - IGF_START_MN ); + } + + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } +#endif +#else + ProcessIGF( st, hTcxEnc->spectrum[frameno], hTcxEnc->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); +#endif + } + } + } + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* Copy memory */ + mvr2r( lsp_new, st->lspold_enc, M ); + } + + return; +} +#else +void core_signal_analysis_high_bitrate( + const float *new_samples, + const int16_t T_op[3], /* i : open-loop pitch values for quantiz. */ + float lsp_new[], + float lsp_mid[], + Encoder_State *st, + float *mdst_spectrum[2], + int16_t pTnsSize[], + int16_t pTnsBits[], + int16_t param_core[], + int16_t *ltpBits, + float *windowed_samples, /* i/o: backup of windowed time signal */ + const int16_t L_frame, + const int16_t L_frameTCX, + const int16_t last_element_mode, + const int16_t vad_hover_flag /* i : VAD hangover flag */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + const int16_t last_overlap = st->hTcxCfg->tcx_last_overlap_mode; + const int16_t curr_overlap = st->hTcxCfg->tcx_curr_overlap_mode; + const int16_t minWindowLen = st->hTcxCfg->tcx_mdct_window_min_lengthFB - 1; + int16_t i, frameno; + int16_t L_subframe; + int16_t left_overlap = -1, right_overlap = -1, folding_offset; + float buf[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + float mdstWin[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */ + float *powerSpec; + float *tcx20Win; + float tcx5Win[N_TCX10_MAX / 2 + L_MDCT_OVLP_MAX]; /* Buffer for TCX5 windowing and interleaving. */ + float *interleaveBuf = tcx5Win; + int16_t nSubframes; + int16_t overlap_mode[3]; + int16_t *transform_type = hTcxEnc->transform_type; + float r[M + 1]; + float A[M + 1]; + float *lsp[2]; + const int16_t tcx10SizeFB = 2 * st->hTcxCfg->tcx5SizeFB; + const int16_t tcx5SizeFB = st->hTcxCfg->tcx5SizeFB; + const int16_t tcx10Size = 2 * st->hTcxCfg->tcx5Size; + int16_t alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1; + float alw_voicing[2], alw_voicing_wc = -1; + int16_t disable_ltp = 0; + + if ( last_element_mode != st->element_mode ) + { + disable_ltp = 1; /* disable TCX-LTP in stereo switching to avoid discontinuities in synthesis */ + } + + powerSpec = tcx20Win = buf; /* Share memory for windowed TD signal and for the power spectrum */ + + /*--------------------------------------------------------------* + * Input Signal Processing: copy, HP filter, pre-emphasis + *---------------------------------------------------------------*/ + + if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) + { + /* Copy Samples */ + mvr2r( new_samples, st->new_speech_enc, L_frame ); + } + + /*--------------------------------------------------------------* + * TCX-LTP + *---------------------------------------------------------------*/ + + if ( st->element_mode == IVAS_CPE_DFT ) + { + tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->wspeech_enc, NULL, st->wspeech_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->speech_enc + st->encoderLookahead_enc, hTcxEnc->speech_ltp + st->encoderLookahead_enc, st->speech_enc + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + + if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) + { + mvr2r( st->speech_enc + st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame ); + + preemph( st->new_speech_enc_pe, st->preemph_fac, L_frame, &( st->mem_preemph_enc ) ); + } + + if ( hTcxEnc->tcxMode == TCX_10 ) + { + mvs2s( ¶m_core[1 + NOISE_FILL_RANGES], ¶m_core[NPRM_DIV + 1 + NOISE_FILL_RANGES], LTPSIZE ); + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + lsp[0] = lsp_new; + lsp[1] = lsp_mid; + } + + /*-------------------------------------------------------------------------* + * Decision matrix for the transform and overlap length + *--------------------------------------------------------------------------*/ + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + alw_pitch_lag_12k8[0] = st->pitch[0]; + alw_pitch_lag_12k8[1] = st->pitch[1]; + alw_voicing[0] = st->voicing[0]; + alw_voicing[1] = st->voicing[1]; + alw_pitch_lag_12k8_wc = min( alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1] ); + alw_voicing_wc = max( alw_voicing[0], alw_voicing[1] ); + } + + overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ + + if ( hTcxEnc->tcxMode == TCX_20 ) + { + nSubframes = 1; + transform_type[0] = TCX_20; + transform_type[1] = TCX_20; + overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc; + alw_voicing[0] = alw_voicing_wc; + } + } + else + { + nSubframes = 2; + if ( curr_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_5; + transform_type[1] = TCX_10; + overlap_mode[1] = ( last_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + else if ( last_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_10; + transform_type[1] = TCX_5; + overlap_mode[1] = ( curr_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ + } + else + { + transform_type[0] = transform_type[1] = TCX_5; + overlap_mode[1] = ( last_overlap == HALF_OVERLAP && curr_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ + } + + if ( st->igf && transform_type[0] != TCX_20 ) + { + IGFEncResetTCX10BitCounter( st->hIGFEnc ); + } + + for ( frameno = 0; frameno < nSubframes; frameno++ ) + { + /*-------------------------------------------------------------------------* + * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed + *--------------------------------------------------------------------------*/ + + L_subframe = L_frameTCX / nSubframes; + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + wtda( hTcxEnc->new_speech_TCX, tcx20Win, NULL, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX ); + + if ( windowed_samples != NULL ) /* store overlap data for later */ + { + assert( frameno == 0 ); + windowed_samples[0] = (float) overlap_mode[frameno]; + windowed_samples[1] = (float) overlap_mode[frameno + 1]; + } + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 1, 1 ); + } + } + else + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno], overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT, 1 ); + + if ( windowed_samples != NULL ) /* save windowed speech_TCX samples */ + { + assert( L_subframe + ( left_overlap + right_overlap ) / 2 < 2 * L_FRAME_MAX / nSubframes - L_FRAME_MAX / 8 ); + windowed_samples[frameno * L_FRAME_MAX + 0] = (float) overlap_mode[frameno]; + windowed_samples[frameno * L_FRAME_MAX + 1] = (float) overlap_mode[frameno + 1]; + mvr2r( tcx20Win, windowed_samples + frameno * L_FRAME_MAX + 2, L_subframe + ( left_overlap + right_overlap ) / 2 ); + } + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* Outer left folding */ + for ( i = 0; i < left_overlap / 2; i++ ) + { + tcx20Win[left_overlap / 2 + i] -= tcx20Win[left_overlap / 2 - 1 - i]; + } + + if ( st->element_mode == IVAS_CPE_MDCT && frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + /* Outer right folding */ + for ( i = 0; i < right_overlap / 2; i++ ) + { + tcx20Win[L_subframe + left_overlap / 2 - 1 - i] += tcx20Win[L_subframe + left_overlap / 2 + i]; + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + folding_offset = left_overlap / 2; + + for ( i = 0; i < 2; i++ ) + { + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, tcx20Win + i * tcx5SizeFB, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1 ); + + TCX_MDCT( tcx5Win, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + else /* transform_type[frameno] != TCX_5 */ + { + assert( transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20 ); + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + edct( tcx20Win, hTcxEnc->spectrum[frameno], L_subframe, st->element_mode ); + + v_multc( hTcxEnc->spectrum[frameno], (float) sqrt( (float) NORM_MDCT_FACTOR / L_subframe ), hTcxEnc->spectrum[frameno], L_subframe ); + } + else + { + /* TCX20/TCX10 */ + if ( st->element_mode == IVAS_CPE_MDCT && frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + TCX_MDCT( tcx20Win, hTcxEnc->spectrum[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */ + if ( hTcxEnc->tcxMode == TCX_20 && ( st->total_brate < HQ_96k || st->igf ) ) + { + /* Compute noise-measure flags for spectrum filling and quantization */ + AnalyzePowerSpectrum( st, L_subframe * st->L_frame / hTcxEnc->L_frameTCX, L_subframe, left_overlap, right_overlap, hTcxEnc->spectrum[frameno], ( ( hTcxEnc->tcxMode == TCX_20 ) && ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) ) ? mdstWin : tcx20Win, powerSpec ); + } + } + } + + if ( st->element_mode == IVAS_CPE_MDCT ) + { + L_subframe = L_frameTCX / nSubframes; + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + wtda_ext( hTcxEnc->new_speech_TCX, mdstWin, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX, 3 ); + } + else + { + /* Windowing for the MDST */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1 ); + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* Outer left folding */ + for ( i = 0; i < left_overlap / 2; i++ ) + { + mdstWin[left_overlap / 2 + i] += mdstWin[left_overlap / 2 - 1 - i]; + } + + if ( frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + /* Outer right folding */ + for ( i = 0; i < right_overlap / 2; i++ ) + { + mdstWin[L_subframe + left_overlap / 2 - 1 - i] -= mdstWin[L_subframe + left_overlap / 2 + i]; + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + folding_offset = left_overlap / 2; + + for ( i = 0; i < 2; i++ ) + { + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1 ); + + TCX_MDST( tcx5Win, mdst_spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + else /* transform_type[frameno] != TCX_5 */ + { + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + edst( mdstWin, mdst_spectrum[frameno], L_subframe, st->element_mode ); + + v_multc( mdst_spectrum[frameno], (float) sqrt( (float) NORM_MDCT_FACTOR / L_subframe ), mdst_spectrum[frameno], L_subframe ); + } + else + { + if ( frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + TCX_MDST( mdstWin, mdst_spectrum[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( mdst_spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, mdst_spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); + } + } + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + TNSAnalysis( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], ( frameno == 0 ) && ( st->last_core == ACELP_CORE ), hTcxEnc->spectrum[frameno], st->hTranDet, -1, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); + + if ( st->hTcxCfg->fIsTNSAllowed ) + { + EncodeTnsData( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frameno], param_core + frameno * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, pTnsSize + frameno, pTnsBits + frameno ); + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* group sub-windows: interleave bins according to their frequencies */ + for ( i = 0; i < tcx5SizeFB; i++ ) + { + interleaveBuf[2 * i] = hTcxEnc->spectrum[frameno][i]; + interleaveBuf[2 * i + 1] = hTcxEnc->spectrum[frameno][tcx5SizeFB + i]; + } + mvr2r( interleaveBuf, hTcxEnc->spectrum[frameno], tcx10SizeFB ); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + if ( st->tcxonly ) + { + HBAutocorrelation( st->hTcxCfg, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &st->speech_enc_pe[frameno * tcx10Size], L_frame / nSubframes, r ); + + adapt_lag_wind( r, M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core ); + + lev_dur( A, r, M, NULL ); + + a2lsp_stab( A, lsp[nSubframes - 1 - frameno], st->lspold_enc ); + } + if ( st->igf ) { ProcessIGF( st, hTcxEnc->spectrum[frameno], hTcxEnc->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); @@ -490,3 +1083,4 @@ void core_signal_analysis_high_bitrate( return; } +#endif diff --git a/lib_enc/ext_sig_ana_fx.c b/lib_enc/ext_sig_ana_fx.c index ee7c572c007f2ff86af1fc1530307bca09676481..f81c1a665ac8c04ddb93cd34cf049312b9899b55 100644 --- a/lib_enc/ext_sig_ana_fx.c +++ b/lib_enc/ext_sig_ana_fx.c @@ -6,11 +6,15 @@ #include #include "options.h" #include "cnst.h" -//#include "prot_fx.h" +// #include "prot_fx.h" #include "rom_com.h" #include "basop_util.h" #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#ifdef IVAS_FLOAT_FIXED +#include +#include +#endif /*-------------------------------------------------------------------* @@ -621,3 +625,779 @@ void core_signal_analysis_high_bitrate_fx( return; } + +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * core_signal_analysis_high_bitrate_ivas_fx() + * + * + *-------------------------------------------------------------------*/ + +void core_signal_analysis_high_bitrate_ivas_fx( + const Word16 *new_samples, /*i: Q0 */ + const Word16 T_op[3], /* i : open-loop pitch values for quantiz. */ + Word16 lsp_new[], /* Q15 */ + Word16 lsp_mid[], /* Q15 */ + Encoder_State *st, + Word16 pTnsSize[], + Word16 pTnsBits[], + Word16 param_core[], + Word16 *ltpBits, + Word32 *windowed_samples, + const Word16 L_frame, + const Word16 L_frameTCX, + const Word16 last_element_mode, + const Word16 vad_hover_flag, /* i : VAD hangover flag */ + Word32 **spectrum, + Word16 *spectrum_e, + Word16 *Q_new ) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + const Word16 last_overlap = st->hTcxCfg->tcx_last_overlap_mode; + const Word16 curr_overlap = st->hTcxCfg->tcx_curr_overlap_mode; + const Word16 minWindowLen = sub( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word16 i, frameno; + Word16 L_subframe; + Word16 left_overlap = -1, right_overlap = -1, folding_offset; + Word32 buf[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + Word16 mdstWin[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */ + Word16 *pMdstWin; + Word16 lpc_left_overlap_mode, lpc_right_overlap_mode; + Word32 *powerSpec = buf; + Word16 powerSpec_e; + Word16 *tcx20Win = (Word16 *) buf; + Word32 *tcx20Win_32 = buf; + Word32 interleaveBuf[N_TCX10_MAX]; + Word16 *tcx5Win = (Word16 *) interleaveBuf; /* Buffer for TCX5 windowing and interleaving. */ + Word16 nSubframes; + Word16 overlap_mode[3]; + Word16 *transform_type = hTcxEnc->transform_type; + Word32 r[M + 1]; + Word16 A[M + 1]; + Word16 r_h[NB_DIV][M + 1], r_l[NB_DIV][M + 1]; + Word16 *lsp[2]; + const Word16 tcx10SizeFB = shl( st->hTcxCfg->tcx5SizeFB, 1 ); + const Word16 tcx5SizeFB = st->hTcxCfg->tcx5SizeFB; + const Word16 tcx10Size = shl( st->hTcxCfg->tcx5Size, 1 ); + Word16 alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1; + Word16 alw_voicing[2], alw_voicing_wc = -1; + Word16 disable_ltp = 0; + Word16 tmp, *tmpP16; + Word32 *tmpP32; + Word16 Q_exp; + Word32 L_tmpbuf[N_MAX + L_MDCT_OVLP_MAX]; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + (void) vad_hover_flag; + powerSpec_e = 0; + move16(); + + Word16 *speech_ltp_fx = NULL; + Word16 *wspeech_fx = NULL; + Word16 *speech_fx = NULL; + Word16 q_out_wtda = 0; + move16(); + + if ( NE_16( last_element_mode, st->element_mode ) ) + { + disable_ltp = 1; /* disable TCX-LTP in stereo switching to avoid discontinuities in synthesis */ + move16(); + } + + /*--------------------------------------------------------------* + * Input Signal Processing: copy, HP filter, pre-emphasis + *---------------------------------------------------------------*/ + + /* Copy Samples */ + test(); + IF( st->tcxonly && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Copy( new_samples, st->new_speech_enc, L_frame ); + Scale_sig( st->new_speech_enc, L_frame, 1 ); // Q1 + } + + /*--------------------------------------------------------------* + * TCX-LTP + *---------------------------------------------------------------*/ + + if ( st->element_mode == IVAS_CPE_DFT ) + { + if ( st->element_mode > EVS_MONO ) + { + wspeech_fx = st->buf_wspeech_enc + st->L_frame + L_SUBFR; + } + else + { + wspeech_fx = st->buf_wspeech_enc + st->L_frame + idiv1616( st->L_frame, st->nb_subfr ); + } + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + speech_fx = st->buf_speech_enc + +st->encoderPastSamples_enc; + speech_ltp_fx = st->hTcxEnc->buf_speech_ltp + st->encoderPastSamples_enc; + } + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, wspeech_fx, NULL, wspeech_fx, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + ELSE IF( st->element_mode != IVAS_CPE_MDCT ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, speech_fx + st->encoderLookahead_enc, speech_ltp_fx + st->encoderLookahead_enc, speech_fx + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + + test(); + IF( st->tcxonly && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Copy( st->speech_enc + st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame ); + + Preemph_scaled( st->new_speech_enc_pe, Q_new, &( st->mem_preemph_enc ), + st->Q_max_enc, st->preemph_fac, 1, 0, 2, L_frame, st->coder_type_raw, 1 ); + } + + /* Rescale Memory */ + Q_exp = sub( *Q_new, st->prev_Q_new ); + move16(); + + Scale_sig( st->old_inp_16k_fx, L_INP_MEM, sub( *Q_new, st->Q_old ) ); // *Q_new + IF( Q_exp != 0 ) + { + Scale_sig( st->buf_speech_enc_pe, st->encoderPastSamples_enc + st->encoderLookahead_enc, Q_exp ); // *Q_new + Scale_sig( &( st->mem_wsp_enc ), 1, Q_exp ); // *Q_new + } + + IF( EQ_16( hTcxEnc->tcxMode, TCX_10 ) ) + { + Copy( ¶m_core[1 + NOISE_FILL_RANGES], ¶m_core[NPRM_DIV + 1 + NOISE_FILL_RANGES], LTPSIZE ); + } + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + lsp[0] = lsp_new; + move16(); + lsp[1] = lsp_mid; + move16(); + } + + /*-------------------------------------------------------------------------* + * Decision matrix for the transform and overlap length + *--------------------------------------------------------------------------*/ + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + alw_pitch_lag_12k8[0] = st->pitch[0]; + move16(); + alw_pitch_lag_12k8[1] = st->pitch[1]; + move16(); + alw_voicing[0] = st->voicing_fx[0]; + move16(); + alw_voicing[1] = st->voicing_fx[1]; + move16(); + alw_pitch_lag_12k8_wc = s_min( alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1] ); + alw_voicing_wc = s_max( alw_voicing[0], alw_voicing[1] ); + } + + overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ + move16(); + + IF( EQ_16( hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + transform_type[0] = TCX_20; + move16(); + transform_type[1] = TCX_20; + move16(); + overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ + move16(); + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc; + move16(); + alw_voicing[0] = alw_voicing_wc; + move16(); + } + } + ELSE + { + nSubframes = 2; + move16(); + IF( curr_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_5; + move16(); + transform_type[1] = TCX_10; + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + move16(); + if ( EQ_16( last_overlap, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + ELSE IF( last_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_10; + move16(); + transform_type[1] = TCX_5; + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ + move16(); + if ( EQ_16( curr_overlap, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + ELSE + { + transform_type[0] = transform_type[1] = TCX_5; + move16(); + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + move16(); + test(); + if ( EQ_16( last_overlap, HALF_OVERLAP ) && EQ_16( curr_overlap, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ + move16(); + } + + test(); + IF( st->igf && NE_16( transform_type[0], TCX_20 ) ) + { + IGFEncResetTCX10BitCounter_fx( st->hIGFEnc ); + } + + /*-------------------------------------------------------------------------* + * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed + *--------------------------------------------------------------------------*/ + + FOR( frameno = 0; frameno < nSubframes; frameno++ ) + { + L_subframe = L_frameTCX; + move16(); + IF( NE_16( nSubframes, 1 ) ) + { + L_subframe = shr( L_frameTCX, 1 ); + } + + lpc_left_overlap_mode = overlap_mode[frameno]; + move16(); + lpc_right_overlap_mode = overlap_mode[frameno + 1]; + move16(); + if ( EQ_16( lpc_left_overlap_mode, ALDO_WINDOW ) ) + { + lpc_left_overlap_mode = FULL_OVERLAP; + move16(); + } + if ( EQ_16( lpc_right_overlap_mode, ALDO_WINDOW ) ) + { + lpc_right_overlap_mode = FULL_OVERLAP; + move16(); + } + + test(); + IF( ( EQ_16( transform_type[frameno], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + wtda_fx( hTcxEnc->new_speech_TCX, &q_out_wtda, tcx20Win_32, NULL, NULL, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX ); + + IF( windowed_samples != NULL ) /* store overlap data for later */ + { + assert( frameno == 0 ); + windowed_samples[0] = L_deposit_l( overlap_mode[frameno] ); + windowed_samples[1] = L_deposit_l( overlap_mode[frameno + 1] ); + } + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 1, 1 ); + } + } + ELSE + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno], + overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], + &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT /* truncate_aldo */, 1 ); + + IF( windowed_samples != NULL ) /* save windowed speech_TCX samples */ + { + assert( L_subframe + ( left_overlap + right_overlap ) / 2 < 2 * L_FRAME_MAX / nSubframes - L_FRAME_MAX / 8 ); + windowed_samples[frameno * L_FRAME_MAX + 0] = L_deposit_l( overlap_mode[frameno] ); + windowed_samples[frameno * L_FRAME_MAX + 1] = L_deposit_l( overlap_mode[frameno + 1] ); + Copy_Scale_sig_16_32( tcx20Win, windowed_samples + frameno * L_FRAME_MAX + 2, L_subframe + ( left_overlap + right_overlap ) / 2, 0 ); + } + } + + IF( EQ_16( transform_type[frameno], TCX_5 ) ) + { + folding_offset = shr( left_overlap, 1 ); + + /* Outter left folding */ + FOR( i = 0; i < folding_offset; i++ ) + { +#ifdef BASOP_NOGLOB + tcx20Win[folding_offset + i] = sub_sat( tcx20Win[folding_offset + i], tcx20Win[folding_offset - 1 - i] ); +#else + tcx20Win[folding_offset + i] = sub( tcx20Win[folding_offset + i], tcx20Win[folding_offset - 1 - i] ); +#endif + move16(); + } + + test(); + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && frameno == 0 && overlap_mode[0] == FULL_OVERLAP && GT_16( sub( L_subframe, left_overlap ), minWindowLen ) ) + { + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word32 L_tmp; + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + tcx20Win[left_overlap + i] = sub_sat( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + tcx20Win[left_overlap + i] = sub( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + tcx20Win[left_overlap + i] = sub_sat( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + tcx20Win[left_overlap + i] = sub( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + } + + /* Outter right folding */ + tmp = shr( right_overlap, 1 ); + FOR( i = 0; i < tmp; i++ ) + { +#ifdef BASOP_NOGLOB + tcx20Win[L_subframe + folding_offset - 1 - i] = add_sat( tcx20Win[L_subframe + folding_offset - 1 - i], tcx20Win[L_subframe + folding_offset + i] ); +#else + tcx20Win[L_subframe + folding_offset - 1 - i] = add( tcx20Win[L_subframe + folding_offset - 1 - i], tcx20Win[L_subframe + folding_offset + i] ); +#endif + move16(); + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + move16(); + + tmpP16 = tcx20Win; + tmpP32 = hTcxEnc->spectrum_fx[frameno]; + assert( st->mct_chan_mode != MCT_CHAN_MODE_LFE ); + FOR( i = 0; i < 2; i++ ) + { + test(); + test(); + WindowSignal( st->hTcxCfg, + folding_offset, + mac_r( -( 1 << 16 ), 3 << 8, shl( i, 7 ) ), /* equivalent to: i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */ + mac_r( 2 << 16, -( 3 << 8 ), shl( i, 7 ) ), /* equivalent to: sub(i, 1) == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */ + &left_overlap, &right_overlap, tmpP16, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1 ); + + hTcxEnc->spectrum_e[frameno] = 16; + move16(); + TCX_MDCT( tcx5Win, + tmpP32, + &hTcxEnc->spectrum_e[frameno], + left_overlap, + sub( L_subframe, shr( add( left_overlap, right_overlap ), 1 ) ), + right_overlap, st->element_mode ); + + tmpP16 += tcx5SizeFB; + tmpP32 += tcx5SizeFB; + + /* high-band gain control in case of BWS */ + IF( st->bwidth_sw_cnt > 0 ) + { + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( st->bwidth_sw_cnt, BWS_TRAN_PERIOD, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( hTcxEnc->spectrum_fx[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), + factor, + hTcxEnc->spectrum_fx[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), + L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + ELSE /* transform_type[frameno] != TCX_5 */ + { + assert( transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20 ); + + /* TCX20/TCX10 */ + hTcxEnc->spectrum_e[frameno] = 16; + move16(); + test(); + test(); + IF( ( EQ_16( transform_type[frameno], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + /* DCT */ + Word16 Q; + + Q = q_out_wtda; + edct_fx( tcx20Win_32, hTcxEnc->spectrum_fx[frameno], L_subframe, &Q ); + hTcxEnc->spectrum_e[frameno] = sub( 31, Q ); + move16(); + + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( NORM_MDCT_FACTOR, L_subframe, &exp_diff ); + tmp = Sqrt16( tmp, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( hTcxEnc->spectrum_fx[frameno], factor, hTcxEnc->spectrum_fx[frameno], L_subframe ); + } + ELSE + { + test(); + test(); + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && frameno == 0 && EQ_16( transform_type[0], TCX_10 ) && overlap_mode[0] == FULL_OVERLAP && GT_16( sub( L_subframe, left_overlap ), minWindowLen ) ) + { + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word32 L_tmp; + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + tcx20Win[left_overlap + i] = sub_sat( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + tcx20Win[left_overlap + i] = sub( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + tcx20Win[left_overlap + i] = sub_sat( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + tcx20Win[left_overlap + i] = sub( tcx20Win[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + } + + TCX_MDCT( tcx20Win, hTcxEnc->spectrum_fx[frameno], &hTcxEnc->spectrum_e[frameno], left_overlap, sub( L_subframe, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + IF( st->bwidth_sw_cnt > 0 ) + { + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( st->bwidth_sw_cnt, BWS_TRAN_PERIOD, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( hTcxEnc->spectrum_fx[frameno] + L_FRAME16k / nSubframes, + factor, + hTcxEnc->spectrum_fx[frameno] + L_FRAME16k / nSubframes, + L_subframe - L_FRAME16k / nSubframes ); + } + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */ + test(); + test(); + IF( EQ_16( hTcxEnc->tcxMode, TCX_20 ) && ( ( LT_32( st->total_brate, HQ_96k ) ) || st->igf ) ) + { + pMdstWin = tcx20Win; + test(); + if ( ( ( EQ_16( hTcxEnc->tcxMode, TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) ) + { + pMdstWin = mdstWin; + } + + /* Compute noise-measure flags for spectrum filling and quantization */ + AnalyzePowerSpectrum_fx( st, div_l( L_mult( L_subframe, st->L_frame ), hTcxEnc->L_frameTCX ), + L_subframe, left_overlap, right_overlap, hTcxEnc->spectrum_fx[frameno], hTcxEnc->spectrum_e[frameno], + pMdstWin, powerSpec, &powerSpec_e ); + } + } + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + L_subframe = idiv1616( L_frameTCX, nSubframes ); + + test(); + IF( EQ_16( transform_type[frameno], TCX_20 ) && NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + wtda_ext_fx( hTcxEnc->new_speech_TCX, mdstWin, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX, 3 ); + Scale_sig( mdstWin, L_frameTCX, 1 ); + } + ELSE + { + /* Windowing for the MDST */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1 ); + } + + IF( EQ_16( transform_type[frameno], TCX_5 ) ) + { + /* Outer left folding */ + FOR( i = 0; i < left_overlap / 2; i++ ) + { +#ifdef BASOP_NOGLOB + mdstWin[left_overlap / 2 + i] = add_sat( mdstWin[left_overlap / 2 + i], mdstWin[left_overlap / 2 - 1 - i] ); +#else + mdstWin[left_overlap / 2 + i] = add( mdstWin[left_overlap / 2 + i], mdstWin[left_overlap / 2 - 1 - i] ); +#endif + } + + test(); + test(); + IF( frameno == 0 && overlap_mode[0] == FULL_OVERLAP && GT_16( sub( L_subframe, left_overlap ), minWindowLen ) ) + { + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word32 L_tmp; + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + mdstWin[left_overlap + i] = add_sat( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + mdstWin[left_overlap + i] = add( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + mdstWin[left_overlap + i] = add_sat( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + mdstWin[left_overlap + i] = add( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + } + + /* Outer right folding */ + FOR( i = 0; i < right_overlap / 2; i++ ) + { +#ifdef BASOP_NOGLOB + mdstWin[L_subframe + left_overlap / 2 - 1 - i] = sub_sat( mdstWin[L_subframe + left_overlap / 2 - 1 - i], mdstWin[L_subframe + left_overlap / 2 + i] ); +#else + mdstWin[L_subframe + left_overlap / 2 - 1 - i] = sub( mdstWin[L_subframe + left_overlap / 2 - 1 - i], mdstWin[L_subframe + left_overlap / 2 + i] ); +#endif + move16(); + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + move16(); + folding_offset = shr( left_overlap, 1 ); + move16(); + + FOR( i = 0; i < 2; i++ ) + { + assert( st->mct_chan_mode != MCT_CHAN_MODE_LFE ); + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1 ); + + spectrum_e[frameno] = 16; + move16(); + TCX_MDST( tcx5Win, spectrum[frameno] + i * tcx5SizeFB, &spectrum_e[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + /* high-band gain control in case of BWS */ + IF( st->bwidth_sw_cnt > 0 ) + { + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( st->bwidth_sw_cnt, BWS_TRAN_PERIOD, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), + factor, + spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), + L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + ELSE /* transform_type[frameno] != TCX_5 */ + { + spectrum_e[frameno] = 16; + test(); + IF( EQ_16( transform_type[frameno], TCX_20 ) && NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + Word16 Q; + Copy_Scale_sig_16_32_no_sat( mdstWin, L_tmpbuf, N_MAX + L_MDCT_OVLP_MAX, 16 ); + + Q = 16; + move16(); + edst_fx( L_tmpbuf, spectrum[frameno], L_subframe, &Q ); + spectrum_e[frameno] = 31 - Q; + + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( NORM_MDCT_FACTOR, L_subframe, &exp_diff ); + tmp = Sqrt16( tmp, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( spectrum[frameno], factor, spectrum[frameno], L_subframe ); + } + ELSE + { + test(); + test(); + test(); + IF( frameno == 0 && EQ_16( transform_type[0], TCX_10 ) && overlap_mode[0] == FULL_OVERLAP && GT_16( sub( L_subframe, left_overlap ), minWindowLen ) ) + { + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word32 L_tmp; + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + mdstWin[left_overlap + i] = add_sat( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + mdstWin[left_overlap + i] = add( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( hTcxEnc->speech_TCX[-1 - i], st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, st->hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( 0, Q16 ) ); // Q0 +#ifdef BASOP_NOGLOB + mdstWin[left_overlap + i] = add_sat( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#else + mdstWin[left_overlap + i] = add( mdstWin[left_overlap + i], extract_l( L_tmp ) ); // Q0 +#endif + move32(); + } + } + + TCX_MDST( mdstWin, spectrum[frameno], &spectrum_e[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + IF( st->bwidth_sw_cnt > 0 ) + { + Word16 exp_diff; + Word32 factor; + + tmp = BASOP_Util_Divide1616_Scale( st->bwidth_sw_cnt, BWS_TRAN_PERIOD, &exp_diff ); + factor = L_shl( L_deposit_h( tmp ), exp_diff ); // Q31 + + v_multc_fixed( spectrum[frameno] + L_FRAME16k / nSubframes, factor, spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); + } + } + } + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + test(); + IF( ( frameno == 0 ) && ( st->last_core == ACELP_CORE ) ) + { + TNSAnalysis_ivas_fx( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], 1, hTcxEnc->spectrum_fx[frameno], st->hTranDet, -32768, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); + } + ELSE + { + TNSAnalysis_ivas_fx( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], 0, hTcxEnc->spectrum_fx[frameno], st->hTranDet, -32768, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); + } + + IF( st->hTcxCfg->fIsTNSAllowed ) + { + EncodeTnsData_fx( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frameno], + param_core + frameno * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, pTnsSize + frameno, pTnsBits + frameno ); + } + + IF( EQ_16( transform_type[frameno], TCX_5 ) ) + { + /* group sub-windows: interleave bins according to their frequencies */ + FOR( i = 0; i < tcx5SizeFB; i++ ) + { + interleaveBuf[2 * i] = hTcxEnc->spectrum_fx[frameno][i]; + move32(); + interleaveBuf[2 * i + 1] = hTcxEnc->spectrum_fx[frameno][tcx5SizeFB + i]; + move32(); + } + MVR2R_WORD32( interleaveBuf, hTcxEnc->spectrum_fx[frameno], tcx10SizeFB ); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + IF( st->tcxonly ) + { + HBAutocorrelation_fx( st->hTcxCfg, lpc_left_overlap_mode, lpc_right_overlap_mode, &st->speech_enc_pe[frameno * tcx10Size], + shr( L_frame, sub( nSubframes, 1 ) ), r, M ); + + FOR( i = 0; i <= M; i++ ) + { + r_l[frameno][i] = L_Extract_lc( r[i], &r_h[frameno][i] ); + move16(); + move16(); + } + + adapt_lag_wind( r_h[frameno], r_l[frameno], M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core ); + + E_LPC_lev_dur( r_h[frameno], r_l[frameno], A, NULL, M, NULL ); + + E_LPC_a_lsp_conversion( A, lsp[nSubframes - 1 - frameno], st->lspold_enc_fx, M ); + } + + IF( st->igf ) + { + Word16 q_spectrum = sub( Q31, hTcxEnc->spectrum_e[frameno] ); + Word16 q_powerSpec = sub( Q31, powerSpec_e ); + ProcessIGF_ivas_fx( st, hTcxEnc->spectrum_fx[frameno], hTcxEnc->spectrum_fx[frameno], &q_spectrum, powerSpec, &q_powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); + } + } + } + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* Copy memory */ + MVR2R_WORD16( lsp_new, st->lspold_enc_fx, M ); + } + + return; +} +#endif diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index 5dc4290c0516494c0afb783992292cb18c5180a5..718666927012fb41189034a440bc50ad5a484472 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -42,11 +42,16 @@ #include "rom_com.h" #include "prot.h" #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot.h" #include "ivas_prot_fx.h" #include "stat_enc.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif + /*-------------------------------------------------------------------* * createFdCngEnc() * @@ -131,30 +136,41 @@ void initFdCngEnc( } /* Initialize the Noise Estimator */ + set_f( hFdCngEnc->msPeriodog, 0.0f, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msAlpha, 0.0f, NPART ); set_f( hFdCngEnc->msBminWin, 0.0f, NPART ); set_f( hFdCngEnc->msBminSubWin, 0.0f, NPART ); set_f( hFdCngEnc->msPsd, 0.0f, NPART ); set_f( hFdCngEnc->msNoiseFloor, 0.0f, NPART ); +#endif set_f( hFdCngEnc->msNoiseEst, 0.0f, NPART ); set_f( hFdCngEnc->energy_ho, 0.0f, NPART ); set_f( hFdCngEnc->msNoiseEst_old, 0.0f, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msMinBuf, FLT_MAX, MSNUMSUBFR * NPART ); set_f( hFdCngEnc->msCurrentMin, FLT_MAX, NPART ); set_f( hFdCngEnc->msCurrentMinOut, FLT_MAX, NPART ); set_f( hFdCngEnc->msCurrentMinSubWindow, FLT_MAX, NPART ); +#endif set_s( hFdCngEnc->msLocalMinFlag, 0, NPART ); set_s( hFdCngEnc->msNewMinFlag, 0, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msPsdFirstMoment, 0.0f, NPART ); set_f( hFdCngEnc->msPsdSecondMoment, 0.0f, NPART ); +#endif hFdCngEnc->msPeriodogBufPtr = 0; + set_f( hFdCngEnc->msPeriodogBuf, 0.0f, MSBUFLEN * NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msLogPeriodog, 0.0f, NPART ); set_f( hFdCngEnc->msLogNoiseEst, 0.0f, NPART ); +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hFdCngEnc->mem_coherence, EPSILON, 4 ); - +#endif return; } @@ -258,152 +274,10 @@ void configureFdCngEnc( assert( !"Unsupported FFT length for FD-based CNG" ); break; } - hsCom->frameSize = hsCom->fftlen >> 1; - - return; -} - -#ifdef IVAS_FLOAT_FIXED -void configureFdCngEnc_ivas_fx( - HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: Contains the variables related to the FD-based CNG process */ - const Word16 bwidth, - const Word32 total_brate ) -{ - HANDLE_FD_CNG_COM hsCom = hFdCngEnc->hFdCngCom; - Word16 psizeDec[NPART]; - Word16 psizeDec_norm[NPART]; - Word16 psizeDec_norm_exp; - Word16 psize_invDec[NPART]; - - set16_fx( psizeDec, 0, NPART ); - - hsCom->CngBandwidth = bwidth; - move16(); - IF( EQ_16( hsCom->CngBandwidth, FB ) ) - { - hsCom->CngBandwidth = SWB; - move16(); - } - hsCom->CngBitrate = total_brate; - move32(); - - /* NB configuration */ - IF( EQ_16( bwidth, NB ) ) - { - hsCom->FdCngSetup = FdCngSetup_nb; /* PTR assignation -> no move needed*/ - move16(); - } - - /* WB configuration */ - ELSE IF( EQ_16( bwidth, WB ) ) - { - /* FFT 6.4kHz, no CLDFB */ - IF( LE_32( total_brate, ACELP_8k00 ) ) - { - hsCom->FdCngSetup = FdCngSetup_wb1; - move16(); - } - /* FFT 6.4kHz, CLDFB 8.0kHz */ - ELSE IF( LE_32( total_brate, ACELP_13k20 ) ) - { - hsCom->FdCngSetup = FdCngSetup_wb2; - move16(); - } - /* FFT 8.0kHz, no CLDFB */ - ELSE - { - hsCom->FdCngSetup = FdCngSetup_wb3; - move16(); - } - } - - /* SWB/FB configuration */ - ELSE - { - /* FFT 6.4kHz, CLDFB 14kHz */ - IF( LE_32( total_brate, ACELP_13k20 ) ) - { - hsCom->FdCngSetup = FdCngSetup_swb1; - move16(); - } - /* FFT 8.0kHz, CLDFB 16kHz */ - ELSE - { - hsCom->FdCngSetup = FdCngSetup_swb2; - move16(); - } - } - hsCom->fftlen = hsCom->FdCngSetup.fftlen; - move16(); - hFdCngEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin; - move16(); - - /* Configure the SID quantizer and the Confort Noise Generator */ - - hFdCngEnc->startBandDec = hsCom->startBand; - move16(); - hFdCngEnc->stopBandDec = add( hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions - 1], 1 ); - move16(); - initPartitions( hsCom->FdCngSetup.sidPartitions, - hsCom->FdCngSetup.numPartitions, - hFdCngEnc->startBandDec, - hFdCngEnc->stopBandDec, - hFdCngEnc->partDec, - &hFdCngEnc->npartDec, - hFdCngEnc->midbandDec, - psizeDec, - psizeDec_norm, - &psizeDec_norm_exp, - psize_invDec, - 0 ); - IF( EQ_16( hFdCngEnc->stopFFTbinDec, 160 ) ) - { - hFdCngEnc->nFFTpartDec = 17; - move16(); - } - ELSE IF( EQ_16( hFdCngEnc->stopFFTbinDec, 256 ) ) - { - hFdCngEnc->nFFTpartDec = 20; - move16(); - } - ELSE - { - hFdCngEnc->nFFTpartDec = 21; - move16(); - } - - switch ( hsCom->fftlen ) - { - case 512: -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - hsCom->fftSineTab_flt = NULL; - hsCom->olapWinAna_flt = olapWinAna512; - hsCom->olapWinSyn_flt = olapWinSyn256; -#endif - hsCom->fftSineTab_fx = NULL; - hsCom->olapWinAna_fx = olapWinAna512_fx; - hsCom->olapWinSyn_fx = olapWinSyn256_fx; - break; - case 640: -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - hsCom->fftSineTab_flt = fftSineTab640; - hsCom->olapWinAna_flt = olapWinAna640; - hsCom->olapWinSyn_flt = olapWinSyn320; -#endif - hsCom->fftSineTab_fx = fftSineTab640_fx; - hsCom->olapWinAna_fx = olapWinAna640_fx; - hsCom->olapWinSyn_fx = olapWinSyn320_fx; - break; - default: - assert( !"Unsupported FFT length for FD-based CNG" ); - break; - } hsCom->frameSize = shr( hsCom->fftlen, 1 ); - move16(); return; } -#endif /*-------------------------------------------------------------------* * deleteFdCngEnc() @@ -433,7 +307,7 @@ void deleteFdCngEnc( * * Reset the instance of type FD_CNG *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void resetFdCngEnc( Encoder_State *st /* i/o: encoder state structure */ ) @@ -491,13 +365,181 @@ void resetFdCngEnc( return; } - - +#endif /*-------------------------------------------------------------------* * perform_noise_estimation_enc() * * Perform noise estimation *-------------------------------------------------------------------*/ +void perform_noise_estimation_enc_ivas_fx( + Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp, + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate */ + CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ +) +{ + Word16 i, j, s, s1, s2; + Word16 numBands; + Word16 numCoreBands = hFdCngEnc->hFdCngCom->numCoreBands; + move16(); + Word16 regularStopBand = hFdCngEnc->hFdCngCom->regularStopBand; + move16(); + Word16 numSlots = hFdCngEnc->hFdCngCom->numSlots; + move16(); + assert( numSlots == 16 ); + + Word32 numSlots_inv_fx = 134217728; + move32(); + Word32 *periodog = hFdCngEnc->hFdCngCom->periodog; + Word32 *ptr_per_fx = periodog; + Word16 npart = hFdCngEnc->hFdCngCom->npart; + move16(); + Word16 nFFTpart = hFdCngEnc->hFdCngCom->nFFTpart; + move16(); + Word16 nCLDFBpart = hFdCngEnc->hFdCngCom->nCLDFBpart; + move16(); + + Word16 *psize = hFdCngEnc->hFdCngCom->psize; + Word32 *msPeriodog_fx = hFdCngEnc->msPeriodog_fx; + Word32 *msNoiseEst_fx = hFdCngEnc->msNoiseEst_fx; + + Word16 *msLogPeriodog_fx = hFdCngEnc->msLogPeriodog_fx; + Word16 *msLogNoiseEst_fx = hFdCngEnc->msLogNoiseEst_fx; + + Word32 scaleEB_fx = 0; + move32(); + Word32 tmp; + + test(); + IF( hCPE != NULL && hCPE->hStereoDft != NULL ) + { + // band_res_dft = ( (float) input_Fs ) / hCPE->hStereoDft->NFFT; + // chan_width_f = 24000.f / CLDFB_NO_CHANNELS_MAX; + // chan_width_bins = chan_width_f / band_res_dft; + + ///* Scaling of Energy buffer to get energy per sample, same scaling as for band_energies, 3 is to compensate for the 1/3 scaling in calculate_energy_buffer */ + // scaleEB = 3 * 4.0f / ( hCPE->hStereoDft->NFFT * hCPE->hStereoDft->NFFT ); + + ///* Scale with number of bins in one band */ + // scaleEB = scaleEB / chan_width_bins; + + SWITCH( input_Fs ) + { + case 8000: + scaleEB_fx = 62912; + move32(); + BREAK; + case 16000: + scaleEB_fx = 15728; + move32(); + BREAK; + case 32000: + scaleEB_fx = 3928; + move32(); + BREAK; + case 48000: + scaleEB_fx = 1744; + move32(); + BREAK; + default: + assert( 0 && "invalid sample rate" ); + } + } + ELSE + { + scaleEB_fx = Mpy_32_16_1( numSlots_inv_fx, hFdCngEnc->hFdCngCom->scalingFactor ); + scaleEB_fx = L_shl( scaleEB_fx, 4 ); + } + + /* preemphasis compensation and grouping of per bin energies into msPeriodog */ + FOR( i = 0; i < nFFTpart; i++ ) + { + tmp = L_add( L_shr( band_energies[i], 1 ), L_shr( band_energies[i + NB_BANDS], 1 ) ); + msPeriodog_fx[i] = Mpy_32_16_1( tmp, preemphCompensation_fx[i] ); + move32(); + } + + /* exponent for fft part of msPeriodog */ + hFdCngEnc->msPeriodog_fx_exp_fft = add( band_energies_exp, PREEMPH_COMPENSATION_EXP ); + move16(); + + /* Adjust to the desired time resolution by averaging the periodograms over the time slots */ + FOR( j = numCoreBands; j < regularStopBand; j++ ) + { + *ptr_per_fx = Mpy_32_32( enerBuffer[j], scaleEB_fx ); + move32(); + + ptr_per_fx++; + move16(); + } + + /* exponent for cldfb part of msPeriodog */ + hFdCngEnc->hFdCngCom->exp_cldfb_periodog = add( sub( enerBuffer_exp, 4 ), CLDFBscalingFactor_EXP ); + move16(); + + numBands = sub( regularStopBand, numCoreBands ); + + IF( numBands > 0 ) + { + ///* Adjust CLDFB filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow( + periodog, + hFdCngEnc->hFdCngCom->exp_cldfb_periodog, + numBands, + hFdCngEnc->hFdCngCom->CLDFBpart, + nCLDFBpart, + hFdCngEnc->hFdCngCom->CLDFBpsize_inv, + &msPeriodog_fx[nFFTpart], + &hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + ///* find common exponent for fft part and cldfb part of msperiodog */ + s1 = getScaleFactor32( msPeriodog_fx, nFFTpart ); + s2 = getScaleFactor32( &msPeriodog_fx[nFFTpart], nCLDFBpart ); + + s = s_max( sub( hFdCngEnc->msPeriodog_fx_exp_fft, s1 ), sub( hFdCngEnc->msPeriodog_fx_exp_cldfb, s2 ) ); + s1 = sub( s, hFdCngEnc->msPeriodog_fx_exp_fft ); + s2 = sub( s, hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + hFdCngEnc->msPeriodog_fx_exp_fft = s; + move16(); + hFdCngEnc->msPeriodog_fx_exp_cldfb = s; + move16(); + + FOR( i = 0; i < nFFTpart; i++ ) + { + msPeriodog_fx[i] = L_shr( msPeriodog_fx[i], s1 ); + move32(); + } + + FOR( i = 0; i < nCLDFBpart; i++ ) + { + msPeriodog_fx[nFFTpart + i] = L_shr( msPeriodog_fx[nFFTpart + i], s_min( 31, s2 ) ); + move32(); + } + } + /* exponent for entire msPeriodog vector */ + hFdCngEnc->msPeriodog_fx_exp = hFdCngEnc->msPeriodog_fx_exp_fft; + move16(); + + /* Compress MS inputs */ + // compress_range_flt( msPeriodog, msLogPeriodog, npart ); + compress_range( msPeriodog_fx, hFdCngEnc->msPeriodog_fx_exp, msLogPeriodog_fx, npart ); + + + /* Call the minimum statistics routine for noise estimation */ + + minimum_statistics_fx( npart, nFFTpart, psize, msLogPeriodog_fx, hFdCngEnc->msNoiseFloor_fx, msLogNoiseEst_fx, hFdCngEnc->msAlpha_fx, hFdCngEnc->msPsd_fx, hFdCngEnc->msPsdFirstMoment_fx, + hFdCngEnc->msPsdSecondMoment_fx, hFdCngEnc->msMinBuf_fx, hFdCngEnc->msBminWin_fx, hFdCngEnc->msBminSubWin_fx, hFdCngEnc->msCurrentMin_fx, hFdCngEnc->msCurrentMinOut_fx, hFdCngEnc->msCurrentMinSubWindow_fx, hFdCngEnc->msLocalMinFlag, hFdCngEnc->msNewMinFlag, hFdCngEnc->msPeriodogBuf_fx, &( hFdCngEnc->msPeriodogBufPtr ), hFdCngEnc->hFdCngCom, + ENC, ( hCPE == NULL ) ? 0 : hCPE->element_mode ); + + /* Expand MS outputs */ + expand_range( msLogNoiseEst_fx, msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + + return; +} void perform_noise_estimation_enc( float *band_energies, /* i : energy in critical bands without minimum noise floor E_MIN*/ @@ -577,7 +619,6 @@ void perform_noise_estimation_enc( return; } - /*-------------------------------------------------------------------* * AdjustFirstSID() * @@ -732,7 +773,23 @@ void FdCng_encodeSID( mvr2r( tot_sig_ext, v, FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ } create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 v_e; + Word16 w_fx[24]; + + f2me_buf( v, v_fx, &v_e, N ); + floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + floatToFixed_arr( w, w_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, v_fx, v_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w_fx, N, FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, v, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices ); +#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N, FD_CNG_maxN_37bits, indices, 1, invTrfMatrix, v, NULL ); } else @@ -1042,50 +1099,64 @@ float cng_energy( * * compute coherence of channels for use in FD-CNG *-------------------------------------------------------------------*/ - -void stereoFdCngCoherence( - Encoder_State **sts, /* i/o: core encoder structures */ - const int16_t last_element_mode, /* i : last element mode */ - float fft_buff[CPE_CHANNELS][2 * L_FFT] /* i : fft buffers for L and R channels */ -) +#ifdef IVAS_FLOAT_FIXED +void stereoFdCngCoherence_fx( + Encoder_State **sts, /* i/o: core encoder structures */ + const Word16 last_element_mode, /* i : last element mode */ + Word16 fft_buf_fx[CPE_CHANNELS][2 * L_FFT], /* i : fft buffers for L and R channels fft_exp*/ + Word16 fft_exp ) { - const float *pt_fftL, *pt_fftR; - int16_t i_subfr, i; - float cr, ci, eL, eR; - float *mem; + const Word16 *pt_fftL, *pt_fftR; + Word16 i_subfr, i; + Word32 cr, ci, eL, eR; + Word16 cr_exp, ci_exp, eL_exp, eR_exp; + Word32 *mem; + Word16 *mem_exp; - if ( last_element_mode != IVAS_CPE_MDCT ) + IF( NE_16( last_element_mode, IVAS_CPE_MDCT ) ) { - set_f( sts[0]->hFdCngEnc->mem_coherence, EPSILON, 4 ); + set32_fx( sts[0]->hFdCngEnc->mem_coherence_fx, EPSILON_FX, 4 ); + set16_fx( sts[0]->hFdCngEnc->mem_coherence_exp, 0, 4 ); } - - if ( sts[0]->core_brate == -1 || sts[1]->core_brate == -1 ) + test(); + test(); + IF( EQ_32( sts[0]->core_brate, -1 ) || EQ_32( sts[1]->core_brate, -1 ) ) { /* case: at least one channel has triggered VAD -> ACTIVE FRAME */ - if ( sts[0]->core_brate == -1 ) + IF( EQ_32( sts[0]->core_brate, -1 ) ) { sts[1]->total_brate = sts[0]->total_brate; + move32(); sts[1]->active_cnt = sts[0]->active_cnt; - if ( sts[1]->active_cnt >= CNG_TYPE_HO ) + move16(); + if ( GE_32( sts[1]->active_cnt, CNG_TYPE_HO ) ) { sts[1]->last_total_brate_cng = -1; + move16(); } } - if ( sts[1]->core_brate == -1 ) + IF( EQ_32( sts[1]->core_brate, -1 ) ) { sts[0]->total_brate = sts[1]->total_brate; + move32(); sts[0]->active_cnt = sts[1]->active_cnt; - if ( sts[0]->active_cnt >= CNG_TYPE_HO ) + move16(); + if ( GE_16( sts[0]->active_cnt, CNG_TYPE_HO ) ) { sts[0]->last_total_brate_cng = -1; + move16(); } } sts[0]->core_brate = -1; + move32(); sts[1]->core_brate = -1; + move32(); sts[0]->hDtxEnc->cnt_SID = 0; + move16(); sts[1]->hDtxEnc->cnt_SID = 0; + move16(); } - else if ( sts[0]->core_brate <= SID_2k40 && sts[1]->core_brate <= SID_2k40 ) + ELSE IF( LE_32( sts[0]->core_brate, SID_2k40 ) && LE_32( sts[1]->core_brate, SID_2k40 ) ) { /* case: no VAD for both channels -> INACTIVE FRAME */ reset_indices_enc( sts[0]->hBstr, sts[0]->hBstr->nb_ind_tot ); @@ -1093,54 +1164,175 @@ void stereoFdCngCoherence( reset_indices_enc( sts[1]->hBstr, sts[1]->hBstr->nb_ind_tot ); /* synchronize SID sending for variable SID rate */ - if ( sts[0]->core_brate != sts[1]->core_brate ) + IF( EQ_32( sts[0]->core_brate, sts[1]->core_brate ) ) { sts[0]->core_brate = SID_2k40; + move32(); sts[1]->core_brate = SID_2k40; + move32(); } /* synchronize SID counters */ - sts[0]->hDtxEnc->cnt_SID = min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID ); + sts[0]->hDtxEnc->cnt_SID = s_min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID ); sts[1]->hDtxEnc->cnt_SID = sts[0]->hDtxEnc->cnt_SID; + move16(); + move16(); } - pt_fftL = fft_buff[0]; - pt_fftR = fft_buff[1]; - mem = sts[0]->hFdCngEnc->mem_coherence; - - for ( i_subfr = 0; i_subfr < 2; i_subfr++ ) + pt_fftL = fft_buf_fx[0]; + pt_fftR = fft_buf_fx[1]; + mem = sts[0]->hFdCngEnc->mem_coherence_fx; + mem_exp = sts[0]->hFdCngEnc->mem_coherence_exp; + FOR( i_subfr = 0; i_subfr < 2; i_subfr++ ) { - cr = ci = eL = eR = EPSILON; + cr = ci = eL = eR = EPSILON_FX; + move32(); + move32(); + move32(); + move32(); + cr_exp = ci_exp = eL_exp = eR_exp = 0; + move16(); + move16(); + move16(); + move16(); - cr += pt_fftL[0] * pt_fftR[0] + pt_fftL[L_FFT / 2] * pt_fftR[L_FFT / 2]; - eL += pt_fftL[0] * pt_fftL[0] + pt_fftL[L_FFT / 2] * pt_fftL[L_FFT / 2]; - eR += pt_fftR[0] * pt_fftR[0] + pt_fftR[L_FFT / 2] * pt_fftR[L_FFT / 2]; + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_add( L_mult( pt_fftL[0], pt_fftR[0] ), L_mult( pt_fftL[L_FFT / 2], pt_fftR[L_FFT / 2] ) ), shl( fft_exp, 1 ), &cr_exp ); + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_add( L_mult( pt_fftL[0], pt_fftL[0] ), L_mult( pt_fftL[L_FFT / 2], pt_fftL[L_FFT / 2] ) ), shl( fft_exp, 1 ), &eL_exp ); + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_add( L_mult( pt_fftR[0], pt_fftR[0] ), L_mult( pt_fftR[L_FFT / 2], pt_fftR[L_FFT / 2] ) ), shl( fft_exp, 1 ), &eR_exp ); - for ( i = 1; i < L_FFT / 2; i++ ) + FOR( i = 1; i < L_FFT / 2; i++ ) { - cr += pt_fftL[i] * pt_fftR[i] + pt_fftL[L_FFT - i] * pt_fftR[L_FFT - i]; - ci += -pt_fftL[i] * pt_fftR[L_FFT - i] + pt_fftR[i] * pt_fftL[L_FFT - i]; - eL += pt_fftL[i] * pt_fftL[i] + pt_fftL[L_FFT - i] * pt_fftL[L_FFT - i]; - eR += pt_fftR[i] * pt_fftR[i] + pt_fftR[L_FFT - i] * pt_fftR[L_FFT - i]; + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_add( L_mult( pt_fftL[i], pt_fftR[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &cr_exp ); + ci = BASOP_Util_Add_Mant32Exp( ci, ci_exp, L_add( L_mult( -pt_fftL[i], pt_fftR[L_FFT - i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[i] ) ), shl( fft_exp, 1 ), &ci_exp ); + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_add( L_mult( pt_fftL[i], pt_fftL[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftL[L_FFT - i] ) ), shl( fft_exp, 1 ), &eL_exp ); + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_add( L_mult( pt_fftR[i], pt_fftR[i] ), L_mult( pt_fftR[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &eR_exp ); } - - if ( sts[0]->ini_frame <= 50 || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) + test(); + test(); + IF( LE_32( sts[0]->ini_frame, 50 ) || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) { - mem[0] = 0.95f * mem[0] + 0.05f * cr; - mem[1] = 0.95f * mem[1] + 0.05f * ci; - mem[2] = 0.95f * mem[2] + 0.05f * eL; - mem[3] = 0.95f * mem[3] + 0.05f * eR; + mem[0] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[0], 31129 /*0.95f*/ ), mem_exp[0], Mpy_32_16_1( cr, 1638 /*0.05f*/ ), cr_exp, &mem_exp[0] ); + move32(); + mem[1] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[1], 31129 /*0.95f*/ ), mem_exp[1], Mpy_32_16_1( ci, 1638 /*0.05f*/ ), ci_exp, &mem_exp[1] ); + move32(); + mem[2] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[2], 31129 /*0.95f*/ ), mem_exp[2], Mpy_32_16_1( eL, 1638 /*0.05f*/ ), eL_exp, &mem_exp[2] ); + move32(); + mem[3] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[3], 31129 /*0.95f*/ ), mem_exp[3], Mpy_32_16_1( eR, 1638 /*0.05f*/ ), eR_exp, &mem_exp[3] ); + move32(); } pt_fftL += L_FFT; pt_fftR += L_FFT; } - sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = sqrtf( ( mem[0] * mem[0] + mem[1] * mem[1] ) / ( mem[2] * mem[3] ) ); - + Word16 sqr_inp, temp, sqr_out, sqr_inp_exp; + Word32 sqr_inp32 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( mem[0], mem[0] ), shl( mem_exp[0], 1 ), Mpy_32_32( mem[1], mem[1] ), shl( mem_exp[1], 1 ), &sqr_inp_exp ); + sqr_inp = BASOP_Util_Divide3232_Scale( sqr_inp32, Mpy_32_32( mem[2], mem[3] ), &temp ); + sqr_inp_exp = add( temp, sub( sqr_inp_exp, add( mem_exp[2], mem_exp[3] ) ) ); + sqr_out = Sqrt16( sqr_inp, &sqr_inp_exp ); + sts[0]->hFdCngEnc->hFdCngCom->coherence_fx = shl_sat( sqr_out, sqr_inp_exp ); // Q15 expected. + move16(); return; } +#else +void stereoFdCngCoherence( + Encoder_State **sts, /* i/o: core encoder structures */ + const int16_t last_element_mode, /* i : last element mode */ + float fft_buff[CPE_CHANNELS][2 * L_FFT] /* i : fft buffers for L and R channels */ +) +{ + const float *pt_fftL, *pt_fftR; + int16_t i_subfr, i; + float cr, ci, eL, eR; + float *mem; + if ( last_element_mode != IVAS_CPE_MDCT ) + { + set_f( sts[0]->hFdCngEnc->mem_coherence, EPSILON, 4 ); + } + + if ( sts[0]->core_brate == -1 || sts[1]->core_brate == -1 ) + { + /* case: at least one channel has triggered VAD -> ACTIVE FRAME */ + if ( sts[0]->core_brate == -1 ) + { + sts[1]->total_brate = sts[0]->total_brate; + sts[1]->active_cnt = sts[0]->active_cnt; + if ( sts[1]->active_cnt >= CNG_TYPE_HO ) + { + sts[1]->last_total_brate_cng = -1; + } + } + if ( sts[1]->core_brate == -1 ) + { + sts[0]->total_brate = sts[1]->total_brate; + sts[0]->active_cnt = sts[1]->active_cnt; + if ( sts[0]->active_cnt >= CNG_TYPE_HO ) + { + sts[0]->last_total_brate_cng = -1; + } + } + sts[0]->core_brate = -1; + sts[1]->core_brate = -1; + sts[0]->hDtxEnc->cnt_SID = 0; + sts[1]->hDtxEnc->cnt_SID = 0; + } + else if ( sts[0]->core_brate <= SID_2k40 && sts[1]->core_brate <= SID_2k40 ) + { + /* case: no VAD for both channels -> INACTIVE FRAME */ + reset_indices_enc( sts[0]->hBstr, sts[0]->hBstr->nb_ind_tot ); + + reset_indices_enc( sts[1]->hBstr, sts[1]->hBstr->nb_ind_tot ); + + /* synchronize SID sending for variable SID rate */ + if ( sts[0]->core_brate != sts[1]->core_brate ) + { + sts[0]->core_brate = SID_2k40; + sts[1]->core_brate = SID_2k40; + } + + /* synchronize SID counters */ + sts[0]->hDtxEnc->cnt_SID = min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID ); + sts[1]->hDtxEnc->cnt_SID = sts[0]->hDtxEnc->cnt_SID; + } + + pt_fftL = fft_buff[0]; + pt_fftR = fft_buff[1]; + mem = sts[0]->hFdCngEnc->mem_coherence; + + for ( i_subfr = 0; i_subfr < 2; i_subfr++ ) + { + cr = ci = eL = eR = EPSILON; + + cr += pt_fftL[0] * pt_fftR[0] + pt_fftL[L_FFT / 2] * pt_fftR[L_FFT / 2]; + eL += pt_fftL[0] * pt_fftL[0] + pt_fftL[L_FFT / 2] * pt_fftL[L_FFT / 2]; + eR += pt_fftR[0] * pt_fftR[0] + pt_fftR[L_FFT / 2] * pt_fftR[L_FFT / 2]; + + for ( i = 1; i < L_FFT / 2; i++ ) + { + cr += pt_fftL[i] * pt_fftR[i] + pt_fftL[L_FFT - i] * pt_fftR[L_FFT - i]; + ci += -pt_fftL[i] * pt_fftR[L_FFT - i] + pt_fftR[i] * pt_fftL[L_FFT - i]; + eL += pt_fftL[i] * pt_fftL[i] + pt_fftL[L_FFT - i] * pt_fftL[L_FFT - i]; + eR += pt_fftR[i] * pt_fftR[i] + pt_fftR[L_FFT - i] * pt_fftR[L_FFT - i]; + } + + if ( sts[0]->ini_frame <= 50 || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) + { + mem[0] = 0.95f * mem[0] + 0.05f * cr; + mem[1] = 0.95f * mem[1] + 0.05f * ci; + mem[2] = 0.95f * mem[2] + 0.05f * eL; + mem[3] = 0.95f * mem[3] + 0.05f * eR; + } + + pt_fftL += L_FFT; + pt_fftR += L_FFT; + } + + sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = sqrtf( ( mem[0] * mem[0] + mem[1] * mem[1] ) / ( mem[2] * mem[3] ) ); + + return; +} +#endif /*-------------------------------------------------------------------* * FdCngEncodeMDCTStereoSID() @@ -1148,6 +1340,325 @@ void stereoFdCngCoherence( * Encode DTX parameters and noise shapes into SID for MDCT-Stereo DTX *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void FdCngEncodeMDCTStereoSID_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ +) +{ + ENC_CORE_HANDLE sts[CPE_CHANNELS]; + Word16 indices[CPE_CHANNELS][FD_CNG_stages_37bits]; + Word16 gain_idx[CPE_CHANNELS]; + Word16 N, stages, ch, p, coh_idx; + Word32 *lr_in_ptr_fx[CPE_CHANNELS]; + Word16 lr_in_ptr_e[CPE_CHANNELS]; + Word32 *ms_ptr_fx[CPE_CHANNELS]; + Word16 ms_ptr_e; + Word32 *lr_out_ptr_fx[CPE_CHANNELS]; + Word16 lr_out_ptr_e[CPE_CHANNELS]; + Word32 logNoiseEst_fx[CPE_CHANNELS][NPART]; + Word32 E_fx[CPE_CHANNELS]; + Word32 gain_fx[CPE_CHANNELS]; + Word16 weights_fx[NPART]; + Word32 side_energy_fx; + Word16 Qside_energy; + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; /*24*18*/ + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; /* dynamically filled */ + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN], dct_target_fx[CPE_CHANNELS][FDCNG_VQ_DCT_MAXTRUNC]; /* 24 +2*18*/ + Word16 tmp, tmp_e; + Word16 no_side_flag; + Word16 is_inp_ms; + Word16 size_value, temp_e, gb, shift; + Word32 tmp32, t1, t2; + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf( hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst, hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst_fx, &hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst_fx_exp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst, hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst_fx, &hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst_fx_exp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEst, &hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEst, &hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->coherence_fx = float_to_fix16( hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->coherence_flt, Q15 ); +#endif + + is_inp_ms = 0; + move16(); + IF( EQ_16( hCPE->hCoreCoder[0]->cng_sba_flag, 1 ) ) + { + is_inp_ms = 1; + move16(); + } + + /* set pointers and initialize */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[ch] = hCPE->hCoreCoder[ch]; + lr_in_ptr_fx[ch] = &sts[ch]->hFdCngEnc->msNoiseEst_fx[0]; + lr_in_ptr_e[ch] = sts[ch]->hFdCngEnc->msNoiseEst_fx_exp; + ms_ptr_fx[ch] = &logNoiseEst_fx[ch][0]; + lr_out_ptr_fx[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0]; + lr_out_ptr_e[ch] = sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEstExp; + } + N = sts[0]->hFdCngEnc->npartDec; + move16(); + set16_fx( weights_fx, ONE_IN_Q8, NPART ); + + /* apply log and save energy of original left and right channels */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + // E[ch] = 0.0f; + E_fx[ch] = 0; + move32(); + FOR( p = 0; p < N; p++ ) + { + IF( lr_in_ptr_fx[ch][p] ) + { + t1 = BASOP_Util_Log2( lr_in_ptr_fx[ch][p] ); // Q25 + t2 = L_add( t1, L_shl( lr_in_ptr_e[ch], Q25 ) ); // Q25 + } + ELSE + { + t2 = 0; + move32(); + } + ms_ptr_fx[ch][p] = Mpy_32_32( t2, TEN_MULT_LOG10_2_IN_Q29 ); // Q23 + move32(); + E_fx[ch] = L_add( E_fx[ch], L_shr( ms_ptr_fx[ch][p], 4 ) ); // Q19 + move32(); + } + } + ms_ptr_e = Q31 - Q23; + move16(); + + /* M/S transform on log envelopes */ + IF( is_inp_ms == 0 ) + { + convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q30 ); // ms_ptr_e = Q23; + } + + gb = find_guarded_bits_fx( N ); + side_energy_fx = sum2_f_32_fx( ms_ptr_fx[1], N, gb ); + Qside_energy = sub( sub( shl( sub( 31, ms_ptr_e ), 1 ), 31 ), gb ); + + /* do not transmit side shape if initial noise shapes are very similar */ + IF( LE_32( side_energy_fx, L_shl( 214748365, sub( Qside_energy, Q31 ) ) ) ) + { + no_side_flag = 1; + move16(); + } + ELSE + { + no_side_flag = 0; + move16(); + } + + /* Quantize noise shapes */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + /* Normalize MSVQ input */ + gain_fx[ch] = 0; + move32(); + FOR( p = N_GAIN_MIN; p < N_GAIN_MAX; p++ ) + { + tmp32 = Mpy_32_32( ms_ptr_fx[ch][p], 165191050 ); // Q23 + gain_fx[ch] = L_add( gain_fx[ch], tmp32 ); // Q23 + move32(); + } + + FOR( p = 0; p < N; p++ ) + { + ms_ptr_fx[ch][p] = L_sub( ms_ptr_fx[ch][p], gain_fx[ch] ); + move32(); + } + } + + /* always split channel targetloop */ + + /* extend fdcng envelope from length 21 to a 24 length fdncg domain envelope signal */ + /* High quality cosine smooth basis extension used to not introduce noise in stage#1 DCT24 analysis and subsequent VQ-steps */ + IF( EQ_16( N, FDCNG_VQ_MAX_LEN_WB ) ) + { + size_value = BASOP_Util_Divide1616_Scale( sizeof( tmpRAM_fx ), ( sizeof( Word32 ) ), &temp_e ); /*Q15*/ + size_value = shr( size_value, sub( 15, temp_e ) ); + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N, FDCNG_VQ_DCT_MAXTRUNC, size_value ); // Q31 /*WB: create truncated IDCT21 matrix */ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + /* run DCT_N N==21 , truncated at 18/21 ~= 86% , i.e use a bit better better quality in extrapolation , than subsequent DCT24 analysis which is truncated at 75%*/ + /* truncated DCT 21 analysis */ + dctT2_N_apply_matrix_fx( (const Word32 *) ms_ptr_fx[ch], dct_target_fx[ch], FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); + /* extrapolate extend fdcng envelope signal in the fdncg ienvelope/"time" domain using DCT21 basis vectors, + estimated DCT21 coeffs scaling extended basis vectors are used to create extrapolated length 24 input target envelope signal */ + /* this DCT21 extension does not introduce DCT24 coefficient noise for the subsequent dct24 target analysis, and later in IDCT24 synthesis */ + + /* truncated IDCT 21 extension synthesis */ + extend_dctN_input_fx( ms_ptr_fx[ch], dct_target_fx[ch], N, tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx /* DCT_N basis vectors */, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ + + Copy32( tot_sig_ext_fx, ms_ptr_fx[ch], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ */ + } + } + + size_value = BASOP_Util_Divide1616_Scale( sizeof( tmpRAM_fx ), ( sizeof( Word32 ) ), &temp_e ); /*Q15*/ + size_value = shr( size_value, sub( 15, temp_e ) ); + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, size_value ); /*always create/set up IDCT24 matrix in RAM */ + + /* end split */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + /* MSVQ */ + IF( ch ) + { + stages = FD_CNG_JOINT_stages_25bits; + move16(); + } + ELSE + { + stages = FD_CNG_stages_37bits; + move16(); + } + + /* DCT24 domain compressed/truncated indices used for first stage */ + /* mid channel quantization using stages 1 through 6 */ + /* & side channel quantization using stages 1 through 4 */ + + { + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_fx[ch], ms_ptr_e, levels_37bits, FD_CNG_maxC_37bits, stages, weights_fx, N, FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[ch] ); + msvq_dec_fx( ivas_cdk_37bits_fx, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix_fx, ms_ptr_fx[ch], NULL, 7 ); + } + } + shift = find_guarded_bits_fx( N ); + ms_ptr_e = sub( 31, sub( 20, shift ) ); + + IF( no_side_flag ) + { + set32_fx( ms_ptr_fx[1], 0, N ); + } + + /* undo M/S */ + IF( is_inp_ms == 0 ) + { + convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q31 ); + } + + /* Compute gain against original left and right channels */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + gain_fx[ch] = 0; + move32(); + + tmp_e = 15; + move16(); + tmp = Inv16( N, &tmp_e ); + FOR( p = 0; p < N; p++ ) + { + gain_fx[ch] = L_add( gain_fx[ch], Mpy_32_16_1( ms_ptr_fx[ch][p], shl( tmp, tmp_e ) ) ); + move32(); + } + gain_fx[ch] = L_sub( L_shl( Mpy_32_16_1( E_fx[ch], shl( tmp, tmp_e ) ), Q23 - Q19 ), L_shl( gain_fx[ch], sub( ms_ptr_e, 8 ) ) ); // Q23 + move32(); + + apply_scale( &gain_fx[ch], sts[ch]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[ch]->element_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); + + /* quantize gain */ + gain_idx[ch] = (Word16) Mpy_32_32_r( L_add( gain_fx[ch], 251658240 ), 384 ); + move16(); + gain_idx[ch] = s_max( 0, s_min( 127, gain_idx[ch] ) ); + move16(); + + gain_fx[ch] = Mpy_32_16_1( L_shl( sub( gain_idx[ch], GAIN_Q_OFFSET_IVAS_FX_Q0 ), 23 ), 21845 ); // Q23 + move32(); + } + + /* restore channel noise envelopes */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + HANDLE_FD_CNG_ENC hFdCngEnc = sts[ch]->hFdCngEnc; + HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom; + + tmp_e = 0; + move16(); + Word32 pow; + + Word16 e_lr_out[NPART]; + + FOR( p = 0; p < N; p++ ) + { + pow = L_shl( gain_fx[ch], 8 - ms_ptr_e ); + pow = L_add( ms_ptr_fx[ch][p], pow ); + pow = Mpy_32_32( pow, 214748365 ); /*pow = 0.1*/ + lr_out_ptr_fx[ch][p] = BASOP_Util_fPow( 10, 31, pow, ms_ptr_e, &e_lr_out[p] ); + move32(); + tmp_e = s_max( tmp_e, e_lr_out[p] ); + } + + FOR( p = 0; p < N; p++ ) + { + lr_out_ptr_fx[ch][p] = L_shl( lr_out_ptr_fx[ch][p], e_lr_out[p] - tmp_e ); + move32(); + } + lr_out_ptr_e[ch] = tmp_e; + move32(); + + sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEstExp = tmp_e; + move16(); + + /* scale bands and get scalefactors */ + scalebands( lr_out_ptr_fx[ch], hFdCngEnc->partDec, N, hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, sub( hFdCngEnc->stopBandDec, hFdCngEnc->startBandDec ), hFdCngCom->cngNoiseLevel, 1 ); + hFdCngCom->cngNoiseLevelExp = lr_out_ptr_e[ch]; + move16(); + + lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac ); + + sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame; + } + + /* quantize channel coherence */ + coh_idx = mult_r( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx, 15 ); + coh_idx = max( 0, min( coh_idx, 15 ) ); + + /* ---- Write SID bitstream ---- */ + + + /* noise shapes and channel gains */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + IF( ch ) + { + stages = FD_CNG_JOINT_stages_25bits; + sts[ch]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + + /* side info */ + push_indice( sts[ch]->hBstr, IND_SID_TYPE, coh_idx, 4 ); + push_indice( sts[ch]->hBstr, IND_SID_TYPE, no_side_flag, 1 ); + } + ELSE + { + stages = FD_CNG_stages_37bits; + /* side info */ + push_indice( sts[ch]->hBstr, IND_SID_TYPE, 1, 1 ); + push_indice( sts[ch]->hBstr, IND_BWIDTH, sts[0]->bwidth, 2 ); + push_indice( sts[ch]->hBstr, IND_ACELP_16KHZ, sts[0]->L_frame == L_FRAME16k ? 1 : 0, 1 ); + } + + FOR( Word16 i = 0; i < stages; i++ ) + { + push_indice( sts[ch]->hBstr, IND_LSF, indices[ch][i], bits_37bits[i] ); + } + push_indice( sts[ch]->hBstr, IND_ENERGY, gain_idx[ch], 7 ); + } + + /* pad with zeros to reach common SID frame size */ + push_indice( sts[1]->hBstr, IND_ENERGY, 0, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC ); + +#ifdef IVAS_FLOAT_FIXED + me2f_buf( sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel, sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, FFTCLDFBLEN ); + me2f_buf( sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel, sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, FFTCLDFBLEN ); + me2f_buf( sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEst, sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, sts[0]->hFdCngEnc->npartDec ); + me2f_buf( sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEst, sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, sts[0]->hFdCngEnc->npartDec ); + sts[0]->preemph_fac_flt = fixedToFloat( sts[0]->preemph_fac, Q15 ); + sts[1]->preemph_fac_flt = fixedToFloat( sts[1]->preemph_fac, Q15 ); +#endif + + return; +} +#else void FdCngEncodeMDCTStereoSID( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ ) @@ -1164,10 +1675,19 @@ void FdCngEncodeMDCTStereoSID( int16_t gain_idx[CPE_CHANNELS]; int16_t N, stages, ch, p, coh_idx; float side_energy; +#ifdef IVAS_FLOAT_FIXED + Word32 *lr_out_ptr_fx[CPE_CHANNELS]; + Word32 gain_fx[CPE_CHANNELS]; + Word32 side_energy_fx; + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; /*24*18*/ + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; /* dynamically filled */ +#endif int16_t no_side_flag; int16_t is_inp_ms; - float tot_sig_ext[FDCNG_VQ_MAX_LEN], dct_target[CPE_CHANNELS][FDCNG_VQ_DCT_MAXTRUNC]; /* 24 +2*18*/ + float tot_sig_ext[FDCNG_VQ_MAX_LEN] /*, dct_target[CPE_CHANNELS][FDCNG_VQ_DCT_MAXTRUNC]*/; /* 24 +2*18*/ + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN], dct_target_fx[CPE_CHANNELS][FDCNG_VQ_DCT_MAXTRUNC]; /* 24 +2*18*/ float *invTrfMatrix; float tmpRAM[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; /*24*18*/ invTrfMatrix = (float *) tmpRAM; /* dynamically filled */ @@ -1186,6 +1706,9 @@ void FdCngEncodeMDCTStereoSID( lr_in_ptr[ch] = &sts[ch]->hFdCngEnc->msNoiseEst[0]; ms_ptr[ch] = &logNoiseEst[ch][0]; lr_out_ptr[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt[0]; +#ifdef IVAS_FLOAT_FIXED + lr_out_ptr_fx[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0]; +#endif } N = sts[0]->hFdCngEnc->npartDec; set_f( weights, 1.f, NPART ); @@ -1200,17 +1723,19 @@ void FdCngEncodeMDCTStereoSID( E[ch] += ms_ptr[ch][p]; } } - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 ms_ptr_fx[2][NPART]; + Word16 q = s_min( Q_factor_arrL( ms_ptr[0], N ), Q_factor_arrL( ms_ptr[1], N ) ) - 1; + floatToFixed_arrL( ms_ptr[0], ms_ptr_fx[0], q, N ); + floatToFixed_arrL( ms_ptr[1], ms_ptr_fx[1], q, N ); +#endif /* M/S transform on log envelopes */ if ( is_inp_ms == 0 ) { #ifndef IVAS_FLOAT_FIXED convertToMS( N, ms_ptr[0], ms_ptr[1], 0.5f ); #else - Word32 ms_ptr_fx[2][NPART]; - Word16 q = s_min( Q_factor_arrL( ms_ptr[0], N ), Q_factor_arrL( ms_ptr[1], N ) ) - 1; - floatToFixed_arrL( ms_ptr[0], ms_ptr_fx[0], q, N ); - floatToFixed_arrL( ms_ptr[1], ms_ptr_fx[1], q, N ); + convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q30 ); @@ -1218,8 +1743,15 @@ void FdCngEncodeMDCTStereoSID( fixedToFloat_arrL( ms_ptr_fx[1], ms_ptr[1], q, N ); #endif } - +#ifndef IVAS_FLOAT_FIXED side_energy = sum2_f( ms_ptr[1], N ); +#else + Word16 gb = find_guarded_bits_fx( N ); + side_energy_fx = sum2_f_32_fx( ms_ptr_fx[1], N, gb ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + side_energy = fixedToFloat( side_energy_fx, 2 * q - 31 - gb ); +#endif +#endif /* do not transmit side shape if initial noise shapes are very similar */ if ( side_energy <= 0.1f ) @@ -1253,27 +1785,68 @@ void FdCngEncodeMDCTStereoSID( /* High quality cosine smooth basis extension used to not introduce noise in stage#1 DCT24 analysis and subsequent VQ-steps */ if ( N == FDCNG_VQ_MAX_LEN_WB ) { - create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*WB: create truncated IDCT21 matrix */ +#ifdef IVAS_FLOAT_FIXED + Word16 size_value, temp_e; + size_value = BASOP_Util_Divide1616_Scale( sizeof( tmpRAM_fx ), ( sizeof( Word32 ) ), &temp_e ); /*Q15*/ + size_value = shr( size_value, sub( 15, temp_e ) ); + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N, FDCNG_VQ_DCT_MAXTRUNC, size_value ); // Q31 /*WB: create truncated IDCT21 matrix */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < FDCNG_VQ_MAX_LEN; i++ ) + { + fixedToFloat_arrL( tmpRAM_fx[i], tmpRAM[i], Q31, FDCNG_VQ_DCT_MAXTRUNC ); + } + q = s_min( Q_factor_arrL( ms_ptr[0], N ), Q_factor_arrL( ms_ptr[1], N ) ) - 1; + floatToFixed_arrL( ms_ptr[0], ms_ptr_fx[0], q, N ); + floatToFixed_arrL( ms_ptr[1], ms_ptr_fx[1], q, N ); +#endif +#else + create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*WB: create truncated IDCT21 matrix */ +#endif for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { /* run DCT_N N==21 , truncated at 18/21 ~= 86% , i.e use a bit better better quality in extrapolation , than subsequent DCT24 analysis which is truncated at 75%*/ +#ifdef IVAS_FLOAT_FIXED + /* truncated DCT 21 analysis */ + dctT2_N_apply_matrix_fx( (const Word32 *) ms_ptr_fx[ch], dct_target_fx[ch], FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); + /* extrapolate extend fdcng envelope signal in the fdncg ienvelope/"time" domain using DCT21 basis vectors, + estimated DCT21 coeffs scaling extended basis vectors are used to create extrapolated length 24 input target envelope signal */ + /* this DCT21 extension does not introduce DCT24 coefficient noise for the subsequent dct24 target analysis, and later in IDCT24 synthesis */ + /* truncated IDCT 21 extension synthesis */ + extend_dctN_input_fx( ms_ptr_fx[ch], dct_target_fx[ch], N, tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx /* DCT_N basis vectors */, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( tot_sig_ext_fx, tot_sig_ext, q, FDCNG_VQ_MAX_LEN ); +#endif +#else /* truncated DCT 21 analysis */ dctT2_N_apply_matrix( (const float *) ms_ptr[ch], dct_target[ch], FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); - /* extrapolate extend fdcng envelope signal in the fdncg ienvelope/"time" domain using DCT21 basis vectors, estimated DCT21 coeffs scaling extended basis vectors are used to create extrapolated length 24 input target envelope signal */ /* this DCT21 extension does not introduce DCT24 coefficient noise for the subsequent dct24 target analysis, and later in IDCT24 synthesis */ /* truncated IDCT 21 extension synthesis */ extend_dctN_input( ms_ptr[ch], dct_target[ch], N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix /* DCT_N basis vectors */, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ +#endif + mvr2r( tot_sig_ext, ms_ptr[ch], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ */ } } - create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*always create/set up IDCT24 matrix in RAM */ - +#ifdef IVAS_FLOAT_FIXED + Word16 size_value, temp_e; + size_value = BASOP_Util_Divide1616_Scale( sizeof( tmpRAM_fx ), ( sizeof( Word32 ) ), &temp_e ); /*Q15*/ + size_value = shr( size_value, sub( 15, temp_e ) ); + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, size_value ); /*always create/set up IDCT24 matrix in RAM */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < FDCNG_VQ_MAX_LEN; i++ ) + { + fixedToFloat_arrL( tmpRAM_fx[i], tmpRAM[i], Q31, FDCNG_VQ_DCT_MAXTRUNC ); + } +#endif +#else + create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*always create/set up IDCT24 matrix in RAM */ +#endif /* end split */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -1292,8 +1865,29 @@ void FdCngEncodeMDCTStereoSID( /* & side channel quantization using stages 1 through 4 */ { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ms_ptr_e; + Word16 weights_fx[24]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; + + f2me_buf( ms_ptr[ch], ms_ptr_fx[ch], &ms_ptr_e, N ); + floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + floatToFixed_arr( weights, weights_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_fx[ch], ms_ptr_e, levels_37bits, FD_CNG_maxC_37bits, stages, weights_fx, N, FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[ch] ); + msvq_dec_fx( ivas_cdk_37bits_fx, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix_fx, ms_ptr_fx[ch], NULL, 7 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + Word16 shift = find_guarded_bits_fx( N ); + ms_ptr_e = 31 - ( 20 - shift ); + me2f_buf( ms_ptr_fx[ch], ms_ptr_e, ms_ptr[ch], N ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[ch], levels_37bits, FD_CNG_maxC_37bits, stages, weights, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[ch] ); msvq_dec_float( cdk_37bits_ivas, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix, ms_ptr[ch], NULL ); +#endif } } @@ -1308,15 +1902,17 @@ void FdCngEncodeMDCTStereoSID( #ifndef IVAS_FLOAT_FIXED convertToMS( N, ms_ptr[0], ms_ptr[1], 1.0f ); #else - Word32 ms_ptr_fx[2][NPART]; - Word16 q = s_min( Q_factor_arrL( ms_ptr[0], N ), Q_factor_arrL( ms_ptr[1], N ) ) - 1; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Word32 ms_ptr_fx[2][NPART]; + q = s_min( Q_factor_arrL( ms_ptr[0], N ), Q_factor_arrL( ms_ptr[1], N ) ) - 1; floatToFixed_arrL( ms_ptr[0], ms_ptr_fx[0], q, N ); floatToFixed_arrL( ms_ptr[1], ms_ptr_fx[1], q, N ); - +#endif convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q31 ); - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS fixedToFloat_arrL( ms_ptr_fx[0], ms_ptr[0], q, N ); fixedToFloat_arrL( ms_ptr_fx[1], ms_ptr[1], q, N ); +#endif #endif } @@ -1329,8 +1925,18 @@ void FdCngEncodeMDCTStereoSID( gain[ch] += ms_ptr[ch][p]; } gain[ch] = ( E[ch] - gain[ch] ) / (float) N; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + gain_fx[ch] = floatToFixed_32( gain[ch], Q23 ); +#endif + apply_scale( &gain_fx[ch], sts[ch]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[ch]->element_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + gain[ch] = fixedToFloat_32( gain_fx[ch], Q23 ); +#endif +#else apply_scale_flt( &gain[ch], sts[ch]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[ch]->element_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); +#endif /* quantize gain */ gain_idx[ch] = (int16_t) floor( gain[ch] * 1.5f + GAIN_Q_OFFSET_IVAS + .5f ); gain_idx[ch] = max( 0, min( 127, gain_idx[ch] ) ); @@ -1349,11 +1955,27 @@ void FdCngEncodeMDCTStereoSID( lr_out_ptr[ch][p] = powf( 10.f, ( ms_ptr[ch][p] + gain[ch] ) / 10.f ); } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q = Q_factor_arrL( lr_out_ptr[ch], N ); + floatToFixed_arrL( lr_out_ptr[ch], lr_out_ptr_fx[ch], q, N ); +#endif + /* scale bands and get scalefactors */ + scalebands( lr_out_ptr_fx[ch], hFdCngEnc->partDec, N, hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, sub( hFdCngEnc->stopBandDec, hFdCngEnc->startBandDec ), hFdCngCom->cngNoiseLevel, 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( hFdCngCom->cngNoiseLevel, hFdCngCom->cngNoiseLevel_flt, q, FFTCLDFBLEN ); +#endif + lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + sts[ch]->preemph_fac_flt = fixedToFloat( sts[ch]->preemph_fac, Q15 ); +#endif +#else /* scale bands and get scalefactors */ scalebands_flt( lr_out_ptr[ch], hFdCngEnc->partDec, N, hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, hFdCngEnc->stopBandDec - hFdCngEnc->startBandDec, hFdCngCom->cngNoiseLevel_flt, 1 ); - lpc_from_spectrum_flt( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac_flt ); +#endif + sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame; } @@ -1398,7 +2020,7 @@ void FdCngEncodeMDCTStereoSID( return; } - +#endif /*-------------------------------------------------------------------* * FdCngEncodeDiracMDCTStereoSID() @@ -1407,6 +2029,250 @@ void FdCngEncodeMDCTStereoSID( * together with Dirac *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void FdCngEncodeDiracMDCTStereoSID_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ +) +{ + ENC_CORE_HANDLE sts[CPE_CHANNELS]; + Word32 *lr_in_ptr_fx[CPE_CHANNELS]; + Word16 lr_in_ptr_e[CPE_CHANNELS]; + Word32 *ms_ptr_fx[CPE_CHANNELS]; + Word16 ms_ptr_e; + Word32 *lr_out_ptr_fx[CPE_CHANNELS]; + Word16 lr_out_ptr_e[CPE_CHANNELS]; + Word32 logNoiseEst_fx[CPE_CHANNELS][NPART]; + Word32 E_fx[CPE_CHANNELS]; + Word32 gain_fx[CPE_CHANNELS]; + Word16 weights_fx[NPART]; + Word16 N[CPE_CHANNELS]; + Word16 indices[CPE_CHANNELS][FD_CNG_stages_37bits]; + Word16 gain_idx[CPE_CHANNELS]; + Word16 ch, p; + Word16 tmp, tmp_e, shift; + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; /* dynamically filled */ + Word32 t1, t2, tmp32; + /* set pointers and initialize */ + + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf( hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst, hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst_fx, &hCPE->hCoreCoder[0]->hFdCngEnc->msNoiseEst_fx_exp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst, hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst_fx, &hCPE->hCoreCoder[1]->hFdCngEnc->msNoiseEst_fx_exp, hCPE->hCoreCoder[1]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEst, &hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, hCPE->hCoreCoder[0]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEst, &hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, hCPE->hCoreCoder[1]->hFdCngEnc->npartDec ); + f2me_buf( hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel, &hCPE->hCoreCoder[0]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, FFTCLDFBLEN ); + f2me_buf( hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel, &hCPE->hCoreCoder[1]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, FFTCLDFBLEN ); +#endif + + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[ch] = hCPE->hCoreCoder[ch]; + N[ch] = sts[ch]->hFdCngEnc->npartDec; + lr_in_ptr_fx[ch] = &sts[ch]->hFdCngEnc->msNoiseEst_fx[0]; + lr_in_ptr_e[ch] = sts[ch]->hFdCngEnc->msNoiseEst_fx_exp; + ms_ptr_fx[ch] = &logNoiseEst_fx[ch][0]; + lr_out_ptr_fx[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0]; + lr_out_ptr_e[ch] = sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEstExp; + move16(); + } + set16_fx( weights_fx, ONE_IN_Q8, NPART ); + + /* apply log and save energy of original left and right channels */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + // E[ch] = 0.0f; + E_fx[ch] = 0; + move32(); + FOR( p = 0; p < N[ch]; p++ ) + { + t1 = BASOP_Util_Log2( lr_in_ptr_fx[ch][p] + EPSILLON_FX ); // Q25 + t2 = L_add( t1, L_shl( lr_in_ptr_e[ch], Q25 ) ); // Q25 + ms_ptr_fx[ch][p] = Mpy_32_32( t2, TEN_MULT_LOG10_2_IN_Q29 ); // Q23 + move32(); + E_fx[ch] = L_add( E_fx[ch], L_shr( ms_ptr_fx[ch][p], 5 ) ); // Q18 + move32(); + } + } + ms_ptr_e = Q31 - Q23; + move16(); + + /* M/S transform on log envelopes */ + convertToMS_fx( N[0], ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q30 ); + E_fx[0] = 0; + move32(); + FOR( p = 0; p < N[0]; p++ ) + { + E_fx[0] = L_add( E_fx[0], L_shr( ms_ptr_fx[0][p], 5 ) ); // Q18 + move32(); + } + + /* Quantize M noise shape */ + /* Normalize MSVQ input */ + gain_fx[0] = 0; + move16(); + FOR( p = N_GAIN_MIN; p < N_GAIN_MAX; p++ ) + { + tmp32 = Mpy_32_32( ms_ptr_fx[0][p], 165191050 ); // Q23 + gain_fx[0] = L_add( gain_fx[0], tmp32 ); // Q23 + move32(); + } + + FOR( p = 0; p < N[0]; p++ ) + { + ms_ptr_fx[0][p] = L_sub( ms_ptr_fx[0][p], gain_fx[0] ); + move32(); + } + + + /* MSVQ */ + /* DCT domain compressed/truncated indices used for first stage */ + /* mid quantization using stages #1 through 6 */ + scale_sig32( ms_ptr_fx[0], N[0], -6 ); + ms_ptr_e = add( ms_ptr_e, 6 ); + move16(); + IF( EQ_16( N[0], FDCNG_VQ_MAX_LEN_WB ) ) + { + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N[0], FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM_fx ) / ( sizeof( Word32 ) ) ); + /* truncated DCT 21 analysis */ + dctT2_N_apply_matrix_fx( (const Word32 *) ms_ptr_fx[0], dct_target_fx, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); + /* truncated IDCT21 extension to 24 synthesis */ + + extend_dctN_input_fx( ms_ptr_fx[0], dct_target_fx, N[0], tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ + + Copy32( tot_sig_ext_fx, ms_ptr_fx[0], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ + } + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM_fx ) / ( sizeof( Word32 ) ) ); + + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_fx[0], ms_ptr_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights_fx, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[0] ); + msvq_dec_fx( ivas_cdk_37bits_fx, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix_fx, ms_ptr_fx[0], NULL, 7 ); + shift = find_guarded_bits_fx( N[0] ); + ms_ptr_e = sub( 31, sub( 20, shift ) ); + scale_sig32( ms_ptr_fx[1], N[1], sub( 8, ms_ptr_e ) ); + + /* set S to zero */ + set32_fx( ms_ptr_fx[1], 0, NPART ); + + /* compute M gain */ + gain_fx[0] = 0; + move32(); + tmp_e = 15; + move16(); + tmp = Inv16( N[0], &tmp_e ); + FOR( p = 0; p < N[0]; p++ ) + { + gain_fx[0] = L_add( gain_fx[0], Mpy_32_16_1( ms_ptr_fx[0][p], shl( tmp, tmp_e ) ) ); + move32(); + } + gain_fx[0] = L_sub( L_shl( Mpy_32_16_1( E_fx[0], shl( tmp, tmp_e ) ), Q23 - Q18 ), L_shl( gain_fx[0], ms_ptr_e - 8 ) ); // Q23 + move32(); + + apply_scale( &gain_fx[0], sts[0]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[0]->hDtxEnc->last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); + + /* quantize gain */ + gain_idx[0] = extract_l( Mpy_32_32_r( L_add( gain_fx[0], 251658240 ), 384 ) ); + move16(); + gain_idx[0] = s_max( 0, s_min( 127, gain_idx[0] ) ); + move16(); + + gain_fx[0] = Mpy_32_16_1( L_shl( sub( gain_idx[0], GAIN_Q_OFFSET_IVAS_FX_Q0 ), 23 ), 21845 ); // Q23 + move32(); + gain_fx[1] = gain_fx[0]; // Q23 + move32(); + + /* undo M/S */ + convertToMS_fx( NPART, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q31 ); + + /* restore channel noise envelopes */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + HANDLE_FD_CNG_ENC hFdCngEnc = sts[ch]->hFdCngEnc; + HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom; + + Word32 pow; + Word16 e_lr_out[NPART]; + tmp_e = -MAX_16; + FOR( p = 0; p < N[ch]; p++ ) + { + pow = L_shl( gain_fx[ch], sub( 8, ms_ptr_e ) ); + pow = L_add( ms_ptr_fx[ch][p], pow ); + pow = Mpy_32_32( pow, 214748365 ); /*pow = 0.1*/ + lr_out_ptr_fx[ch][p] = BASOP_Util_fPow( 10, 31, pow, ms_ptr_e, &e_lr_out[p] ); + tmp_e = s_max( tmp_e, e_lr_out[p] ); + } + + FOR( p = 0; p < N[ch]; p++ ) + { + lr_out_ptr_fx[ch][p] = L_shl( lr_out_ptr_fx[ch][p], sub( e_lr_out[p], tmp_e ) ); // Q(31 - tmp_e) + } + + sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEstExp = tmp_e; + move16(); + lr_out_ptr_e[ch] = tmp_e; + move16(); + + /* NB last band energy compensation */ + IF( hFdCngCom->CngBandwidth == NB ) + { + lr_out_ptr_fx[ch][N[ch] - 1] = Mpy_32_16_1( lr_out_ptr_fx[ch][N[ch] - 1], NB_LAST_BAND_SCALE ); + move32(); + } + ELSE IF( hFdCngCom->CngBandwidth == SWB && LE_32( hFdCngCom->CngBitrate, ACELP_13k20 ) ) + { + lr_out_ptr_fx[ch][N[ch] - 1] = Mpy_32_16_1( lr_out_ptr_fx[ch][N[ch] - 1], SWB_13k2_LAST_BAND_SCALE ); + move32(); + } + /* scale bands and get scalefactors */ + scalebands( lr_out_ptr_fx[ch], hFdCngEnc->partDec, N[ch], hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, sub( hFdCngEnc->stopBandDec, hFdCngEnc->startBandDec ), hFdCngCom->cngNoiseLevel, 1 ); + hFdCngCom->cngNoiseLevelExp = lr_out_ptr_e[ch]; + move16(); + lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac ); + sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame; + } + sts[0]->hFdCngEnc->hFdCngCom->coherence_fx = 0; + move16(); + sts[1]->hFdCngEnc->hFdCngCom->coherence_fx = 0; + move16(); + + /* ---- Write SID bitstream ---- */ + + /* side info */ + push_indice( sts[0]->hBstr, IND_SID_TYPE, 1, 1 ); + push_indice( sts[0]->hBstr, IND_BWIDTH, sts[0]->bwidth, 2 ); + IF( EQ_16( sts[0]->L_frame, L_FRAME16k ) ) + { + push_indice( sts[0]->hBstr, IND_ACELP_16KHZ, 1, 1 ); + } + ELSE + { + push_indice( sts[0]->hBstr, IND_ACELP_16KHZ, 0, 1 ); + } + + /* noise shapes and channel gains */ + FOR( Word16 i = 0; i < FD_CNG_stages_37bits; i++ ) + { + push_indice( sts[0]->hBstr, IND_LSF, indices[0][i], bits_37bits[i] ); + } + push_indice( sts[0]->hBstr, IND_ENERGY, gain_idx[0], 7 ); + +#ifdef IVAS_FLOAT_FIXED + me2f_buf( sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel, sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, sts[0]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, FFTCLDFBLEN ); + me2f_buf( sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel, sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevelExp, sts[1]->hFdCngEnc->hFdCngCom->cngNoiseLevel_flt, FFTCLDFBLEN ); + me2f_buf( sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEst, sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, sts[0]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, sts[0]->hFdCngEnc->npartDec ); + me2f_buf( sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEst, sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEstExp, sts[1]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt, sts[1]->hFdCngEnc->npartDec ); + sts[0]->preemph_fac_flt = fixedToFloat( sts[0]->preemph_fac, Q15 ); + sts[1]->preemph_fac_flt = fixedToFloat( sts[1]->preemph_fac, Q15 ); + sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = fixedToFloat( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx, Q15 ); + sts[1]->hFdCngEnc->hFdCngCom->coherence_flt = fixedToFloat( sts[1]->hFdCngEnc->hFdCngCom->coherence_fx, Q15 ); +#endif + + return; +} +#else void FdCngEncodeDiracMDCTStereoSID( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure */ ) @@ -1415,6 +2281,9 @@ void FdCngEncodeDiracMDCTStereoSID( float *lr_in_ptr[CPE_CHANNELS]; float *ms_ptr[CPE_CHANNELS]; float *lr_out_ptr[CPE_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word32 *lr_out_ptr_fx[CPE_CHANNELS]; +#endif float logNoiseEst[CPE_CHANNELS][NPART]; float E[CPE_CHANNELS]; float gain[CPE_CHANNELS]; @@ -1428,6 +2297,7 @@ void FdCngEncodeDiracMDCTStereoSID( float dct_target[FDCNG_VQ_DCT_MAXTRUNC]; float tot_sig_ext[FDCNG_VQ_MAX_LEN]; invTrfMatrix = (float *) tmpRAM; /* dynamically filled */ + // assert(0); /* set pointers and initialize */ for ( ch = 0; ch < CPE_CHANNELS; ch++ ) @@ -1437,6 +2307,9 @@ void FdCngEncodeDiracMDCTStereoSID( lr_in_ptr[ch] = &sts[ch]->hFdCngEnc->msNoiseEst[0]; ms_ptr[ch] = &logNoiseEst[ch][0]; lr_out_ptr[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst_flt[0]; +#ifdef IVAS_FLOAT_FIXED + lr_out_ptr_fx[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0]; +#endif } set_f( weights, 1.f, NPART ); @@ -1481,20 +2354,73 @@ void FdCngEncodeDiracMDCTStereoSID( /* MSVQ */ /* DCT domain compressed/truncated indices used for first stage */ /* mid quantization using stages #1 through 6 */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; /* dynamically filled */ + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word16 ms_ptr_e; + Word32 tot_sig_ext_fx[FDCNG_VQ_MAX_LEN]; + + f2me_buf( ms_ptr[0], ms_ptr_fx[0], &ms_ptr_e, FDCNG_VQ_DCT_MAXTRUNC ); + scale_sig32( ms_ptr_fx[0], FDCNG_VQ_DCT_MAXTRUNC, -5 ); // gaurd bits + ms_ptr_e += 5; + +#endif if ( N[0] == FDCNG_VQ_MAX_LEN_WB ) { +#ifdef IVAS_FLOAT_FIXED + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, N[0], FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM_fx ) / ( sizeof( Word32 ) ) ); +#else create_IDCT_N_Matrix( invTrfMatrix, N[0], FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); +#endif /* truncated DCT 21 analysis */ +#ifdef IVAS_FLOAT_FIXED + dctT2_N_apply_matrix_fx( (const Word32 *) ms_ptr_fx[0], dct_target_fx, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); +#else dctT2_N_apply_matrix( (const float *) ms_ptr[0], dct_target, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX ); +#endif /* truncated IDCT21 extension to 24 synthesis */ + +#ifdef IVAS_FLOAT_FIXED + extend_dctN_input_fx( ms_ptr_fx[0], dct_target_fx, N[0], tot_sig_ext_fx, FDCNG_VQ_MAX_LEN, invTrfMatrix_fx, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ +#else extend_dctN_input( ms_ptr[0], dct_target, N[0], tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/ +#endif mvr2r( tot_sig_ext, ms_ptr[0], FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ } +#ifdef IVAS_FLOAT_FIXED + create_IDCT_N_Matrix_fx( invTrfMatrix_fx, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( Word32 ) ) ); +#else create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf( dct_target_fx, ms_ptr_e, dct_target, FDCNG_VQ_DCT_MAXTRUNC ); + me2f_buf( tot_sig_ext_fx, ms_ptr_e, tot_sig_ext, FDCNG_VQ_MAX_LEN ); + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); +#endif + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 weights_fx[24]; + + floatToFixed_arr( weights, weights_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_fx[0], ms_ptr_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights_fx, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[0] ); + msvq_dec_fx( ivas_cdk_37bits_fx, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix_fx, ms_ptr_fx[0], NULL, 7 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 shift = find_guarded_bits_fx( N[0] ); + ms_ptr_e = 31 - ( 20 - shift ); + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + me2f_buf( ms_ptr_fx[0], ms_ptr_e, ms_ptr[0], FDCNG_VQ_DCT_MAXTRUNC ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[0], levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[0] ); msvq_dec_float( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix, ms_ptr[0], NULL ); +#endif /* set S to zero */ @@ -1503,7 +2429,17 @@ void FdCngEncodeDiracMDCTStereoSID( /* compute M gain */ gain[0] = sum_f( ms_ptr[0], N[0] ); gain[0] = ( E[0] - gain[0] ) / (float) N[0]; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 gain_fx = floatToFixed( gain[0], Q23 ); +#endif + apply_scale( &gain_fx, sts[0]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[0]->hDtxEnc->last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + gain[0] = fixedToFloat( gain_fx, Q23 ); +#endif +#else apply_scale_flt( &gain[0], sts[0]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[0]->hDtxEnc->last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); +#endif /* quantize gain */ gain_idx[0] = (int16_t) floor( gain[0] * 1.5f + GAIN_Q_OFFSET_IVAS + .5f ); @@ -1546,12 +2482,26 @@ void FdCngEncodeDiracMDCTStereoSID( { lr_out_ptr[ch][N[ch] - 1] *= SWB_13k2_LAST_BAND_SCALE_FLT; } - +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q = Q_factor_arrL( lr_out_ptr[ch], N[ch] ); + floatToFixed_arrL( lr_out_ptr[ch], lr_out_ptr_fx[ch], q, N[ch] ); +#endif + /* scale bands and get scalefactors */ + scalebands( lr_out_ptr_fx[ch], hFdCngEnc->partDec, N[ch], hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, sub( hFdCngEnc->stopBandDec, hFdCngEnc->startBandDec ), hFdCngCom->cngNoiseLevel, 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( hFdCngCom->cngNoiseLevel, hFdCngCom->cngNoiseLevel_flt, q, FFTCLDFBLEN ); +#endif + lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + sts[ch]->preemph_fac_flt = fixedToFloat( sts[ch]->preemph_fac, Q15 ); +#endif +#else /* scale bands and get scalefactors */ scalebands_flt( lr_out_ptr[ch], hFdCngEnc->partDec, N[ch], hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, hFdCngEnc->stopBandDec - hFdCngEnc->startBandDec, hFdCngCom->cngNoiseLevel_flt, 1 ); lpc_from_spectrum_flt( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac_flt ); - +#endif sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame; } sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = 0.0f; @@ -1573,3 +2523,4 @@ void FdCngEncodeDiracMDCTStereoSID( return; } +#endif diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index 33f693d4b0ea22a9d2ea1f7e1e3c71582d9a1afc..8ef56f72fd37cb8c210377ed7437c3a45cb15cbc 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -30,6 +30,7 @@ y = u__p; \ } #endif +extern void BASOP_getTables( const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *psin_step, Word16 length ); /************************************* * Create an instance of type FD_CNG * @@ -133,6 +134,8 @@ void initFdCngEnc_fx( HANDLE_FD_CNG_ENC hsEnc, Word32 input_Fs, Word16 scale ) hsEnc->msPeriodogBufPtr = 0; move16(); set32_fx( hsEnc->msPsdSecondMoment_fx, 0, NPART ); + set32_fx( hsEnc->mem_coherence_fx, EPSILON_FX, 4 ); + set16_fx( hsEnc->mem_coherence_exp, 0, 4 ); return; @@ -264,6 +267,150 @@ void configureFdCngEnc_fx( HANDLE_FD_CNG_ENC hsEnc, /* i/o: Contains the variabl hsCom->frameSize = shr( hsCom->fftlen, 1 ); } +void configureFdCngEnc_ivas_fx( + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: Contains the variables related to the FD-based CNG process */ + const Word16 bwidth, + const Word32 total_brate ) +{ + HANDLE_FD_CNG_COM hsCom = hFdCngEnc->hFdCngCom; + Word16 psizeDec[NPART]; + Word16 psizeDec_norm[NPART]; + Word16 psizeDec_norm_exp; + Word16 psize_invDec[NPART]; + + set16_fx( psizeDec, 0, NPART ); + + hsCom->CngBandwidth = bwidth; + move16(); + IF( EQ_16( hsCom->CngBandwidth, FB ) ) + { + hsCom->CngBandwidth = SWB; + move16(); + } + hsCom->CngBitrate = total_brate; + move32(); + + /* NB configuration */ + IF( EQ_16( bwidth, NB ) ) + { + hsCom->FdCngSetup = FdCngSetup_nb; /* PTR assignation -> no move needed*/ + } + + /* WB configuration */ + ELSE IF( EQ_16( bwidth, WB ) ) + { + /* FFT 6.4kHz, no CLDFB */ + IF( LE_32( total_brate, ACELP_8k00 ) ) + { + hsCom->FdCngSetup = FdCngSetup_wb1; + } + /* FFT 6.4kHz, CLDFB 8.0kHz */ + ELSE IF( LE_32( total_brate, ACELP_13k20 ) ) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + } + /* FFT 8.0kHz, no CLDFB */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_wb3; + } + } + + /* SWB/FB configuration */ + ELSE + { + /* FFT 6.4kHz, CLDFB 14kHz */ + IF( LE_32( total_brate, ACELP_13k20 ) ) + { + hsCom->FdCngSetup = FdCngSetup_swb1; + } + /* FFT 8.0kHz, CLDFB 16kHz */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_swb2; + } + } + hsCom->fftlen = hsCom->FdCngSetup.fftlen; + move16(); + hFdCngEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin; + move16(); + + /* Configure the SID quantizer and the Confort Noise Generator */ + + hFdCngEnc->startBandDec = hsCom->startBand; + move16(); + hFdCngEnc->stopBandDec = add( hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions - 1], 1 ); + move16(); + initPartitions( hsCom->FdCngSetup.sidPartitions, + hsCom->FdCngSetup.numPartitions, + hFdCngEnc->startBandDec, + hFdCngEnc->stopBandDec, + hFdCngEnc->partDec, + &hFdCngEnc->npartDec, + hFdCngEnc->midbandDec, + psizeDec, + psizeDec_norm, + &psizeDec_norm_exp, + psize_invDec, + 0 ); + IF( EQ_16( hFdCngEnc->stopFFTbinDec, 160 ) ) + { + hFdCngEnc->nFFTpartDec = 17; + move16(); + } + ELSE IF( EQ_16( hFdCngEnc->stopFFTbinDec, 256 ) ) + { + hFdCngEnc->nFFTpartDec = 20; + move16(); + } + ELSE + { + hFdCngEnc->nFFTpartDec = 21; + move16(); + } + + SWITCH( hsCom->fftlen ) + { + case 512: +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hsCom->fftSineTab_flt = NULL; + hsCom->olapWinAna_flt = olapWinAna512; + hsCom->olapWinSyn_flt = olapWinSyn256; +#endif + hsCom->fftSineTab_fx = NULL; + hsCom->olapWinAna_fx = olapWinAna512_fx; + hsCom->olapWinSyn_fx = olapWinSyn256_fx; + hsCom->fftlenShift = 8; + move16(); + hsCom->fftlenFac = 32767 /*1.0 Q15*/; + move16(); + BREAK; + case 640: +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hsCom->fftSineTab_flt = fftSineTab640; + hsCom->olapWinAna_flt = olapWinAna640; + hsCom->olapWinSyn_flt = olapWinSyn320; +#endif + hsCom->fftSineTab_fx = fftSineTab640_fx; + hsCom->olapWinAna_fx = olapWinAna640_fx; + hsCom->olapWinSyn_fx = olapWinSyn320_fx; + hsCom->fftlenShift = 9; + move16(); + hsCom->fftlenFac = 20480 /*0.625 Q15*/; + move16(); + BREAK; + default: + assert( !"Unsupported FFT length for FD-based CNG" ); + BREAK; + } + BASOP_getTables( &hsCom->olapWinAna, NULL, NULL, shr( hsCom->fftlen, 1 ) ); + BASOP_getTables( &hsCom->olapWinSyn, NULL, NULL, shr( hsCom->fftlen, 2 ) ); + hsCom->frameSize = shr( hsCom->fftlen, 1 ); + move16(); + + return; +} + /************************************** * Delete the instance of type FD_CNG * **************************************/ @@ -1545,80 +1692,573 @@ void generate_comfort_noise_enc_fx( Encoder_State *stcod, } } -/*-------------------------------------------------------------------* - * cng_energy_fx() - * - * - *-------------------------------------------------------------------*/ - -/*! r: CNG energy */ -Word16 cng_energy_fx( - const Word16 element_mode, /* i : element mode */ - const Word16 bwidth, /* i : audio bandwidh */ - const Word16 CNG_mode, /* i : mode for DTX configuration */ - const Word16 CNG_att, /* i : attenuation factor for CNG */ - const Word16 *exc, /* i : input signal */ - const Word16 len, /* i : vector length */ - const Word16 Q_new /* i : Input scaling */ -) +#ifdef IVAS_FLOAT_FIXED +void generate_comfort_noise_enc_ivas_fx( Encoder_State *stcod, + Word16 Q_new, + Word16 gen_exc ) { - Word16 i, maxv, scale; - Word16 hi, lo, enr, tmp16, att; - const Word16 *pt_res; - Word32 L_ener, L_tmp; + Word16 i, s, sn, cnt; + Word16 startBand2; + Word16 stopFFTbin2; + Word16 preemph_fac; + Word32 sqrtNoiseLevel; + Word16 randGaussExp; + Word16 fftBufferExp; + Word16 cngNoiseLevelExp; + Word16 *seed; + Word16 *timeDomainOutput; + Word32 *ptr_r, *ptr_i; + Word32 *cngNoiseLevel; + Word32 *ptr_level; + Word32 *fftBuffer; + Word16 old_syn_pe_tmp[16]; + Word16 tcx_transition = 0; + move16(); + HANDLE_FD_CNG_ENC stenc = stcod->hFdCngEnc; + HANDLE_FD_CNG_COM st = stenc->hFdCngCom; + DTX_ENC_HANDLE hDtxEnc = stcod->hDtxEnc; + TD_CNG_ENC_HANDLE hTdCngEnc = stcod->hTdCngEnc; - maxv = 0; + LPD_state_HANDLE hLPDmem = stcod->hLPDmem; + TCX_ENC_HANDLE hTcxEnc = stcod->hTcxEnc; + + /* Warning fix */ + s = 0; move16(); - FOR( i = 0; i < len; i++ ) + + /* pointer initialization */ + + cngNoiseLevel = st->cngNoiseLevel; + cngNoiseLevelExp = st->cngNoiseLevelExp; + move16(); + ptr_level = cngNoiseLevel; + seed = &( st->seed ); + fftBuffer = st->fftBuffer; + timeDomainOutput = st->timeDomainBuffer; + + /* + Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin + scaling Gaussian random noise: format Q3.29 + */ + sn = 0; + move16(); + IF( s_and( cngNoiseLevelExp, 1 ) != 0 ) { - maxv = s_max( maxv, abs_s( exc[i] ) ); + sn = add( sn, 1 ); + cngNoiseLevelExp = add( cngNoiseLevelExp, sn ); } - scale = norm_s( maxv ); - pt_res = exc; - L_ener = L_deposit_l( 1 ); - IF( EQ_16( len, L_FRAME ) ) + + randGaussExp = CNG_RAND_GAUSS_SHIFT; + move16(); + cnt = sub( stenc->stopFFTbinDec, stenc->startBandDec ); + IF( stenc->startBandDec == 0 ) { - FOR( i = 0; i < 128; i++ ) - { - tmp16 = shl( *pt_res, scale ); - L_tmp = L_mult0( tmp16, tmp16 ); - pt_res++; - tmp16 = shl( *pt_res, scale ); - L_tmp = L_mac0( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ - } + /* DC component in FFT */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32( L_shr( *ptr_level, sn ), &s ); + + fftBuffer[0] = L_shl( Mpy_32_32( rand_gauss( seed ), sqrtNoiseLevel ), s ); + move32(); + + /* Nyquist frequency is discarded */ + fftBuffer[1] = L_deposit_l( 0 ); + move32(); + + ptr_level = ptr_level + 1; + ptr_r = fftBuffer + 2; + cnt = sub( cnt, 1 ); } - ELSE /* L_FRAME16k */ + ELSE { - FOR( i = 0; i < 160; i++ ) - { - tmp16 = shl( *pt_res, scale ); - L_tmp = L_mult0( tmp16, tmp16 ); - pt_res++; - tmp16 = shl( *pt_res, scale ); - L_tmp = L_mac0( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ - pt_res++; - L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ - } + startBand2 = shl( stenc->startBandDec, 1 ); + set32_fx( fftBuffer, 0, startBand2 ); + ptr_r = fftBuffer + startBand2; } - hi = norm_l( L_ener ); - lo = Log2_norm_lc( L_shl( L_ener, hi ) ); - hi = sub( 30, add( hi, shl( add( Q_new, scale ), 1 ) ) ); /* log2 exp in Q2*(Q_new+scale) */ - L_tmp = L_Comp( hi, lo ); /* Q16 */ - enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ - - /* decrease the energy in case of WB input */ - test(); - IF( EQ_16( element_mode, IVAS_CPE_DFT ) || EQ_16( element_mode, IVAS_CPE_TD ) ) + sn = add( sn, 1 ); + ptr_i = ptr_r + 1; + FOR( i = 0; i < cnt; i++ ) { - // PMT(" IVAS CNG ener computing is missing") -#ifdef IVAS_CODE - enr += CNG_att * FAC_LOG2 / 10.0f; -#else - (void) CNG_att; -#endif + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32( L_shr( *ptr_level, sn ), &s ); + + /* Real part in FFT bins */ + *ptr_r = L_shl( Mpy_32_32( rand_gauss( seed ), sqrtNoiseLevel ), s ); + move32(); + + /* Imaginary part in FFT bins */ + *ptr_i = L_shl( Mpy_32_32( rand_gauss( seed ), sqrtNoiseLevel ), s ); + move32(); + + ptr_r = ptr_r + 2; + ptr_i = ptr_i + 2; + ptr_level = ptr_level + 1; + } + + /* Remaining FFT bins are set to zero */ + stopFFTbin2 = shl( stenc->stopFFTbinDec, 1 ); + set32_fx( fftBuffer + stopFFTbin2, 0, sub( st->fftlen, stopFFTbin2 ) ); + + fftBufferExp = add( shr( cngNoiseLevelExp, 1 ), randGaussExp ); + + /* If previous frame is active, reset the overlap-add buffer */ + IF( GT_32( stcod->last_core_brate, SID_2k40 ) ) + { + set16_fx( st->olapBufferSynth, 0, st->fftlen ); + test(); + test(); + IF( ( GT_32( stcod->last_core, ACELP_CORE ) && EQ_16( stcod->codec_mode, MODE2 ) ) || EQ_16( stcod->codec_mode, MODE1 ) ) + { + tcx_transition = 1; + move16(); + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT_enc_ivas_fx( fftBuffer, fftBufferExp, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn, + tcx_transition, st, gen_exc, &Q_new, -1, -1 ); + IF( hTdCngEnc != NULL ) + { + Word32 Lener, att; + Word16 exp; + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + /*enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize;*/ + Lener = Dot_productSq16HQ( 1, st->exc_cng, stcod->L_frame, &exp ); + exp = add( sub( shl( sub( 15, Q_new ), 1 ), 8 ), exp ); /*8 = log2(256)*/ + + /* convert log2 of residual signal energy */ + /*(float)log10( enr + 0.1f ) / (float)log10( 2.0f );*/ + Lener = BASOP_Util_Log2( Lener ); + Lener = L_add( Lener, L_shl( L_deposit_l( exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ + if ( EQ_16( stcod->L_frame, L_FRAME16k ) ) + { + Lener = L_sub( Lener, 10802114l /*0.3219280949f Q25*/ ); /*log2(320) = 8.3219280949f*/ + } + /* decrease the energy in case of WB input */ + IF( NE_16( stcod->bwidth, NB ) ) + { + IF( EQ_16( stcod->bwidth, WB ) ) + { + IF( hDtxEnc->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = L_shl( L_deposit_l( ENR_ATT_fx[hDtxEnc->CNG_mode] ), 17 ); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = L_shl( L_deposit_l( ENR_ATT_fx[4] ), 17 ); + } + } + ELSE + { + att = 384 << 17; + move32(); /*1.5 Q8<<17=Q25*/ + } + Lener = L_sub( Lener, att ); + } + /*stdec->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr );*/ + Lener = BASOP_util_Pow2( Lener, 6, &exp ); + Lener = Mult_32_16( Lener, 6554 /*0.2f Q15*/ ); + exp = sub( 25, exp ); + Lener = L_shr( Lener, exp ); /*Q6*/ + hTdCngEnc->lp_ener_fx = L_add( Mult_32_16( hTdCngEnc->lp_ener_fx, 26214 /*0.8f Q15*/ ), Lener ); /*Q6*/ + move32(); + } + + /* Overlap-add when previous frame is active */ + test(); + IF( ( GT_32( stcod->last_core_brate, SID_2k40 ) ) && ( EQ_16( stcod->codec_mode, MODE2 ) ) ) + { + Word32 old_exc_ener, gain, noise32; + Word16 seed_loc, lpcorder, old_syn, tmp, gain16, N, N2, N4, N8; + Word16 old_exc_ener_exp, gain_exp; + Word16 normFacE, normShiftE, normShiftEM1; + Word16 normFacG, normShiftG, normShiftGM1; + Word16 noiseExp, *old_exc, old_Aq[M + 1], *old_syn_pe; + Word16 noise[640], normShiftP2; + Word16 Q_exc, Q_syn; + + + assert( st->frameSize <= 640 ); + + seed_loc = st->seed; + move16(); + N = st->frameSize; + move16(); + N2 = shr( st->frameSize, 1 ); + + IF( GT_16( stcod->last_core, ACELP_CORE ) ) + { + Word16 left_overlap_mode; + left_overlap_mode = stcod->hTcxCfg->tcx_last_overlap_mode; + move16(); + if ( EQ_16( left_overlap_mode, ALDO_WINDOW ) ) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + + tcx_windowing_synthesis_current_frame( timeDomainOutput, + stcod->hTcxCfg->tcx_mdct_window, /*Keep sine windows for limiting Time modulation*/ + stcod->hTcxCfg->tcx_mdct_window_half, + stcod->hTcxCfg->tcx_mdct_window_minimum, + stcod->hTcxCfg->tcx_mdct_window_length, + stcod->hTcxCfg->tcx_mdct_window_half_length, + stcod->hTcxCfg->tcx_mdct_window_min_length, + 0, + left_overlap_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + N / 2, + shr( sub( abs_s( stcod->hTcxCfg->tcx_offset ), stcod->hTcxCfg->tcx_offset ), 1 ), /* equivalent to: stdec->hTcxCfg->tcx_offset<0?-stdec->hTcxCfg->tcx_offset:0 */ + 1, + 0, + 0 ); + + IF( stcod->hTcxCfg->last_aldo != 0 ) + { + FOR( i = 0; i < st->frameSize; i++ ) + { + timeDomainOutput[i] = add( timeDomainOutput[i], shr_r( hTcxEnc->old_out_fx[i + NS2SA( stcod->sr_core, N_ZERO_MDCT_NS )], hTcxEnc->Q_old_out ) ); + move16(); + } + } + ELSE + { + tcx_windowing_synthesis_past_frame( hTcxEnc->Txnq, + stcod->hTcxCfg->tcx_aldo_window_1_trunc, + stcod->hTcxCfg->tcx_mdct_window_half, + stcod->hTcxCfg->tcx_mdct_window_minimum, + stcod->hTcxCfg->tcx_mdct_window_length, + stcod->hTcxCfg->tcx_mdct_window_half_length, + stcod->hTcxCfg->tcx_mdct_window_min_length, + stcod->hTcxCfg->tcx_last_overlap_mode ); + + FOR( i = 0; i < N2; i++ ) + { + timeDomainOutput[i] = add( timeDomainOutput[i], shl( hTcxEnc->Txnq[i], TCX_IMDCT_HEADROOM ) ); + move16(); + } + } + } + ELSE + { + + /* + - the scaling of the LPCs (e.g. old_Aq) is always Q12 (encoder or decoder) + + - the scaling of the deemphasized signals (e.g. old_syn) is always Q0 (encoder or decoder) + + - the scaling of the excitation signals in the encoder (e.g. old_exc) is Q_new + - the scaling of the preemphasized signals in the encoder (e.g. old_syn_pe) is Q_new-1 + + - the scaling of the excitation signals in the decoder (e.g. old_exc) is Q_exc (or stdec->Q_exc) + - the scaling of the preemphasized signals in the decoder (e.g. old_syn_pe) is Q_syn (or stdec->Q_syn) + */ + + lpcorder = M; + move16(); + E_LPC_f_lsp_a_conversion( stcod->lsp_old_fx, old_Aq, M ); + old_exc = hLPDmem->old_exc + sub( L_EXC_MEM, N2 ); + old_syn_pe = hLPDmem->mem_syn2; + old_syn = hLPDmem->syn[lpcorder]; + move16(); + preemph_fac = stcod->preemph_fac; + move16(); + Q_exc = Q_new; + Q_syn = sub( Q_new, 1 ); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N8 = shr( N2, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + assert( N2 == ( N8 << CNG_NORM_RECIPROCAL_RANGE_SHIFT ) ); + + normFacE = getNormReciprocalWord16( N8 ); + normShiftE = BASOP_util_norm_s_bands2shift( N8 ); + normShiftEM1 = sub( normShiftE, 1 ); + normShiftP2 = add( normShiftE, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + old_exc_ener = L_shr( L_mult( old_exc[0], old_exc[0] ), normShiftP2 ); + FOR( i = 1; i < N2; i++ ) + { + old_exc_ener = L_add( old_exc_ener, L_shr( L_mult( old_exc[i], old_exc[i] ), normShiftP2 ) ); + } + old_exc_ener = L_shl( Mpy_32_16_1( old_exc_ener, shl( normFacE, normShiftEM1 ) ), 1 ); + + old_exc_ener_exp = 0; + move16(); + old_exc_ener = Sqrt32( old_exc_ener, &old_exc_ener_exp ); + old_exc_ener_exp = add( old_exc_ener_exp, ( sub( 15, Q_exc ) ) ); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N4 = shr( N, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + assert( N == ( N4 << CNG_NORM_RECIPROCAL_RANGE_SHIFT ) ); + + normFacG = getNormReciprocalWord16( N4 ); + normShiftG = BASOP_util_norm_s_bands2shift( N4 ); + normShiftGM1 = sub( normShiftG, 1 ); + normShiftP2 = add( normShiftG, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + gain = L_deposit_l( 0 ); + FOR( i = 0; i < N; i++ ) + { + noise32 = rand_gauss( &seed_loc ); + noise[i] = extract_h( noise32 ); + move16(); + gain = L_add( gain, L_shr( L_mult( noise[i], noise[i] ), normShiftP2 ) ); + } + gain = L_shl( Mpy_32_16_1( gain, shl( normFacG, normShiftGM1 ) ), 1 ); + + gain_exp = 2 * CNG_RAND_GAUSS_SHIFT; + move16(); + gain = ISqrt32( gain, &gain_exp ); + + gain = Mpy_32_32( old_exc_ener, gain ); + gain16 = extract_h( gain ); + + gain_exp = add( old_exc_ener_exp, gain_exp ); + noiseExp = add( CNG_RAND_GAUSS_SHIFT, gain_exp ); + + s = sub( 15 - NOISE_HEADROOM, noiseExp ); + FOR( i = 0; i < N; i++ ) + { +#ifdef BASOP_NOGLOB + noise[i] = shr_sat( mult( noise[i], gain16 ), s ); +#else + noise[i] = shr( mult( noise[i], gain16 ), s ); +#endif + move16(); + } + + assert( lpcorder <= 16 ); + + s = sub( 15 - NOISE_HEADROOM, ( sub( 15, Q_syn ) ) ); + FOR( i = 0; i < lpcorder; i++ ) + { +#ifdef BASOP_NOGLOB + old_syn_pe_tmp[i] = shr_sat( old_syn_pe[i], s ); +#else + old_syn_pe_tmp[i] = shr( old_syn_pe[i], s ); +#endif + move16(); + } + + E_UTIL_synthesis( + 0, /* i : scaling to apply for a[0] Q0 */ + old_Aq, /* i : LP filter coefficients Q12 */ + noise, /* i : input signal Qx */ + noise, /* o : output signal Qx-s */ + N, /* i : size of filtering Q0 */ + old_syn_pe_tmp, /* i/o: memory associated with this filtering. Q0 */ + 0, /* i : 0=no update, 1=update of memory. Q0 */ + lpcorder /* i : order of LP filter Q0 */ + ); + + tmp = old_syn; + move16(); + + E_UTIL_deemph2( + NOISE_HEADROOM, + noise, /* I/O: signal Qx */ + preemph_fac, /* I: deemphasis factor Qx */ + N, /* I: vector size */ + &tmp /* I/O: memory (signal[-1]) Qx */ + ); + + FOR( i = 0; i < N4; i++ ) + { + tmp = mult( noise[i], st->olapWinSyn[i].v.re ); + timeDomainOutput[i] = add( timeDomainOutput[i], tmp ); + move16(); + tmp = mult( noise[i + N4], st->olapWinSyn[N4 - 1 - i].v.im ); + timeDomainOutput[i + N4] = add( timeDomainOutput[i + N4], tmp ); + move16(); + } + } + } +} +#endif + +/*-------------------------------------------------------------------* + * cng_energy_fx() + * + * + *-------------------------------------------------------------------*/ + +/*! r: CNG energy */ +Word16 cng_energy_fx( + const Word16 element_mode, /* i : element mode */ + const Word16 bwidth, /* i : audio bandwidh */ + const Word16 CNG_mode, /* i : mode for DTX configuration */ + const Word16 CNG_att, /* i : attenuation factor for CNG */ + const Word16 *exc, /* i : input signal */ + const Word16 len, /* i : vector length */ + const Word16 Q_new /* i : Input scaling */ +) +{ + Word16 i, maxv, scale; + Word16 hi, lo, enr, tmp16, att; + const Word16 *pt_res; + Word32 L_ener, L_tmp; + + maxv = 0; + move16(); + FOR( i = 0; i < len; i++ ) + { + maxv = s_max( maxv, abs_s( exc[i] ) ); + } + scale = norm_s( maxv ); + pt_res = exc; + L_ener = L_deposit_l( 1 ); + IF( EQ_16( len, L_FRAME ) ) + { + FOR( i = 0; i < 128; i++ ) + { + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mult0( tmp16, tmp16 ); + pt_res++; + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mac0_sat( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR( i = 0; i < 160; i++ ) + { + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mult0( tmp16, tmp16 ); + pt_res++; + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mac0( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ + } + } + + hi = norm_l( L_ener ); + lo = Log2_norm_lc( L_shl( L_ener, hi ) ); + hi = sub( 30, add( hi, shl( add( Q_new, scale ), 1 ) ) ); /* log2 exp in Q2*(Q_new+scale) */ + L_tmp = L_Comp( hi, lo ); /* Q16 */ + enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ + + /* decrease the energy in case of WB input */ + test(); + IF( EQ_16( element_mode, IVAS_CPE_DFT ) || EQ_16( element_mode, IVAS_CPE_TD ) ) + { + // PMT(" IVAS CNG ener computing is missing") +#ifdef IVAS_CODE + enr += CNG_att * FAC_LOG2 / 10.0f; +#else + (void) CNG_att; +#endif + } + ELSE IF( NE_16( bwidth, NB ) ) + { + IF( EQ_16( bwidth, WB ) ) + { + IF( CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT_fx[CNG_mode]; + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT_fx[4]; + } + } + ELSE + { + att = 384; + move16(); /*Q8*/ + } + enr = sub( enr, att ); + } + return enr; +} + +/*-------------------------------------------------------------------* + * cng_energy_ivas_fx() + * + * + *-------------------------------------------------------------------*/ + +/*! r: CNG energy */ +Word16 cng_energy_ivas_fx( + const Word16 element_mode, /* i : element mode */ + const Word16 bwidth, /* i : audio bandwidh */ + const Word16 CNG_mode, /* i : mode for DTX configuration */ + const Word16 CNG_att, /* i : attenuation factor for CNG Q7 */ + const Word16 *exc, /* i : input signal */ + const Word16 len, /* i : vector length */ + const Word16 Q_new /* i : Input scaling */ +) +{ + Word16 i, maxv, scale; + Word16 hi, lo, enr, tmp16, att; + const Word16 *pt_res; + Word32 L_ener, L_tmp; + + maxv = 0; + move16(); + FOR( i = 0; i < len; i++ ) + { + maxv = s_max( maxv, abs_s( exc[i] ) ); + } + scale = norm_s( maxv ); + pt_res = exc; + L_ener = L_deposit_l( 1 ); + IF( EQ_16( len, L_FRAME ) ) + { + FOR( i = 0; i < 128; i++ ) + { + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mult0( tmp16, tmp16 ); + pt_res++; + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mac0( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( L_tmp, 7 ) ); /* 2*(Q_new+scale)+1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR( i = 0; i < 160; i++ ) + { + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mult0( tmp16, tmp16 ); + pt_res++; + tmp16 = shl( *pt_res, scale ); + L_tmp = L_mac0( L_tmp, tmp16, tmp16 ); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add( L_ener, L_shr( Mult_32_16( L_tmp, 26214 /* 256/320, Q15 */ ), 7 ) ); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ + } + } + + hi = norm_l( L_ener ); + lo = Log2_norm_lc( L_shl( L_ener, hi ) ); + hi = sub( 30, add( hi, shl( add( Q_new, scale ), 1 ) ) ); /* log2 exp in Q2*(Q_new+scale) */ + L_tmp = L_Comp( hi, lo ); /* Q16 */ + enr = round_fx( L_shl( L_tmp, 8 ) ); /* Q8 (16+8-16) */ + + /* decrease the energy in case of WB input */ + test(); + IF( EQ_16( element_mode, IVAS_CPE_DFT ) || EQ_16( element_mode, IVAS_CPE_TD ) ) + { + // PMT(" IVAS CNG ener computing is missing") + enr = add( enr, mult( CNG_att, FAC_LOG2_BY10_Q16 ) ); /* Q8 (7+16-15) */ } ELSE IF( NE_16( bwidth, NB ) ) { diff --git a/lib_enc/find_tar_fx.c b/lib_enc/find_tar_fx.c index 1fb28ca9752e1f632da001ddde6abae13863cd33..54cdec132b4e3d52c9aaa9ff629282b81945e37f 100644 --- a/lib_enc/find_tar_fx.c +++ b/lib_enc/find_tar_fx.c @@ -189,3 +189,182 @@ void find_targets_fx( return; } + +void find_targets_ivas_fx( + const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/ + const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/ + const Word16 i_subfr, /* i : subframe index */ + Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/ + const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/ + const Word16 *res, /* i : residual signal Q_new*/ + const Word16 L_subfr, /* i : length of vectors for gain quantization */ + const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/ + Word16 tilt_fac, /* i : tilt factor Q15 */ + Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/ + Word16 *cn, /* o : target vector in residual domain Q_new*/ + Word16 *h1 /* o : impulse response of weighted synthesis filter */ +) +{ + Word16 i; + Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */ + Word16 scale, scaleq, j, d, s, s2, tmp; + Word16 Aqs[M + 1]; + Word32 Ltmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + /*------------------------------------------------------------------------* + * Find the target vector for excitation search: + * + * |------| res[n] + * speech[n]---| A(z) |-------- + * |------| | |--------| error[n] |------| + * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target + * exc |--------| |------| + * + * Instead of subtracting the zero-input response of filters from + * the weighted input speech, the above configuration is used to + * compute the target vector. + *-----------------------------------------------------------------------*/ + FOR( i = 0; i < M; i++ ) + { +#ifdef BASOP_NOGLOB + temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); +#else + temp[i] = sub( speech[i + i_subfr - M], mem_syn[i] ); +#endif + move16(); + } + Syn_filt_s( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 ); + + Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new -1*/ + + deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new -1 */ + + + /*-----------------------------------------------------------------* + * Find target in residual domain (cn[]) for innovation search + *--------------------------------------------------------------*/ + IF( cn != NULL ) + { + /* first half: xn[] --> cn[] */ + temp[0] = 0; + move16(); + preemph_copy_fx( xn, cn, tilt_fac, shr( L_subfr, 1 ), temp ); + syn_filt_s_lc_fx( 1, Ap, cn, temp, shr( L_subfr, 1 ) ); /* Q-1 -> Q-2 */ + Residu3_lc_fx( p_Aq, M, temp, cn, shr( L_subfr, 1 ), 1 ); /* Q-2 -> Q-1 */ + Scale_sig( cn, shr( L_subfr, 1 ), 1 ); + + /* second half: res[] --> cn[] (approximated and faster) */ + Copy( &res[i_subfr + shr( L_subfr, 1 )], cn + shr( L_subfr, 1 ), shr( L_subfr, 1 ) ); + } + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + + scale = norm_s( Ap[0] ); + scaleq = norm_s( p_Aq[0] ); + d = sub( scaleq, scale ); + IF( d >= 0 ) + { + Copy( p_Aq, Aqs, M + 1 ); + s = add( scaleq, 1 ); + s2 = shr( 16384, d ); + } + ELSE + { + Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); + s = add( scale, 1 ); + s2 = 16384; + } + Overflow = 0; + move16(); + FOR( i = 0; i < M; i++ ) + { + Ltmp = L_mult( Ap[i], s2 ); + FOR( j = 1; j <= i; j++ ) + { +#ifdef BASOP_NOGLOB /* Critical Overflow , as well as those below*/ + Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); +#else + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); +#endif + } +#ifdef BASOP_NOGLOB /* Critical Overflow */ + h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); +#else + h1[i] = round_fx( L_shl( Ltmp, s ) ); +#endif + } + Ltmp = L_mult( Ap[i], s2 ); + FOR( j = 1; j <= M; j++ ) + { +#ifdef BASOP_NOGLOB /* Critical Overflow */ + Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); +#else + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); +#endif + } +#ifdef BASOP_NOGLOB /* Critical Overflow */ + h1[M] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); +#else + h1[M] = round_fx( L_shl( Ltmp, s ) ); +#endif + + // PMT("should we used extended basop here for when the L_subfr > L_SUBFR, to prevent saturation/overflow and the subsequent loop\n") + FOR( i = M + 1; i < L_subfr; i++ ) + { + Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); + FOR( j = 2; j <= M; j++ ) + { +#ifdef BASOP_NOGLOB /* Critical Overflow */ + Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); +#else + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); +#endif + } +#ifdef BASOP_NOGLOB /* Critical Overflow */ + h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); +#else + h1[i] = round_fx( L_shl( Ltmp, s ) ); +#endif + } + IF( Overflow ) + { + s2 = shr( s2, 1 ); + FOR( i = 0; i < M; i++ ) + { + Ltmp = L_mult( Ap[i], s2 ); + FOR( j = 1; j <= i; j++ ) + { + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); + } +#ifdef BASOP_NOGLOB + h1[i] = round_fx( L_shl_o( Ltmp, s, &Overflow ) ); +#else + h1[i] = round_fx( L_shl( Ltmp, s ) ); +#endif + } + Ltmp = L_mult( Ap[i], s2 ); + FOR( j = 1; j <= M; j++ ) + { + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); + } + h1[M] = round_fx( L_shl( Ltmp, s ) ); + FOR( i = M + 1; i < L_subfr; i++ ) + { + Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); + FOR( j = 2; j <= M; j++ ) + { + Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); + } + h1[i] = round_fx( L_shl( Ltmp, s ) ); + } + } + + tmp = 0; + Deemph2( h1, tilt_fac, L_subfr, &tmp ); + + return; +} diff --git a/lib_enc/find_tilt.c b/lib_enc/find_tilt.c index 0f64f8888a6b455ab96220f966b08974fba764fe..cb8af8babec5b0326b812d9665a1224f94f47e94 100644 --- a/lib_enc/find_tilt.c +++ b/lib_enc/find_tilt.c @@ -41,6 +41,12 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#endif // IVAS_FLOAT_FIXED + + /*---------------------------------------------------------------------* * Local constants *---------------------------------------------------------------------*/ @@ -55,6 +61,275 @@ * * Find LF/HF energy ratio *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void find_tilt_ivas_fx( + const Word32 fr_bands[], /* i : energy in frequency bands Q_new*/ + const Word32 bckr[], /* i : per band background noise energy estimate Q_new*/ + Word32 ee[2], /* o : lf/hf E ration for present frame Q6*/ + const Word16 pitch[3], /* i : open loop pitch values for 3 half-frames Q0*/ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames Q15*/ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new - 2*/ + const Word16 corr_shift, /* i : normalized correlation correction Q15*/ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 max_band, /* i : maximum critical band */ + Word32 hp_E[], /* o : energy in HF Q_new*/ + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + const Word16 Q_new, /* i : scaling factor */ + Word32 *bckr_tilt_lt /* i/o: lf/hf E ratio of background noise Q16 */ + , + Word16 Opt_vbr_mode ) +{ + Word32 lp_bckr = 0, hp_bckr = 0, lp_E, Ltmp; + const Word32 *pt_E, *pt_bands, *pt_bckr, *hf_bands, *tmp_E; + Word16 tmp, freq, f0, f1, f2, mean_voi, bin; + Word16 i, nb_bands; + Word16 e_tmp, m_tmp; + Word16 m_Fs, e_Fs; + Word16 m_cnt, e_cnt; + Word16 m_hpE, e_hpE; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + move32(); + move32(); + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + IF( NE_16( bwidth, NB ) ) + { + /* WB processing */ + bin = BIN4_FX; + move16(); /* First useful frequency bin ~ 50 Hz */ + pt_bands = fr_bands; + tmp_E = lf_E; + pt_bckr = bckr; + nb_bands = 10; + move16(); + } + ELSE + { + /* NB processing */ + bin = add( shl( BIN4_FX, 1 ), BIN4_FX ); /* First useful frequency bin ~ 150 Hz */ + pt_bands = fr_bands + 1; /* Exlcude 1st critical band */ + tmp_E = lf_E + 2; /* Start at the 3rd bin (150 Hz) */ + pt_bckr = bckr + 1; /* Exlcude 1st critical band */ + nb_bands = 9; + move16(); /* Nb. of "low" frequency bands taken into account in NB processing */ + } + + /*-----------------------------------------------------------------* + * Find spectrum tilt + *-----------------------------------------------------------------*/ + + pt_E = tmp_E; /* Point at the 1st useful element of the per-bin energy vector */ + hf_bands = fr_bands; + + /* bckr + voicing */ + /*lp_bckr = mean( pt_bckr, nb_bands );*/ /* estimated noise E in first critical bands, up to 1270 Hz */ + lp_bckr = Mean32( pt_bckr, nb_bands ); + /*hp_bckr = 0.5f * (bckr[max_band-1] + bckr[max_band]);*/ /* estimated noise E in last 2 critical bands */ +#ifdef BASOP_NOGLOB + hp_bckr = L_shr( L_add_sat( bckr[max_band - 1], bckr[max_band] ), 1 ); +#else + hp_bckr = L_shr( L_add( bckr[max_band - 1], bckr[max_band] ), 1 ); +#endif + if ( hp_bckr == 0 ) /* Avoid division by zero. */ + { + hp_bckr = L_deposit_l( 1 ); + } + Ltmp = BASOP_Util_Divide3232_Scale_cadence( lp_bckr, hp_bckr, &e_tmp ); + Ltmp = Mpy_32_16_r( Ltmp, 3277 ); + Ltmp = L_shr_sat( Ltmp, sub( 15, e_tmp ) ); + *bckr_tilt_lt = L_add_sat( Mpy_32_16_r( *bckr_tilt_lt, 29491 ), Ltmp ); + move32(); + + test(); + IF( EQ_16( codec_mode, MODE2 ) || Opt_vbr_mode == 1 ) + { + /*lp_bckr *= FACT;*/ + /*hp_bckr *= FACT;*/ +#ifdef BASOP_NOGLOB + lp_bckr = L_add_sat( L_shl_sat( lp_bckr, 1 ), lp_bckr ); + hp_bckr = L_add_sat( L_shl_sat( hp_bckr, 1 ), hp_bckr ); +#else + lp_bckr = L_add( L_shl( lp_bckr, 1 ), lp_bckr ); + hp_bckr = L_add( L_shl( hp_bckr, 1 ), hp_bckr ); +#endif + } + /*mean_voi = 0.5f * (voicing[1] + voicing[2]) + corr_shift;*/ + Ltmp = L_mult( voicing[1], 16384 ); + Ltmp = L_mac( Ltmp, voicing[2], 16384 ); +#ifdef BASOP_NOGLOB + Ltmp = L_mac_o( Ltmp, corr_shift, 32767, &Overflow ); + mean_voi = round_fx_o( Ltmp, &Overflow ); +#else + Ltmp = L_mac( Ltmp, corr_shift, 32767 ); + mean_voi = round_fx( Ltmp ); +#endif + + /*f0 = INT_FS_FX / pitch[2];*/ + e_tmp = norm_s( pitch[2] ); + m_tmp = shl( pitch[2], e_tmp ); + + m_Fs = div_s( INT_FS_FX, m_tmp ); + e_Fs = sub( 15, e_tmp ); + f0 = shr( m_Fs, sub( e_Fs, 4 ) ); /* Q4 */ + + FOR( i = 0; i < 2; i++ ) + { + /*hp_E[i] = 0.5f * (hf_bands[max_band-1] + hf_bands[max_band]) - hp_bckr; */ /* averaged E in last 2 critical bands */ + Ltmp = L_add( L_shr( hf_bands[max_band - 1], 1 ), L_shr( hf_bands[max_band], 1 ) ); + hp_E[i] = L_sub( Ltmp, hp_bckr ); + move32(); + IF( Opt_vbr_mode == 0 ) + { + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( hp_E[i], sub( 31, Q_new ), E_MIN_IVAS_FX, 31 - Q19 ), -1 ) ) + { + hp_E[i] = L_shl( E_MIN_IVAS_FX, sub( Q_new, Q19 ) ); + move32(); + } + } + ELSE + { + hp_E[i] = L_max( hp_E[i], L_shl( 1, Q_new ) ); + move32(); + } + + test(); + IF( GT_16( mean_voi, TH_COR_FX ) && LT_16( pitch[2], TH_PIT_FX ) ) /* High-pitched voiced frames */ + { + freq = bin; + move16(); /* 1st useful frequency bin */ + m_cnt = 0; + move16(); + lp_E = L_deposit_l( 0 ); + + f1 = add( shr( f0, 1 ), f0 ); /* Middle between 2 harmonics */ + f2 = f0; + move16(); + WHILE( LE_16( freq, 20320 ) ) /* End frequency of 10th critical band */ + { + FOR( ; freq <= f1; freq += BIN4_FX ) + { + /* include only bins sufficiently close to harmonics */ + tmp = sub( freq, f2 ); + IF( L_mac0( -(Word32) TH_D_FX * TH_D_FX, tmp, tmp ) < 0 ) + { +#ifdef BASOP_NOGLOB + lp_E = L_add_o( *pt_E, lp_E, &Overflow ); +#else + lp_E = L_add( *pt_E, lp_E ); +#endif + m_cnt = add( m_cnt, 1 ); + } + pt_E++; + } +#ifdef BASOP_NOGLOB + f1 = add_o( f1, f0, &Overflow ); + f2 = add_o( f2, f0, &Overflow ); +#else + f1 = add( f1, f0 ); + f2 = add( f2, f0 ); +#endif + } + /*lp_E = lp_E / (float)cnt - lp_bckr;*/ + e_tmp = sub( norm_l( lp_E ), 1 ); + m_tmp = extract_h( L_shl( lp_E, e_tmp ) ); + + e_tmp = sub( e_tmp, 2 ); /* lf_e divided by 4 in anal_sp */ + + e_cnt = norm_s( m_cnt ); + m_cnt = shl( m_cnt, e_cnt ); + + m_tmp = div_s( m_tmp, m_cnt ); + e_tmp = sub( e_tmp, e_cnt ); + +#ifdef BASOP_NOGLOB + lp_E = L_sub_o( L_shr_o( m_tmp, sub( e_tmp, 1 ), &Overflow ), lp_bckr, &Overflow ); +#else + lp_E = L_sub( L_shr( m_tmp, sub( e_tmp, 1 ) ), lp_bckr ); +#endif + + pt_E = tmp_E + VOIC_BINS; /* Update for next half-frame */ + } + ELSE /* Other than high-pitched voiced frames */ + { + /*lp_E = mean( pt_bands, nb_bands ) - lp_bckr;*/ /* averaged E in first critical bands, up to 1270 Hz */ + lp_E = L_sub( Mean32( pt_bands, nb_bands ), lp_bckr ); + } + IF( Opt_vbr_mode == 0 ) + { + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( lp_E, sub( 31, Q_new ), E_MIN_IVAS_FX, 31 - Q19 ), -1 ) ) + { + lp_E = L_shl( E_MIN_IVAS_FX, sub( Q_new, Q19 ) ); + } + } + ELSE + { + lp_E = L_max( lp_E, 0 ); + } + /*ee[i] = lp_E / hp_E[i];*/ /* LF/HF ratio */ + test(); + IF( lp_E != 0 && hp_E[i] != 0 ) + { + e_tmp = sub( norm_l( lp_E ), 1 ); + m_tmp = extract_h( L_shl( lp_E, e_tmp ) ); + e_hpE = norm_l( hp_E[i] ); + m_hpE = extract_h( L_shl( hp_E[i], e_hpE ) ); + m_tmp = div_s( m_tmp, m_hpE ); + e_tmp = sub( e_tmp, e_hpE ); + +#ifdef BASOP_NOGLOB + ee[i] = L_shr_o( m_tmp, add( e_tmp, 15 - 6 ), &Overflow ); /* ee in Q6 */ +#else /* BASOP_NOGLOB */ + ee[i] = L_shr( m_tmp, add( e_tmp, 15 - 6 ) ); /* ee in Q6 */ +#endif + move32(); + } + ELSE IF( lp_E == 0 ) + { + ee[i] = L_deposit_l( 0 ); + move32(); + } + ELSE + { + ee[i] = MAX_32; + move32(); + } + + IF( EQ_16( bwidth, NB ) ) /* For NB input, compensate for the missing bands */ + { +#ifdef BASOP_NOGLOB + Ltmp = L_shl_o( ee[i], 3, &Overflow ); +#else + Ltmp = L_shl( ee[i], 3 ); +#endif + IF( EQ_32( Ltmp, MAX_32 ) ) /* if Overflow: Compute with less precision */ + { + Ltmp = Mult_32_16( ee[i], 24576 ); /* 6/8 */ +#ifdef BASOP_NOGLOB + ee[i] = L_shl_sat( Ltmp, 3 ); +#else + ee[i] = L_shl( Ltmp, 3 ); +#endif + move32(); /* x8 */ + } + ELSE + { + ee[i] = Mult_32_16( Ltmp, 24576 ); + move32(); /* 6/8 */ + } + } + + pt_bands += NB_BANDS; /* Update for next half-frame */ + hf_bands += NB_BANDS; + } + + return; +} +#endif // IVAS_FLOAT_FIXED void find_tilt( const float fr_bands[], /* i : energy in frequency bands */ diff --git a/lib_enc/find_uv.c b/lib_enc/find_uv.c index f48d1fe70157db039e9c0d18afe7895a18906516..4a4e7f4f239da71a7a8ca21addb694b181983aa6 100644 --- a/lib_enc/find_uv.c +++ b/lib_enc/find_uv.c @@ -41,6 +41,11 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#endif // IVAS_FLOAT_FIXED + /*-------------------------------------------------------------------* * Local constants *-------------------------------------------------------------------*/ @@ -57,6 +62,7 @@ *-------------------------------------------------------------------*/ /*! r: maximum energy ratio */ +#ifndef IVAS_FLOAT_FIXED static float find_ener_decrease( const int16_t ind_deltaMax, /* i : index of the beginning of maximum energy search */ const float *pt_enr_ssf /* i : Pointer to the energy buffer */ @@ -97,14 +103,674 @@ static float find_ener_decrease( return dE2; } +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 find_ener_decrease_fx( /* o : maximum energy ratio Q10 */ + const Word16 ind_deltaMax, /* i : index of the beginning of maximum energy search */ + const Word32 *pt_enr_ssf /* i : Pointer to the energy buffer */ +) +{ + Word16 i, j, end, flag; + Word16 wtmp0, wtmp1; + Word32 maxEnr, minEnr; + Word16 dE2, exp0, exp1; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + dE2 = 0; + move16(); + j = ind_deltaMax + 2; + move16(); + end = j + L_ENR; + move16(); + maxEnr = L_add( pt_enr_ssf[j], 0 ); + j = add( j, 1 ); + flag = 0; + move16(); + FOR( i = j; i < end; i++ ) + { + test(); + IF( ( GT_32( pt_enr_ssf[i], maxEnr ) ) && ( flag == 0 ) ) + { + maxEnr = L_add( pt_enr_ssf[i], 0 ); /*Q0*/ + j = add( j, 1 ); + } + ELSE + { + flag = 1; + move16(); + } + } + + minEnr = L_add( maxEnr, 0 ); + FOR( i = j; i < end; i++ ) + { + minEnr = L_min( minEnr, pt_enr_ssf[i] ); + } + + +#ifdef BASOP_NOGLOB + minEnr = L_add_sat( minEnr, 100000 ); +#else + minEnr = L_add( minEnr, 100000 ); +#endif + exp0 = norm_l( minEnr ); + wtmp0 = extract_h( L_shl( minEnr, exp0 ) ); + exp1 = sub( norm_l( maxEnr ), 1 ); + wtmp1 = extract_h( L_shl( maxEnr, exp1 ) ); + wtmp1 = div_s( wtmp1, wtmp0 ); +#ifdef BASOP_NOGLOB + dE2 = shr_ro( wtmp1, add( sub( exp1, exp0 ), 15 - 10 ), &Overflow ); /*Q10*/ +#else + dE2 = shr_r( wtmp1, add( sub( exp1, exp0 ), 15 - 10 ) ); /*Q10*/ +#endif + + return dE2; +} /*-------------------------------------------------------------------* * find_uv() * * Decision about coder type *-------------------------------------------------------------------*/ +Word16 find_uv_ivas_fx( /* o : coding type */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *T_op_fr, /* i : pointer to adjusted fractional pitch (4 val.) Q6 */ + const Word16 *voicing_fr, /* i : refined correlation for each subframes Q15 */ + const Word16 *speech, /* i : pointer to speech signal for E computation Q_new */ + const Word32 *ee, /* i : lf/hf Energy ratio for present frame Q6 */ + Word32 *dE1X, /* o : sudden energy increase for S/M classifier */ + const Word16 corr_shift, /* i : normalized correlation correction in noise Q15 */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 Etot, /* i : total energy Q8 */ + const Word32 hp_E[], /* i : energy in HF q_hp_E */ + Word16 *flag_spitch, /* i/o: flag to indicate very short stable pitch and high correlation */ + const Word16 last_core_orig, /* i : original last core */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 Q_new, + const Word16 q_hp_E ) +{ + Word16 coder_type, i; + Word32 mean_ee, dE1, fac_32; + const Word16 *pt_speech; + Word32 L_tmp, enr_ssf[2 * NB_SSF + 2 * NB_SSF + 2], E_min_th; + Word16 dE2; + Word16 ind_deltaMax, tmp_offset_flag; + Word32 Ltmp0, *pt_enr_ssf, *pt_enr_ssf1, dE2_th; + Word16 exp0, exp1; + Word16 wtmp0, wtmp1; + Word16 fac, mean_voi3, dE3; + Word16 relE_thres; + Word16 mean_voi3_offset; + Word16 voicing_m, dpit1, dpit2, dpit3; + Word16 ee0_th, ee1_th, voi_th, nb_cond, flag_low_relE; + NOISE_EST_HANDLE hNoiseEst = st_fx->hNoiseEst; + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + Word16 Last_Resort; + Word16 vadnoise; + + IF( hSC_VBR != NULL ) + { + Last_Resort = hSC_VBR->Last_Resort; + move16(); + vadnoise = hSC_VBR->vadnoise_fx; + move16(); + } + ELSE + { + Last_Resort = 0; + move16(); + vadnoise = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Detect sudden energy increases to catch voice and music + * temporal events (dE1) + * + * - Find maximum energy per short subblocks. + * Two subblock sets are used shifted by half the subblock length + * - Find maximum energy ratio between adjacent subblocks + *-----------------------------------------------------------------*/ + + /* Find maximum energy per short subblocks */ + pt_speech = speech - SSF; + pt_enr_ssf = enr_ssf + 2 * NB_SSF; + FOR( i = 0; i < 2 * ( NB_SSF + 1 ); i++ ) + { + emaximum_fx( Q_new, pt_speech, SSF, pt_enr_ssf ); + pt_speech += ( SSF / 2 ); + pt_enr_ssf++; + } + + dE1 = 0; + move16(); + ind_deltaMax = 0; + move16(); + pt_enr_ssf = enr_ssf + 2 * NB_SSF; + pt_enr_ssf1 = pt_enr_ssf + 2; + + /* Test on energy increase between adjacent sub-subframes */ + exp1 = 0; + move16(); + FOR( i = 0; i < 2 * NB_SSF; i++ ) + { + /*fac = *pt_enr_ssf1 / (*pt_enr_ssf + 1);*/ + Ltmp0 = L_max( *pt_enr_ssf, 1 ); + exp0 = norm_l( Ltmp0 ); + wtmp0 = extract_h( L_shl( Ltmp0, exp0 ) ); + exp1 = sub( norm_l( *pt_enr_ssf1 ), 1 ); + wtmp1 = extract_h( L_shl( *pt_enr_ssf1, exp1 ) ); + fac = div_s( wtmp1, wtmp0 ); +#ifdef BASOP_NOGLOB + fac_32 = L_shr_o( L_deposit_l( fac ), add( sub( exp1, exp0 ), 15 - 13 ), &Overflow ); /* fac32 in Q13*/ +#else /* BASOP_NOGLOB */ + fac_32 = L_shr( L_deposit_l( fac ), add( sub( exp1, exp0 ), 15 - 13 ) ); /* fac32 in Q13*/ +#endif /* BASOP_NOGLOB */ + + if ( GT_32( fac_32, dE1 ) ) + { + ind_deltaMax = i; + move16(); + } + + dE1 = L_max( dE1, fac_32 ); + + pt_enr_ssf++; + pt_enr_ssf1++; + } + + IF( hStereoClassif != NULL ) + { + IF( st_fx->idchan == 0 ) + { + hStereoClassif->dE1_ch1_fx = dE1; + move32(); + hStereoClassif->dE1_ch1_e = 31 - Q13; + move16(); + } + ELSE + { + hStereoClassif->dE1_ch2_fx = dE1; + move32(); + hStereoClassif->dE1_ch2_e = 31 - Q13; + move16(); + } + } + + if ( dE1X != NULL ) + { + *dE1X = dE1; + move32(); + } + + /*-----------------------------------------------------------------* + * Average spectral tilt + * Average voicing (normalized correlation) + *-----------------------------------------------------------------*/ + + /*mean_ee = 1.0f/3.0f * (st->ee_old + ee[0] + ee[1]); */ /* coefficients take into account the position of the window */ +#ifdef BASOP_NOGLOB + mean_ee = L_add_o( L_add_o( st_fx->ee_old_fx, ee[0], &Overflow ), ee[1], &Overflow ); +#else /* BASOP_NOGLOB */ + mean_ee = L_add( L_add( st_fx->ee_old_fx, ee[0] ), ee[1] ); +#endif /* BASOP_NOGLOB */ + mean_ee = Mult_32_16( mean_ee, 10923 ); /*Q6*/ + + /* mean_voi3 = 1.0f/3.0f * (voicing[0] + voicing[1] + voicing[2]);*/ + Ltmp0 = L_mult( st_fx->voicing_fx[0], 10923 ); + Ltmp0 = L_mac( Ltmp0, st_fx->voicing_fx[1], 10923 ); +#ifdef BASOP_NOGLOB // -dtx 12650 amrwb\Dtx3.INP + mean_voi3 = mac_r_sat( Ltmp0, st_fx->voicing_fx[2], 10923 ); /*Q15*/ +#else + mean_voi3 = mac_r( Ltmp0, st_fx->voicing_fx[2], 10923 ); /*Q15*/ +#endif + /*-----------------------------------------------------------------* + * Total frame energy difference (dE3) + *-----------------------------------------------------------------*/ + + dE3 = sub( Etot, hNoiseEst->Etot_last_fx ); /*Q8*/ + + /*-----------------------------------------------------------------* + * Energy decrease after spike (dE2) + *-----------------------------------------------------------------*/ + + /* set different thresholds and conditions for NB and WB input */ + dE2_th = 30 << 10; + move32(); + nb_cond = 1; + move16(); /* no additional condition for WB input */ + IF( EQ_16( st_fx->input_bwidth, NB ) ) + { + dE2_th = 21 << 10; + move32(); +#ifdef BASOP_NOGLOB + if ( GE_16( add_o( mean_voi3, corr_shift, &Overflow ), 22282 ) ) /*( mean_voi3 + corr_shift ) >= 0.68f*/ +#else + if ( GE_16( add( mean_voi3, corr_shift ), 22282 ) ) /*( mean_voi3 + corr_shift ) >= 0.68f*/ +#endif + { + nb_cond = 0; + move16(); + } + } + + /* calcualte maximum energy decrease */ + dE2 = 0; + move16(); /* Test on energy decrease after an energy spike */ + pt_enr_ssf = enr_ssf + 2 * NB_SSF; + + test(); + IF( GT_32( dE1, 30 << 13 ) && nb_cond ) /*>30 Q13*/ + { + IF( LT_16( sub( shl( NB_SSF, 1 ), ind_deltaMax ), L_ENR ) ) + { + st_fx->old_ind_deltaMax = ind_deltaMax; + move16(); + Copy32( pt_enr_ssf, st_fx->old_enr_ssf_fx, 2 * NB_SSF ); + } + ELSE + { + st_fx->old_ind_deltaMax = -1; + move16(); + dE2 = find_ener_decrease_fx( ind_deltaMax, pt_enr_ssf ); /*Q10*/ + + if ( GT_32( dE2, dE2_th ) ) + { + st_fx->spike_hyst = 0; + move16(); + } + } + } + ELSE + { + IF( st_fx->old_ind_deltaMax >= 0 ) + { + Copy32( st_fx->old_enr_ssf_fx, enr_ssf, 2 * NB_SSF ); + dE2 = find_ener_decrease_fx( st_fx->old_ind_deltaMax, enr_ssf ); + + if ( GT_32( dE2, dE2_th ) ) + { + st_fx->spike_hyst = 1; + move16(); + } + } + + st_fx->old_ind_deltaMax = -1; + move16(); + } + + /*-----------------------------------------------------------------* + * Detection of voiced offsets (tmp_offset_flag) + *-----------------------------------------------------------------*/ + + tmp_offset_flag = 1; + move16(); + + IF( NE_16( st_fx->input_bwidth, NB ) ) + { + ee0_th = 154; /*2.4 in Q6 */ + move16(); + voi_th = 24248; /*0.74f Q15 */ + move16(); + } + ELSE + { + ee0_th = 627; /*9.8f Q6 */ + move16(); + voi_th = 24904; /*0.76f Q15*/ + move16(); + } + + E_min_th = L_shl( E_MIN_IVAS_FX, sub( q_hp_E, Q19 ) ); + + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + if ( ( EQ_16( st_fx->last_coder_type_raw, UNVOICED ) ) || /* previous frame was unvoiced */ + ( ( LT_32( ee[0], ee0_th ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy is concentrated in high frequencies provided that some energy is present in HF */ + ( LT_16( add_o( st_fx->voicing_fx[0], corr_shift, &Overflow ), voi_th ) ) ) ) /* normalized correlation is low */ +#else /* BASOP_NOGLOB */ + if ( ( EQ_16( st_fx->last_coder_type_raw, UNVOICED ) ) || /* previous frame was unvoiced */ + ( ( LT_32( ee[0], ee0_th ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy is concentrated in high frequencies provided that some energy is present in HF */ + ( LT_16( add( st_fx->voicing_fx[0], corr_shift ), voi_th ) ) ) ) /* normalized correlation is low */ +#endif /* BASOP_NOGLOB */ + { + tmp_offset_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Decision about UC + *-----------------------------------------------------------------*/ + + /* SC-VBR - set additional parameters and thresholds for SC-VBR */ + mean_voi3_offset = 0; + move16(); + flag_low_relE = 0; + move16(); + ee1_th = 608; /*9.5 Q6*/ + move16(); + test(); + test(); + IF( st_fx->Opt_SC_VBR || ( EQ_16( st_fx->idchan, 1 ) && EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) ) /* Allow the low energy flag for the secondary channel */ + { + ee1_th = 544; /*8.5f Q6*/ + move16(); + + /* SC-VBR - determine the threshold on relative energy as a function of lp_noise */ + IF( NE_16( st_fx->input_bwidth, NB ) ) + { + /*relE_thres = 0.700f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16) */ + L_tmp = L_mac( -562036736, 22938, st_fx->lp_noise_fx ); + if ( Last_Resort == 0 ) + { + /*relE_thres = 0.650f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16)*/ + L_tmp = L_mac( -562036736, 21299, st_fx->lp_noise_fx ); + } + relE_thres = round_fx( L_tmp ); + } + ELSE + { + + /*relE_thres = 0.60f * st->lp_noise - 28.2f; (lp_noise in Q8, constant Q8<<16)*/ + L_tmp = L_mac( -473117491, 19661, st_fx->lp_noise_fx ); + relE_thres = round_fx( L_tmp ); + } + relE_thres = s_max( relE_thres, -6400 ); /* Q8 */ + + /* SC-VBR = set flag on low relative energy */ + if ( LT_16( relE, relE_thres ) ) + { + flag_low_relE = 1; + move16(); + } + + /* SC-VBR - correction of voicing threshold for NB inputs (important only in noisy conditions) */ + test(); + if ( EQ_16( st_fx->input_bwidth, NB ) && LT_16( vadnoise, 20 << 8 ) ) /* vadnoise in Q8, constant Q0<<8 */ + { + mean_voi3_offset = 1638; /*0.05f Q15*/ + move16(); + } + } + + /* make decision whether frame is unvoiced */ + coder_type = GENERIC; + move16(); + IF( EQ_16( st_fx->input_bwidth, NB ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + if ( ( ( LT_16( add_o( mean_voi3, corr_shift, &Overflow ), add( 22282, mean_voi3_offset ) ) ) && /* normalized correlation low */ + ( LT_16( add_o( st_fx->voicing_fx[2], corr_shift, &Overflow ), 25887 ) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32( ee[0], 640 ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32( ee[1], ee1_th ) ) && ( GT_32( hp_E[1], E_min_th ) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + /*( st_fx->music_hysteresis_fx == 0 ) &&*/ /* ... and in segment after AUDIO frames */ + ( LE_32( dE1, 237568 ) ) && /* Avoid on sharp energy spikes */ + ( LE_32( st_fx->old_dE1_fx, 237568 ) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst < 0 ) ) || /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + flag_low_relE ) /* low relative frame energy (only for SC-VBR) */ +#else + if ( ( ( LT_16( add( mean_voi3, corr_shift ), add( 22282, mean_voi3_offset ) ) ) && /* normalized correlation low */ + ( LT_16( add( st_fx->voicing_fx[2], corr_shift ), 25887 ) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32( ee[0], 640 ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32( ee[1], ee1_th ) ) && ( GT_32( hp_E[1], E_min_th ) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + /*( st_fx->music_hysteresis_fx == 0 ) &&*/ /* ... and in segment after AUDIO frames */ + ( LE_32( dE1, 237568 ) ) && /* Avoid on sharp energy spikes */ + ( LE_32( st_fx->old_dE1_fx, 237568 ) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst < 0 ) ) || /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + flag_low_relE ) /* low relative frame energy (only for SC-VBR) */ +#endif + { + coder_type = UNVOICED; + move16(); + } + } + ELSE + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + if ( ( ( LT_16( add_o( mean_voi3, corr_shift, &Overflow ), add( 22774, mean_voi3_offset ) ) ) && /* normalized correlation low */ + ( LT_16( add_sat( st_fx->voicing_fx[2], corr_shift ), 25887 ) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32( ee[0], 397 ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32( ee[1], 397 ) ) && ( GT_32( hp_E[1], E_min_th ) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + /*( st_fx->music_hysteresis_fx == 0 ) && */ /* ... and in segment after AUDIO frames */ + ( LE_32( dE1, 245760 ) ) && /* Avoid on sharp energy spikes */ + ( LE_32( st_fx->old_dE1_fx, 245760 ) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst < 0 ) ) /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + || ( flag_low_relE && ( LE_32( st_fx->old_dE1_fx, 245760 ) ) ) ) /* low relative frame energy (only for SC-VBR) */ +#else + if ( ( ( LT_16( add( mean_voi3, corr_shift ), add( 22774, mean_voi3_offset ) ) ) && /* normalized correlation low */ + ( LT_16( add( st_fx->voicing_fx[2], corr_shift ), 25887 ) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32( ee[0], 397 ) ) && ( GT_32( hp_E[0], E_min_th ) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32( ee[1], 397 ) ) && ( GT_32( hp_E[1], E_min_th ) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + /*( st_fx->music_hysteresis_fx == 0 ) && */ /* ... and in segment after AUDIO frames */ + ( LE_32( dE1, 245760 ) ) && /* Avoid on sharp energy spikes */ + ( LE_32( st_fx->old_dE1_fx, 245760 ) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst < 0 ) ) /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + || ( flag_low_relE && ( LE_32( st_fx->old_dE1_fx, 245760 ) ) ) ) /* low relative frame energy (only for SC-VBR) */ +#endif + { + coder_type = UNVOICED; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Decision about VC + *-----------------------------------------------------------------*/ + if ( st_fx->Opt_SC_VBR ) + { + hSC_VBR->set_ppp_generic = 0; + } + move16(); + + test(); + test(); + IF( EQ_16( st_fx->localVAD, 1 ) && EQ_16( coder_type, GENERIC ) && NE_16( last_core_orig, AMR_WB_CORE ) ) + { + dpit1 = abs_s( sub( T_op_fr[1], T_op_fr[0] ) ); + dpit2 = abs_s( sub( T_op_fr[2], T_op_fr[1] ) ); + dpit3 = abs_s( sub( T_op_fr[3], T_op_fr[2] ) ); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( GT_16( voicing_fr[0], 19825 ) ) && /* normalized correlation high in 1st sf. */ + ( GT_16( voicing_fr[1], 19825 ) ) && /* normalized correlation high in 2st sf. */ + ( GT_16( voicing_fr[2], 19825 ) ) && /* normalized correlation high in 3st sf. */ + ( GT_16( voicing_fr[3], 19825 ) ) && /* normalized correlation high in 4st sf. */ + ( GT_32( mean_ee, 256 ) ) && /* energy concentrated in low frequencies */ + ( LT_16( dpit1, 3 << 6 ) ) && + ( LT_16( dpit2, 3 << 6 ) ) && + ( LT_16( dpit3, 3 << 6 ) ) ) + { + coder_type = VOICED; + move16(); + } + ELSE IF( st_fx->Opt_SC_VBR && EQ_16( st_fx->input_bwidth, NB ) && LT_16( vadnoise, 20 << 8 ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( GT_16( voicing_fr[0], 8192 ) && /* normalized correlation high in 1st sf. */ + ( GT_16( voicing_fr[1], 8192 ) ) && /* normalized correlation high in 2st sf. */ + ( GT_16( voicing_fr[2], 8192 ) ) && /* normalized correlation high in 3st sf. */ + ( GT_16( voicing_fr[3], 8192 ) ) && /* normalized correlation high in 4st sf. */ + ( GT_32( mean_ee, 64 ) ) && /* energy concentrated in low frequencies */ + ( LT_16( dpit1, 5 << 6 ) ) && + ( LT_16( dpit2, 5 << 6 ) ) && + ( LT_16( dpit3, 5 << 6 ) ) ) + { + hSC_VBR->set_ppp_generic = 1; + move16(); + coder_type = VOICED; + move16(); + } + } + + /* set VOICED mode for frames with very stable pitch and high correlation + and avoid to switch to AUDIO/MUSIC later */ + voicing_m = mac_r( L_mac( L_mac( L_mult( voicing_fr[3], 8192 ), voicing_fr[2], 8192 ), voicing_fr[1], 8192 ), voicing_fr[0], 8192 ); + test(); + test(); + test(); + test(); + test(); + IF( *flag_spitch || ( LE_16( dpit1, 3 << 6 ) && LE_16( dpit2, 3 << 6 ) && LE_16( dpit3, 3 << 6 ) && + GT_16( voicing_m, 31130 ) && GT_16( st_fx->voicing_sm_fx, 31785 ) ) ) + { + coder_type = VOICED; + move16(); + *flag_spitch = 1; + move16(); /*to avoid switch to AUDIO/MUSIC later*/ + } + } + + /*-----------------------------------------------------------------* + * Channel-aware mode - set RF mode and total bitrate + *-----------------------------------------------------------------*/ + + st_fx->rf_mode = st_fx->Opt_RF_ON; + move16(); + + IF( EQ_16( coder_type, GENERIC ) ) + { + test(); + test(); + test(); + test(); + IF( ( LT_16( voicing_fr[0], 6554 ) ) && /* normalized correlation high in 2st sf. */ + ( LT_16( voicing_fr[1], 6554 ) ) && /* normalized correlation high in 2st sf. */ + ( LT_16( voicing_fr[2], 6554 ) ) && /* normalized correlation high in 3rd sf. */ + ( LT_16( voicing_fr[3], 6554 ) ) && /* normalized correlation high in 4th sf. */ + ( GT_16( vadnoise, 25 << 8 ) ) ) /* when speech is clean */ + + { + st_fx->rf_mode = 0; + move16(); + /* Current frame cannot be compressed to pack the partial redundancy;*/ + + IF( NE_16( st_fx->rf_mode, st_fx->Opt_RF_ON ) ) + { + core_coder_mode_switch_ivas_fx( st_fx, st_fx->last_total_brate, 0 ); + } + } + } + + /*-----------------------------------------------------------------* + * UNCLR classifier + *-----------------------------------------------------------------*/ + IF( hStereoClassif != NULL ) + { + test(); + test(); + test(); + test(); + test(); + IF( st_fx->element_mode > EVS_MONO && ( EQ_16( coder_type, GENERIC ) || EQ_16( coder_type, UNVOICED ) || coder_type == INACTIVE || st_fx->localVAD == 0 ) && LT_16( hStereoClassif->unclr_sw_enable_cnt[st_fx->idchan], MAX_UV_CNT ) ) + { + hStereoClassif->unclr_sw_enable_cnt[st_fx->idchan] = add( hStereoClassif->unclr_sw_enable_cnt[st_fx->idchan], 1 ); + move16(); + } + ELSE + { + hStereoClassif->unclr_sw_enable_cnt[st_fx->idchan] = 0; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update spike hysteresis parameters */ + test(); + if ( st_fx->spike_hyst >= 0 && LT_16( st_fx->spike_hyst, 2 ) ) + { + st_fx->spike_hyst = add( st_fx->spike_hyst, 1 ); + move16(); + } + + /* reset spike hysteresis */ + test(); + test(); + test(); + if ( ( GT_16( st_fx->spike_hyst, 1 ) ) && + ( GT_16( dE3, 5 << 8 ) || /* energy increases */ +#ifdef BASOP_NOGLOB + ( GT_16( relE, -3328 ) && ( GT_16( add_sat( mean_voi3, corr_shift ), 22774 ) ) ) ) ) /* normalized correlation is high */ +#else + ( GT_16( relE, -3328 ) && ( GT_16( add( mean_voi3, corr_shift ), 22774 ) ) ) ) ) /* normalized correlation is high */ +#endif + { + st_fx->spike_hyst = -1; + move16(); + } + + /* update tilt parameters */ + st_fx->ee_old_fx = ee[1]; + move32(); /*Q6*/ + st_fx->old_dE1_fx = dE1; + move32(); /*Q13*/ + + /* save the raw coder_type for various modules later in the codec (the reason is that e.g. UNVOICED is lost at higher rates) */ + st_fx->coder_type_raw = coder_type; + move16(); + + return coder_type; +} +#endif // IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * find_uv() + * + * Decision about coder type + *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED /*! r: coding type */ int16_t find_uv( Encoder_State *st, /* i/o: encoder state structure */ @@ -486,3 +1152,4 @@ int16_t find_uv( return coder_type; } +#endif diff --git a/lib_enc/find_wsp.c b/lib_enc/find_wsp.c index 97df5db897a0ec12625d376e68a48b5cd4fb4554..9e1db65a54da1e6127fe1f937b3de0f6426b3730 100644 --- a/lib_enc/find_wsp.c +++ b/lib_enc/find_wsp.c @@ -93,17 +93,24 @@ void find_wsp( return; } void ivas_find_wsp( - const Word16 L_frame, /* i : length of the frame */ - const Word16 L_subfr, /* i : length of subframe */ - const Word16 nb_subfr, /* i : number of subframes */ - const Word16 *A_fx, /* i : A(z) filter coefficients */ - Word16 *Aw_fx, /* o : weighted A(z) filter coefficients */ - const Word16 *speech_fx, /* i : pointer to the denoised speech frame */ - const Word16 tilt_fact, /* i : tilt factor */ - Word16 *wsp_fx, /* o : poitnter to the weighted speech frame */ - Word16 *mem_wsp_fx, /* i/o: W(Z) denominator memory */ - const Word16 gamma, /* i : weighting factor */ - const Word16 L_look /* i : look-ahead */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_subfr, /* i : length of subframe */ + const Word16 nb_subfr, /* i : number of subframes */ + const Word16 *A_fx, + /* i : A(z) filter coefficients */ // Q12 + Word16 *Aw_fx, + /* o : weighted A(z) filter coefficients */ // Q12 + const Word16 *speech_fx, + /* i : pointer to the denoised speech frame */ // Q_new + const Word16 tilt_fact, + /* i : tilt factor */ // Q15 + Word16 *wsp_fx, + /* o : poitnter to the weighted speech frame */ // Q_new + Word16 *mem_wsp_fx, + /* i/o: W(Z) denominator memory */ // Q_new + const Word16 gamma, + /* i : weighting factor */ // Q15 + const Word16 L_look /* i : look-ahead */ ) { Word16 *p_Aw_fx, tmp_fx; diff --git a/lib_enc/gain_enc_fx.c b/lib_enc/gain_enc_fx.c index abb66a8b899578dc0ad57e6b4db41bedec9d0e72..2e53060b5f5dc16dd086f0aa3ee16b23ea1e92ce 100644 --- a/lib_enc/gain_enc_fx.c +++ b/lib_enc/gain_enc_fx.c @@ -7,6 +7,7 @@ #include "rom_com_fx.h" /* Static table prototypes */ #include "rom_com.h" /* Static table prototypes */ //#include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ @@ -539,41 +540,33 @@ void gain_enc_mless_fx( return; } - -/*---------------------------------------------------------------------* - * gain_enc_SQ() - * - * Scalar Quantization of pitch and codebook gains without prediction - * - an initial predicted gain, gcode0, is first determined based on - * the predicted scaled innovation energy - * - a correction factor gamma = g_code / gcode0 is then vector quantized - * along with gain_pit - * - the mean-squared weighted error criterion is used for codebook search - *---------------------------------------------------------------------*/ - -void gain_enc_SQ_fx( +void gain_enc_mless_ivas_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 gains_mode[], /* i : gain bits */ + const Word16 element_mode, /* i : element mode */ + const Word16 L_frame, /* i : length of the frame */ const Word16 i_subfr, /* i : subframe index */ - const Word16 *xn, /* i : target vector Q_xn */ - const Word16 *yy1, /* i : zero-memory filtered adaptive excitation Q_xn */ - const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9 */ - const Word16 *code, /* i : algebraic excitation Q9 */ - const Word16 Es_pred, /* i : predicted scaled innovation energy Q8 */ - Word16 *gain_pit, /* o : quantized pitch gain Q14 */ - Word32 *gain_code, /* o : quantized codebook gain Q16 */ - Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12 */ - Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16 */ - Word16 *g_corr, /* i/o: correlations , ,, -2 and 2 */ - const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ - const Word16 Q_xn /* i : xn and y1 scaling */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *xn, /* i : target vector */ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation */ + const Word16 Q_xn, /* i : xn and y1 scaling */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word16 Es_pred, /* i : predicted scaled innovation energy */ + Word16 *gain_pit, /* o : quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ ) { - Word16 index, nBits_pitch, nBits_code; + + Word16 index, size, nBits, nBits2; Word16 gcode0, Ei, gain_code16; + const Word16 *qua_table; Word16 coeff[5], exp_coeff[5]; Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp; - Word32 L_tmp, L_tmp1, L_tmp2; Word16 tmp1, expg; Word16 exp1, exp2; @@ -587,18 +580,14 @@ void gain_enc_SQ_fx( * calculate the rest of the correlation coefficients * c2 = , c3 = -2, c4 = 2 *-----------------------------------------------------------------*/ - /*g_corr[1] *= -0.5;*/ - /*g_corr[2] = dotp( y2, y2, L_SUBFR ) + 0.01f;*/ - /*g_corr[3] = dotp( xn, y2, L_SUBFR ) - 0.02f;*/ - /*g_corr[4] = dotp( yy1, y2, L_SUBFR ) + 0.02f;*/ coeff[0] = g_corr[0]; move16(); exp_coeff[0] = g_corr[1]; move16(); - coeff[1] = g_corr[2]; - move16(); /* coeff[1] = xn yy1 */ - exp_coeff[1] = g_corr[3]; + coeff[1] = negate( g_corr[2] ); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add( g_corr[3], 1 ); move16(); /* Compute scalar product */ @@ -606,29 +595,28 @@ void gain_enc_SQ_fx( exp_coeff[2] = add( sub( exp, 18 ), shl( Q_xn, 1 ) ); move16(); /* -18 (y2 Q9) */ - /* Compute scalar product */ - coeff[3] = extract_h( Dot_product12( xn, y2, L_SUBFR, &exp ) ); - exp_coeff[3] = add( sub( exp, 9 ), Q_xn ); - move16(); /* -9 (y2 Q9), (xn y2) */ + /* Compute scalar product -2* */ + coeff[3] = extract_h( L_negate( Dot_product12( xn, y2, L_SUBFR, &exp ) ) ); + exp_coeff[3] = add( sub( exp, 9 - 1 ), Q_xn ); + move16(); /* -9 (y2 Q9), +1 (2 xn y2) */ - /* Compute scalar product */ - coeff[4] = extract_h( Dot_product12( yy1, y2, L_SUBFR, &exp ) ); - exp_coeff[4] = add( sub( exp, 9 ), Q_xn ); - move16(); /* -9 (y2 Q9), (y1 y2) */ + /* Compute scalar product 2* */ + coeff[4] = extract_h( Dot_product12( y1, y2, L_SUBFR, &exp ) ); + exp_coeff[4] = add( sub( exp, 9 - 1 ), Q_xn ); + move16(); /* -9 (y2 Q9), +1 (2 y1 y2) */ /*-----------------------------------------------------------------* * calculate the unscaled innovation energy * calculate the predicted gain code - * calculate optimal gains *-----------------------------------------------------------------*/ - /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;*/ - /**gain_inov = 1.0f / (float)sqrt( Ecode );*/ + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ L_tmp = Dot_product12( code, code, L_SUBFR, &exp_code ); exp_inov = sub( exp_code, 18 + 6 ); exp_code = sub( exp_code, 30 ); /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + /*----------------------------------------------------------------* * calculate the predicted gain code *----------------------------------------------------------------*/ @@ -665,171 +653,213 @@ void gain_enc_SQ_fx( /* 16384 < Pow2() <= 32767 */ exp_gcode0 = sub( exp_gcode0, 14 ); + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + nBits = gains_mode[shr( i_subfr, 6 )]; + move16(); - /*tmp1 = (g_corr[0]*g_corr[2]) - (g_corr[4]*g_corr[4]); - tmp2 = g_corr[1]/tmp1; - tmp1 = g_corr[3]/tmp1; - - *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp1); - *gain_code = (g_corr[0]*tmp1) - (g_corr[4]*tmp2);*/ - - /* *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp3); - = ((g_corr[1]*g_corr[2]) - (g_corr[3]*g_corr[4]))/tmp1;*/ - - /* *gain_code = (g_corr[0]*tmp3) - (g_corr[4]*tmp2); - = ((g_corr[3]*g_corr[0]) - (g_corr[1]*g_corr[4]))/tmp1;*/ + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( tc_subfr, 3 * L_SUBFR ) && EQ_16( i_subfr, 3 * L_SUBFR ) && EQ_16( L_frame, L_FRAME ) ) || + ( EQ_16( tc_subfr, 4 * L_SUBFR ) && EQ_16( i_subfr, 4 * L_SUBFR ) && EQ_16( L_frame, L_FRAME16k ) ) ) + { + /* *gain_pit = (g_corr[2]*tmp2) - (0.5f*g_corr[4]*tmp3); + = ((-0.5f*g_corr[1]*g_corr[2]) - (-0.25*g_corr[3]*g_corr[4]))/tmp1; + = ((0.25*g_corr[3]*g_corr[4]) - (0.5*g_corr[1]*g_corr[2]))/tmp1; */ - L_tmp1 = L_mult( coeff[0], coeff[2] ); /*Q31*/ - exp1 = add( exp_coeff[0], exp_coeff[2] ); + /* *gain_code = (g_corr[0]*tmp3) - (0.5f*g_corr[4]*tmp2); + = ((-0.5*g_corr[3]*g_corr[0]) - (-0.25*g_corr[1]*g_corr[4]))/tmp1; + = ((0.25*g_corr[1]*g_corr[4]) - (0.5*g_corr[0]*g_corr[3]))/tmp1; */ -#ifdef BASOP_NOGLOB - L_tmp2 = L_mult_o( coeff[4], coeff[4], &Overflow ); /*Q31*/ -#else - L_tmp2 = L_mult( coeff[4], coeff[4] ); /*Q31*/ -#endif - exp2 = add( exp_coeff[4], exp_coeff[4] ); + L_tmp1 = L_mult( coeff[0], coeff[2] ); /*Q31*/ + exp1 = add( exp_coeff[0], exp_coeff[2] ); - IF( GT_16( exp1, exp2 ) ) - { - L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ - exp_den = exp1; - move16(); - } - ELSE - { - L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ - exp_den = exp2; - move16(); - } - L_frac_den = L_sub( L_tmp1, L_tmp2 ); /*Q31*/ + L_tmp2 = L_shr( L_mult( coeff[4], coeff[4] ), 2 ); /*Q31*/ + exp2 = add( exp_coeff[4], exp_coeff[4] ); - frac_den = extract_h( L_frac_den ); - frac_den = s_max( frac_den, 1 ); - L_frac_den = L_max( L_frac_den, 1 ); - exp = norm_l( L_frac_den ); - tmp = div_s( shl( 1, sub( 14, exp ) ), frac_den ); /*Q(14-exp)*/ + IF( GT_16( exp1, exp2 ) ) + { + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_den = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_den = exp2; + move16(); + } + L_frac_den = L_sub( L_tmp1, L_tmp2 ); /*Q31*/ + frac_den = extract_h( L_frac_den ); + frac_den = s_max( frac_den, 1 ); + L_frac_den = L_max( L_frac_den, 1 ); + exp = norm_l( L_frac_den ); + tmp = div_s( shl( 1, sub( 14, exp ) ), frac_den ); /*Q(14-exp)*/ - L_tmp1 = L_mult( coeff[3], coeff[4] ); /*Q31*/ - exp1 = add( exp_coeff[3], exp_coeff[4] ); + L_tmp1 = L_shr( L_mult( coeff[3], coeff[4] ), 2 ); /*Q31*/ + exp1 = add( exp_coeff[3], exp_coeff[4] ); - L_tmp2 = L_mult( coeff[1], coeff[2] ); /*Q31*/ - exp2 = add( exp_coeff[1], exp_coeff[2] ); + L_tmp2 = L_shr( L_mult( coeff[1], coeff[2] ), 1 ); /*Q31*/ + exp2 = add( exp_coeff[1], exp_coeff[2] ); - IF( GT_16( exp1, exp2 ) ) - { - L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ - exp_num = exp1; - move16(); - } - ELSE - { - L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ - exp_num = exp2; - move16(); - } -#ifdef BASOP_NOGLOB - L_frac_num = L_sub_o( L_tmp2, L_tmp1, &Overflow ); /*Q31*/ -#else /* BASOP_NOGLOB */ - L_frac_num = L_sub( L_tmp2, L_tmp1 ); /*Q31*/ -#endif /* BASOP_NOGLOB */ + IF( GT_16( exp1, exp2 ) ) + { + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_num = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_num = exp2; + move16(); + } + L_frac_num = L_sub( L_tmp1, L_tmp2 ); /*Q31*/ - L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ - exp_div = sub( exp_num, exp_den ); + L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ + exp_div = sub( exp_num, exp_den ); #ifdef BASOP_NOGLOB - *gain_pit = round_fx_o( L_shl_o( L_div, add( exp, exp_div ), &Overflow ), &Overflow ); /*Q14*/ -#else /* BASOP_NOGLOB */ - *gain_pit = round_fx( L_shl( L_div, add( exp, exp_div ) ) ); /*Q14*/ -#endif /* BASOP_NOGLOB */ + *gain_pit = round_fx_o( L_shl_o( L_div, add( exp, exp_div ), &Overflow ), &Overflow ); /*Q14*/ +#else + *gain_pit = round_fx( L_shl( L_div, add( exp, exp_div ) ) ); /*Q14*/ +#endif - L_tmp1 = L_mult( coeff[1], coeff[4] ); /*Q31*/ - exp1 = add( exp_coeff[1], exp_coeff[4] ); + L_tmp1 = L_shr( L_mult( coeff[1], coeff[4] ), 2 ); /*Q31*/ + exp1 = add( exp_coeff[1], exp_coeff[4] ); - L_tmp2 = L_mult( coeff[0], coeff[3] ); /*Q31*/ - exp2 = add( exp_coeff[0], exp_coeff[3] ); + L_tmp2 = L_shr( L_mult( coeff[0], coeff[3] ), 1 ); /*Q31*/ + exp2 = add( exp_coeff[0], exp_coeff[3] ); - IF( GT_16( exp1, exp2 ) ) - { - L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ - exp_num = exp1; - } - ELSE - { - L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ - exp_num = exp2; - } -#ifdef BASOP_NOGLOB - L_frac_num = L_sub_o( L_tmp2, L_tmp1, &Overflow ); /*Q31*/ -#else /* BASOP_NOGLOB */ - L_frac_num = L_sub( L_tmp2, L_tmp1 ); /*Q31*/ -#endif /* BASOP_NOGLOB */ + IF( GT_16( exp1, exp2 ) ) + { + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_num = exp1; + } + ELSE + { + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_num = exp2; + } + L_frac_num = L_sub( L_tmp1, L_tmp2 ); /*Q31*/ - L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ - exp_div = sub( exp_num, exp_den ); + L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ + exp_div = sub( exp_num, exp_den ); #ifdef BASOP_NOGLOB - *gain_code = L_shl_sat( L_div, s_max( -31, sub( add( exp, exp_div ), 14 ) ) ); + *gain_code = L_shl_o( L_div, sub( add( exp, exp_div ), 14 ), &Overflow ); #else - *gain_code = L_shl( L_div, s_max( -31, sub( add( exp, exp_div ), 14 ) ) ); + *gain_code = L_shl( L_div, sub( add( exp, exp_div ), 14 ) ); #endif - move32(); /*Q16*/ - - *gain_pit = s_max( G_PITCH_MIN_Q14, s_min( *gain_pit, G_PITCH_MAX_Q14 ) ); + move32(); /*Q16*/ - /*-----------------------------------------------------------------* - * limit the pitch gain searching range (if indicated by clip_gain) - *-----------------------------------------------------------------*/ + *gain_pit = s_max( G_PITCH_MIN_TC192_Q14, s_min( *gain_pit, G_PITCH_MAX_TC192_Q14 ) ); - test(); - test(); - IF( EQ_16( clip_gain, 1 ) && GT_16( *gain_pit, 15565 ) ) - { - *gain_pit = 15565; - move16(); - } - ELSE IF( EQ_16( clip_gain, 2 ) && GT_16( *gain_pit, 10650 ) ) - { - *gain_pit = 10650; - move16(); - } - - /*-----------------------------------------------------------------* - * search for the best quantized values - *-----------------------------------------------------------------*/ - - nBits_pitch = gains_mode[shr( i_subfr, 6 )]; + /* set number of bits for two SQs */ + nBits2 = shr( add( nBits, 1 ), 1 ); + nBits = shr( nBits, 1 ); - /* set number of bits for two SQs */ - nBits_code = shr( add( nBits_pitch, 1 ), 1 ); - nBits_pitch = shr( nBits_pitch, 1 ); + /* gain_pit Q */ - /* gain_pit Q */ - /*tmp1 = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << nBits_pitch) - 1);*/ /* set quantization step */ - tmp1 = mult_r( G_PITCH_MAX_Q13, div_s( 1, sub( shl( 1, nBits_pitch ), 1 ) ) ); /*Q13*/ /* set quantization step */ + tmp1 = mult_r( G_PITCH_MAX_MINUS_MIN_TC192_Q13, div_s( 1, sub( shl( 1, nBits ), 1 ) ) ); /*Q13*/ /* set quantization step */ + index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_TC192_Q14, tmp1, shl( 1, nBits ) ); + move16(); + push_indice( hBstr, IND_GAIN_PIT, index, nBits ); - index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_Q14, tmp1, shl( 1, nBits_pitch ) ); - move16(); - push_indice_fx( hBstr, IND_GAIN_PIT, index, nBits_pitch ); + /* gain_code Q */ + /**gain_code /= gcode0;*/ + IF( gcode0 != 0 ) + { + tmp = div_s( 16384, gcode0 ); /*Q15*/ + L_tmp = Mult_32_16( *gain_code, tmp ); /*Q16*/ + *gain_code = L_shr( L_tmp, add( 14, exp_gcode0 ) ); /*Q16*/ + } - /* gain_code Q */ - /* *gain_code /= gcode0; */ - IF( gcode0 != 0 ) - { - tmp = div_s( 16384, gcode0 ); /*Q15*/ - L_tmp = Mult_32_16( *gain_code, tmp ); /*Q16*/ - *gain_code = L_shr( L_tmp, add( 14, exp_gcode0 ) ); /*Q16*/ + index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_TC192_Q14, LG10_G_CODE_MAX_TC192_Q13, nBits2, &expg ); + push_indice( hBstr, IND_GAIN_CODE, index, nBits2 ); + L_tmp = L_mult( gain_code16, gcode0 ); /*Q0*Q0 -> Q1*/ +#ifdef BASOP_NOGLOB + *gain_code = L_shl_o( L_tmp, add( add( expg, exp_gcode0 ), 15 ), &Overflow ); /*Q16*/ +#else + *gain_code = L_shl( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); /*Q16*/ +#endif } + ELSE + { + size = shl( 1, nBits ); - index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_Q14, LG10_G_CODE_MAX_Q13, nBits_code, &expg ); - push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits_code ); - L_tmp = L_mult( gain_code16, gcode0 ); /*Q0*Q0 -> Q1*/ -#ifdef BASOP_NOGLOB - *gain_code = L_shl_sat( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); + SWITCH( nBits ) + { + case 7: + { + qua_table = gain_qua_mless_7b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 30 ); + } + BREAK; + } + case 6: + { + qua_table = gain_qua_mless_6b_fx; + if ( GT_16( element_mode, EVS_MONO ) ) + { +#ifdef IVAS_CODE + qua_table = gain_qua_mless_6b_stereo; #else - *gain_code = L_shl( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); + // PMTE() #endif - move32(); /*Q16*/ + } + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 14 ); + } + BREAK; + } + case 5: + { + qua_table = gain_qua_mless_5b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 6 ); + } + BREAK; + } + default: + { + qua_table = gain_qua_mless_6b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 14 ); + } + BREAK; + } + } + + /* in case of AVQ inactive, limit the gain_pit to 0.65 */ + test(); + IF( EQ_16( clip_gain, 2 ) && EQ_16( nBits, 6 ) ) + { + size = sub( size, 36 ); + nBits = sub( nBits, 1 ); + } + + /*-----------------------------------------------------------------* + * search for the best quantizer + *-----------------------------------------------------------------*/ + index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, qua_table, size ); + push_indice( hBstr, IND_GAIN, index, nBits ); + } /* *norm_gain_code = *gain_code / *gain_inov; */ exp = sub( norm_s( *gain_inov ), 1 ); @@ -842,424 +872,1183 @@ void gain_enc_SQ_fx( return; } -/*-------------------------------------------------------------------* - * gain_enc_gaus() +/*---------------------------------------------------------------------* + * gain_enc_SQ() * - * Quantization of gain for Gaussian codebook - *-------------------------------------------------------------------*/ -Word16 gain_enc_gaus_fx( /* o : Return index of quantization */ - Word32 *gain, /* i/o: Code gain to quantize */ - const Word16 bits, /* i : number of bits to quantize */ - const Word16 lowBound, /* i : lower bound of quantizer (dB) Q8 */ - const Word16 stepSize, /* i : Step size choice Q14 */ - const Word16 inv_stepSize /* i : Step size choice Q15 */ + * Scalar Quantization of pitch and codebook gains without prediction + * - an initial predicted gain, gcode0, is first determined based on + * the predicted scaled innovation energy + * - a correction factor gamma = g_code / gcode0 is then vector quantized + * along with gain_pit + * - the mean-squared weighted error criterion is used for codebook search + *---------------------------------------------------------------------*/ + +void gain_enc_SQ_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *xn, /* i : target vector Q_xn */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation Q_xn */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9 */ + const Word16 *code, /* i : algebraic excitation Q9 */ + const Word16 Es_pred, /* i : predicted scaled innovation energy Q8 */ + Word16 *gain_pit, /* o : quantized pitch gain Q14 */ + Word32 *gain_code, /* o : quantized codebook gain Q16 */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12 */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16 */ + Word16 *g_corr, /* i/o: correlations , ,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + const Word16 Q_xn /* i : xn and y1 scaling */ ) { - Word16 index, exp_gain, frac_gain, wtmp; - Word16 enr_q, wenr; - Word32 Ltmp, enr; + Word16 index, nBits_pitch, nBits_code; + Word16 gcode0, Ei, gain_code16; + Word16 coeff[5], exp_coeff[5]; + Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp; + + Word32 L_tmp, L_tmp1, L_tmp2; + Word16 tmp1, expg; + Word16 exp1, exp2; + Word16 exp_num, exp_den, exp_div, frac_den; + Word32 L_frac_num, L_frac_den, L_div; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif - /*enr = 20.0 * log10(*gain + 0.001) codebook gain in dB */ - exp_gain = norm_l( *gain ); - frac_gain = Log2_norm_lc( L_shl( *gain, exp_gain ) ); - exp_gain = sub( 30 - 16, exp_gain ); - enr = Mpy_32_16( exp_gain, frac_gain, LG10 ); /* Output in Q13 */ - wenr = extract_h( L_shl( enr, 8 + 3 ) ); + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2 + *-----------------------------------------------------------------*/ + /*g_corr[1] *= -0.5;*/ + /*g_corr[2] = dotp( y2, y2, L_SUBFR ) + 0.01f;*/ + /*g_corr[3] = dotp( xn, y2, L_SUBFR ) - 0.02f;*/ + /*g_corr[4] = dotp( yy1, y2, L_SUBFR ) + 0.02f;*/ - /*----------------------------------------------------------------* - * Quantize linearly the log E - *----------------------------------------------------------------*/ + coeff[0] = g_corr[0]; + move16(); + exp_coeff[0] = g_corr[1]; + move16(); + coeff[1] = g_corr[2]; + move16(); /* coeff[1] = xn yy1 */ + exp_coeff[1] = g_corr[3]; + move16(); - wtmp = sub( wenr, lowBound ); /* Q8 */ + /* Compute scalar product */ + coeff[2] = extract_h( Dot_product12( y2, y2, L_SUBFR, &exp ) ); + exp_coeff[2] = add( sub( exp, 18 ), shl( Q_xn, 1 ) ); + move16(); /* -18 (y2 Q9) */ - index = extract_l( L_shr( L_mac( 8388608, wtmp, inv_stepSize ), 16 + 8 ) ); + /* Compute scalar product */ + coeff[3] = extract_h( Dot_product12( xn, y2, L_SUBFR, &exp ) ); + exp_coeff[3] = add( sub( exp, 9 ), Q_xn ); + move16(); /* -9 (y2 Q9), (xn y2) */ - /* index [0 (1< */ + coeff[4] = extract_h( Dot_product12( yy1, y2, L_SUBFR, &exp ) ); + exp_coeff[4] = add( sub( exp, 9 ), Q_xn ); + move16(); /* -9 (y2 Q9), (y1 y2) */ - Ltmp = L_mac( L_shl( lowBound, 7 ), index, stepSize ); - enr_q = round_fx( L_shl( Ltmp, 16 - 7 ) ); /* enr_q Q8 */ + /*-----------------------------------------------------------------* + * calculate the unscaled innovation energy + * calculate the predicted gain code + * calculate optimal gains + *-----------------------------------------------------------------*/ + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;*/ + /**gain_inov = 1.0f / (float)sqrt( Ecode );*/ - /* gain = (float)pow( 10.0f, enr/20.0f ) quantized codebook gain */ - enr = L_mult( enr_q, 21772 ); /* 0.166096 in Q17 -> Q26 */ - enr = L_shr( enr, 10 ); /*Q26->Q16*/ - frac_gain = L_Extract_lc( enr, &exp_gain ); + L_tmp = Dot_product12( code, code, L_SUBFR, &exp_code ); + exp_inov = sub( exp_code, 18 + 6 ); + exp_code = sub( exp_code, 30 ); - Ltmp = Pow2( 14, frac_gain ); /* Put 14 as exponent */ - exp_gain = sub( exp_gain, 14 ); /* Retreive exponent of wtmp */ -#ifdef BASOP_NOGLOB - *gain = L_shl_o( Ltmp, add( 16, exp_gain ), &Overflow ); -#else - *gain = L_shl( Ltmp, add( 16, exp_gain ) ); -#endif - move32(); /*Q16*/ + /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + tmp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, tmp ) ); + tmp = add( 30 - 18 - 6 - 1, sub( exp_code, tmp ) ); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + L_tmp1 = Mpy_32_16( tmp, frac, 12330 ); /* Q13 */ + Ei = round_fx( L_shl( L_tmp1, 11 ) ); /* Q8 */ - return index; -} -/*-----------------------------------------------------------------* - * gain_enc_tc() - * - * Search and quantization of gain_code for subframes (in the - * beginning of frame) without pulses in TC - 3b coding. - * In this case: - * - gain_pit = 0 - * - gain_code - scalar quantization (no prediciton history used) - *-----------------------------------------------------------------*/ -void gain_enc_tc_fx( - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ - const Word16 gains_mode[], /* i : gain bits */ - const Word16 i_subfr, /* i : subframe index */ - const Word16 xn_fx[], /* i : target vector */ - const Word16 y2_fx[], /* i : zero-memory filtered algebraic codebook excitation */ - const Word16 code_fx[], /* i : algebraic excitation */ - const Word16 Es_pred_fx, /* i : predicted scaled innovation energy */ - Word16 *gain_pit_fx, /* o : Pitch gain / Quantized pitch gain */ - Word32 *gain_code_fx, /* o : quantized codebook gain */ - Word16 *gain_inov_fx, /* o : innovation gain */ - Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation */ - const Word16 Q_xn /* i : xn and y1 scaling Q0 */ -) -{ - Word16 i, index = 0, nBits, num, den, exp_num, exp_den; - Word16 Ei_fx, g_code_fx, gcode0_fx; - Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac, tmp16; - Word32 L_tmp, L_tmp1; - Word16 wgain_code = 0, gain_code16; - *gain_pit_fx = 0; - move16(); - /*----------------------------------------------------------------* - * get number of bits for gain quantization - *----------------------------------------------------------------*/ - nBits = gains_mode[shr( i_subfr, 6 )]; + /* predicted codebook gain */ + gcode0 = sub( Es_pred, Ei ); /* Q8 */ + + /*---------------------------------------------------------------* + * Decode codebook gain and the adaptive excitation low-pass + * filtering factor (Finalize computation ) + *---------------------------------------------------------------*/ + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = Isqrt_lc( L_tmp, &exp_inov ); + *gain_inov = extract_h( L_shl( L_tmp, sub( exp_inov, 3 ) ) ); /* gain_inov in Q12 */ + /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */ /*----------------------------------------------------------------* - * find the code pitch (for current subframe) + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) *----------------------------------------------------------------*/ - /**gain_code = dotp( xn, y2, L_SUBFR )/( dotp( y2, y2, L_SUBFR ) + 0.01f );*/ - /* Compute scalar product */ - L_tmp = Dot_product( y2_fx, y2_fx, L_SUBFR ); /* -18 (y2 Q9) */ - exp_den = norm_l( L_tmp ); - den = extract_h( L_shl( L_tmp, exp_den ) ); - exp_den = sub( add( exp_den, 18 ), shl( Q_xn, 1 ) ); + L_tmp = L_mult( gcode0, 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ - /* Compute scalar product */ - L_tmp1 = Dot_product( xn_fx, y2_fx, L_SUBFR ); /* -9 (y2 Q9) */ - exp_num = sub( norm_l( L_tmp1 ), 1 ); - num = extract_h( L_shl( L_tmp1, exp_num ) ); - exp_num = sub( add( exp_num, 8 ), Q_xn ); + gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub( exp_gcode0, 14 ); - tmp16 = s_or( shr( num, 16 ), 1 ); /* extract sign if num < 0 tmp16 = -1 else tmp16 = 1 */ - num = abs_s( num ); - /*----------------------------------------------------------------* - * compute gain = xy/yy - *----------------------------------------------------------------*/ - g_code_fx = div_s( num, den ); + /*tmp1 = (g_corr[0]*g_corr[2]) - (g_corr[4]*g_corr[4]); + tmp2 = g_corr[1]/tmp1; + tmp1 = g_corr[3]/tmp1; + + *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp1); + *gain_code = (g_corr[0]*tmp1) - (g_corr[4]*tmp2);*/ + + /* *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp3); + = ((g_corr[1]*g_corr[2]) - (g_corr[3]*g_corr[4]))/tmp1;*/ + + /* *gain_code = (g_corr[0]*tmp3) - (g_corr[4]*tmp2); + = ((g_corr[3]*g_corr[0]) - (g_corr[1]*g_corr[4]))/tmp1;*/ + + L_tmp1 = L_mult( coeff[0], coeff[2] ); /*Q31*/ + exp1 = add( exp_coeff[0], exp_coeff[2] ); - i = sub( exp_num, exp_den ); /* Gain_trans in Q7 */ - g_code_fx = i_mult2( g_code_fx, tmp16 ); /* apply sign */ #ifdef BASOP_NOGLOB - *gain_code_fx = L_shr_sat( L_deposit_l( g_code_fx ), i ); + L_tmp2 = L_mult_o( coeff[4], coeff[4], &Overflow ); /*Q31*/ #else - *gain_code_fx = L_shr( L_deposit_l( g_code_fx ), i ); + L_tmp2 = L_mult( coeff[4], coeff[4] ); /*Q31*/ #endif - move32(); + exp2 = add( exp_coeff[4], exp_coeff[4] ); - /*----------------------------------------------------------------* - * calculate the predicted gain code - * decode codebook gain - *----------------------------------------------------------------*/ + IF( GT_16( exp1, exp2 ) ) + { + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_den = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_den = exp2; + move16(); + } + L_frac_den = L_sub( L_tmp1, L_tmp2 ); /*Q31*/ - *gain_pit_fx = 0; - move16(); + frac_den = extract_h( L_frac_den ); + frac_den = s_max( frac_den, 1 ); + L_frac_den = L_max( L_frac_den, 1 ); + exp = norm_l( L_frac_den ); + tmp = div_s( shl( 1, sub( 14, exp ) ), frac_den ); /*Q(14-exp)*/ - /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; - *gain_inov = 1.0f / (float)sqrt( Ecode );*/ - L_tmp = Dot_product12( code_fx, code_fx, L_SUBFR, &expg ); - expg = sub( expg, 18 + 6 ); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ - expg2 = expg; - move16(); - L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ - move32(); - L_tmp = Isqrt_lc( L_tmp, &expg ); + L_tmp1 = L_mult( coeff[3], coeff[4] ); /*Q31*/ + exp1 = add( exp_coeff[3], exp_coeff[4] ); - *gain_inov_fx = extract_h( L_shl( L_tmp, sub( expg, 3 ) ) ); - move16(); /* gain_inov in Q12 */ + L_tmp2 = L_mult( coeff[1], coeff[2] ); /*Q31*/ + exp2 = add( exp_coeff[1], exp_coeff[2] ); - /*Ei = 10 * (float)log10( Ecode );*/ - e_tmp = norm_l( L_tmp1 ); - f_tmp = Log2_norm_lc( L_shl( L_tmp1, e_tmp ) ); - e_tmp = sub( expg2, add( 1, e_tmp ) ); - L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 12330 ); /* Q13 */ /* 10*log10(2) in Q12*/ - Ei_fx = round_fx( L_shl( L_tmp1, 11 ) ); /* Q8 */ - /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ - gcode0_fx = sub( Es_pred_fx, Ei_fx ); /* Q8 */ - /*-----------------------------------------------------------------* - * gcode0 = pow(10.0, gcode0/20) - * = pow(2, 3.321928*gcode0/20) - * = pow(2, 0.166096*gcode0) - *-----------------------------------------------------------------*/ - L_tmp = L_mult( gcode0_fx, 21771 ); /* *0.166096 in Q17 -> Q26 */ - L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ - frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ - gcode0_fx = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ - exp_gcode0 = sub( exp_gcode0, 14 ); - IF( GT_16( nBits, 3 ) ) + IF( GT_16( exp1, exp2 ) ) { - /*g_code = *gain_code / gcode0;*/ - IF( gcode0_fx != 0 ) - { - tmp16 = div_s( 16384, gcode0_fx ); /*Q15*/ - L_tmp = Mult_32_16( *gain_code_fx, tmp16 ); /*Q16*/ - *gain_code_fx = L_shr( L_tmp, add( 14, exp_gcode0 ) ); /*Q16*/ - } - ELSE - { - *gain_code_fx = MAX_32; - move32(); - } + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_num = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_num = exp2; + move16(); + } +#ifdef BASOP_NOGLOB + L_frac_num = L_sub_o( L_tmp2, L_tmp1, &Overflow ); /*Q31*/ +#else /* BASOP_NOGLOB */ + L_frac_num = L_sub( L_tmp2, L_tmp1 ); /*Q31*/ +#endif /* BASOP_NOGLOB */ - /*index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits );*/ - index = gain_quant_fx( gain_code_fx, &gain_code16, LG10_G_CODE_MIN_TC_Q14, LG10_G_CODE_MAX_TC_Q13, nBits, &expg ); + L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ + exp_div = sub( exp_num, exp_den ); - /**gain_code = g_code * gcode0;*/ - L_tmp = L_mult( gain_code16, gcode0_fx ); /*Q0*Q0 -> Q1*/ - *gain_code_fx = L_shl( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); /*Q16*/ - move32(); +#ifdef BASOP_NOGLOB + *gain_pit = round_fx_o( L_shl_o( L_div, add( exp, exp_div ), &Overflow ), &Overflow ); /*Q14*/ +#else /* BASOP_NOGLOB */ + *gain_pit = round_fx( L_shl( L_div, add( exp, exp_div ) ) ); /*Q14*/ +#endif /* BASOP_NOGLOB */ - push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); + L_tmp1 = L_mult( coeff[1], coeff[4] ); /*Q31*/ + exp1 = add( exp_coeff[1], exp_coeff[4] ); + + L_tmp2 = L_mult( coeff[0], coeff[3] ); /*Q31*/ + exp2 = add( exp_coeff[0], exp_coeff[3] ); + + IF( GT_16( exp1, exp2 ) ) + { + L_tmp2 = L_shr( L_tmp2, sub( exp1, exp2 ) ); /*Q31*/ + exp_num = exp1; } ELSE { - index = N_GAIN_CODE_TC - 1; - move16(); - FOR( i = 0; i < N_GAIN_CODE_TC - 1; i++ ) - { - L_tmp = L_mult( tbl_gain_code_tc_quant_mean[i], gcode0_fx ); /* Q13*Q0 -> Q14 */ - L_tmp = L_shl( L_tmp, add( exp_gcode0, 2 ) ); /* Q14 -> Q16 */ + L_tmp1 = L_shr( L_tmp1, sub( exp2, exp1 ) ); /*Q31*/ + exp_num = exp2; + } +#ifdef BASOP_NOGLOB + L_frac_num = L_sub_o( L_tmp2, L_tmp1, &Overflow ); /*Q31*/ +#else /* BASOP_NOGLOB */ + L_frac_num = L_sub( L_tmp2, L_tmp1 ); /*Q31*/ +#endif /* BASOP_NOGLOB */ + + L_div = Mult_32_16( L_frac_num, tmp ); /*Q(30-exp)*/ + exp_div = sub( exp_num, exp_den ); - IF( LT_32( *gain_code_fx, L_tmp ) ) - { - index = i; - move16(); - BREAK; - } - } - /*----------------------------------------------------------------* - * 3-bit -> 2-bit encoding - *----------------------------------------------------------------*/ - IF( EQ_16( nBits, 2 ) ) - { - /* 2-bit -> 3-bit decoding */ - index = shr( index, 1 ); - wgain_code = tbl_gain_code_tc_fx[shl( index, 1 )]; - move16(); - /**gain_code *= gcode0;*/ - L_tmp = L_mult( wgain_code, gcode0_fx ); /* Q13*Q0 -> Q14 */ - *gain_code_fx = L_shl( L_tmp, add( exp_gcode0, 2 ) ); - move32(); /* Q14 -> Q16 */ - push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); - } - ELSE /* nBits == 3 */ - { - wgain_code = tbl_gain_code_tc_fx[index]; - move16(); - /**gain_code *= gcode0;*/ - L_tmp = L_mult( wgain_code, gcode0_fx ); /* Q13*Q0 -> Q14 */ #ifdef BASOP_NOGLOB - *gain_code_fx = L_shl_sat( L_tmp, add( exp_gcode0, 2 ) ); + *gain_code = L_shl_sat( L_div, s_max( -31, sub( add( exp, exp_div ), 14 ) ) ); #else - *gain_code_fx = L_shl( L_tmp, add( exp_gcode0, 2 ) ); + *gain_code = L_shl( L_div, s_max( -31, sub( add( exp, exp_div ), 14 ) ) ); #endif - move32(); /* Q14 -> Q16 */ - push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); - } + move32(); /*Q16*/ + + *gain_pit = s_max( G_PITCH_MIN_Q14, s_min( *gain_pit, G_PITCH_MAX_Q14 ) ); + + /*-----------------------------------------------------------------* + * limit the pitch gain searching range (if indicated by clip_gain) + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( EQ_16( clip_gain, 1 ) && GT_16( *gain_pit, 15565 ) ) + { + *gain_pit = 15565; + move16(); + } + ELSE IF( EQ_16( clip_gain, 2 ) && GT_16( *gain_pit, 10650 ) ) + { + *gain_pit = 10650; + move16(); } /*-----------------------------------------------------------------* - * decode normalized codebook gain + * search for the best quantized values *-----------------------------------------------------------------*/ - /**norm_gain_code = *gain_code / *gain_inov;*/ - expg = sub( norm_s( *gain_inov_fx ), 1 ); - expg = s_max( expg, 0 ); - tmp_fx = div_s( shr( 8192, expg ), *gain_inov_fx ); - *norm_gain_code_fx = L_shr( Mult_32_16( *gain_code_fx, tmp_fx ), sub( 1, expg ) ); + nBits_pitch = gains_mode[shr( i_subfr, 6 )]; + + /* set number of bits for two SQs */ + nBits_code = shr( add( nBits_pitch, 1 ), 1 ); + nBits_pitch = shr( nBits_pitch, 1 ); + + /* gain_pit Q */ + /*tmp1 = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << nBits_pitch) - 1);*/ /* set quantization step */ + tmp1 = mult_r( G_PITCH_MAX_Q13, div_s( 1, sub( shl( 1, nBits_pitch ), 1 ) ) ); /*Q13*/ /* set quantization step */ + + index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_Q14, tmp1, shl( 1, nBits_pitch ) ); + move16(); + push_indice_fx( hBstr, IND_GAIN_PIT, index, nBits_pitch ); + + /* gain_code Q */ + /* *gain_code /= gcode0; */ + IF( gcode0 != 0 ) + { + tmp = div_s( 16384, gcode0 ); /*Q15*/ + L_tmp = Mult_32_16( *gain_code, tmp ); /*Q16*/ + *gain_code = L_shr( L_tmp, add( 14, exp_gcode0 ) ); /*Q16*/ + } + + index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_Q14, LG10_G_CODE_MAX_Q13, nBits_code, &expg ); + push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits_code ); + L_tmp = L_mult( gain_code16, gcode0 ); /*Q0*Q0 -> Q1*/ +#ifdef BASOP_NOGLOB + *gain_code = L_shl_sat( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); +#else + *gain_code = L_shl( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); +#endif + move32(); /*Q16*/ + + /* *norm_gain_code = *gain_code / *gain_inov; */ + exp = sub( norm_s( *gain_inov ), 1 ); + exp = s_max( exp, 0 ); + + tmp = div_s( shr( 8192, exp ), *gain_inov ); + *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); move32(); + return; } -/*-----------------------------------------------------------------* - * Find_Opt_gainQ_fx() + +/*-------------------------------------------------------------------* + * gain_enc_gaus() * - * Find the best quantizer - *-----------------------------------------------------------------*/ -static Word16 Find_Opt_gainQ_fx( - Word16 *coeff, - Word16 *exp_coeff, - Word16 *gain_pit, - Word32 *gain_code, - Word16 gcode0, - Word16 exp_gcode0, - const Word16 *cdbk, /* i : Codebook used */ - const Word16 size /* i : size of Codebook used */ + * Quantization of gain for Gaussian codebook + *-------------------------------------------------------------------*/ +Word16 gain_enc_gaus_fx( /* o : Return index of quantization */ + Word32 *gain, /* i/o: Code gain to quantize */ + const Word16 bits, /* i : number of bits to quantize */ + const Word16 lowBound, /* i : lower bound of quantizer (dB) Q8 */ + const Word16 stepSize, /* i : Step size choice Q14 */ + const Word16 inv_stepSize /* i : Step size choice Q15 */ ) { - Word16 index, i, j; - const Word16 *p; - Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; - Word32 dist_min; - Word16 coeff_lo[5]; - Word16 exp_max[5]; - Word16 exp_code, e_max; - Word32 L_tmp, L_tmp1; + Word16 index, exp_gain, frac_gain, wtmp; + Word16 enr_q, wenr; + Word32 Ltmp, enr; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif + /*enr = 20.0 * log10(*gain + 0.001) codebook gain in dB */ + exp_gain = norm_l( *gain ); + frac_gain = Log2_norm_lc( L_shl( *gain, exp_gain ) ); + exp_gain = sub( 30 - 16, exp_gain ); + enr = Mpy_32_16( exp_gain, frac_gain, LG10 ); /* Output in Q13 */ + wenr = extract_h( L_shl( enr, 8 + 3 ) ); /*----------------------------------------------------------------* - * Find the best quantizer - * ~~~~~~~~~~~~~~~~~~~~~~~ - * Before doing the computation we need to align exponents of coeff[] - * to be sure to have the maximum precision. - * - * In the table the pitch gains are in Q14, the code gains are in Q9 and - * are multiply by gcode0 which have been multiply by 2^exp_gcode0. - * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code - * we divide by 2^15. - * Considering all the scaling above we have: - * - * exp_code = exp_gcode0-9+15 = exp_gcode0+6 - * - * g_pitch*g_pitch = -14-14+15 - * g_pitch = -14 - * g_code*g_code = (2*exp_code)+15 - * g_code = exp_code - * g_pitch*g_code = -14 + exp_code +15 - * - * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 - * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 - * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) - * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code - * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + * Quantize linearly the log E *----------------------------------------------------------------*/ - exp_code = add( exp_gcode0, 6 ); + wtmp = sub( wenr, lowBound ); /* Q8 */ - exp_max[0] = sub( exp_coeff[0], 13 ); - move16(); - exp_max[1] = sub( exp_coeff[1], 14 ); - move16(); - exp_max[2] = add( exp_coeff[2], add( 15, shl( exp_code, 1 ) ) ); + index = extract_l( L_shr( L_mac( 8388608, wtmp, inv_stepSize ), 16 + 8 ) ); + + /* index [0 (1< Q26 */ + enr = L_shr( enr, 10 ); /*Q26->Q16*/ + frac_gain = L_Extract_lc( enr, &exp_gain ); + + Ltmp = Pow2( 14, frac_gain ); /* Put 14 as exponent */ + exp_gain = sub( exp_gain, 14 ); /* Retreive exponent of wtmp */ +#ifdef BASOP_NOGLOB + *gain = L_shl_o( Ltmp, add( 16, exp_gain ), &Overflow ); +#else + *gain = L_shl( Ltmp, add( 16, exp_gain ) ); +#endif + move32(); /*Q16*/ + + return index; +} +/*-----------------------------------------------------------------* + * gain_enc_tc() + * + * Search and quantization of gain_code for subframes (in the + * beginning of frame) without pulses in TC - 3b coding. + * In this case: + * - gain_pit = 0 + * - gain_code - scalar quantization (no prediciton history used) + *-----------------------------------------------------------------*/ +void gain_enc_tc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 xn_fx[], /* i : target vector */ + const Word16 y2_fx[], /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 code_fx[], /* i : algebraic excitation */ + const Word16 Es_pred_fx, /* i : predicted scaled innovation energy */ + Word16 *gain_pit_fx, /* o : Pitch gain / Quantized pitch gain */ + Word32 *gain_code_fx, /* o : quantized codebook gain */ + Word16 *gain_inov_fx, /* o : innovation gain */ + Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation */ + const Word16 Q_xn /* i : xn and y1 scaling Q0 */ +) +{ + Word16 i, index = 0, nBits, num, den, exp_num, exp_den; + Word16 Ei_fx, g_code_fx, gcode0_fx; + Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac, tmp16; + Word32 L_tmp, L_tmp1; + Word16 wgain_code = 0, gain_code16; + *gain_pit_fx = 0; move16(); - exp_max[3] = add( exp_coeff[3], exp_code ); + /*----------------------------------------------------------------* + * get number of bits for gain quantization + *----------------------------------------------------------------*/ + nBits = gains_mode[shr( i_subfr, 6 )]; + + /*----------------------------------------------------------------* + * find the code pitch (for current subframe) + *----------------------------------------------------------------*/ + + /**gain_code = dotp( xn, y2, L_SUBFR )/( dotp( y2, y2, L_SUBFR ) + 0.01f );*/ + /* Compute scalar product */ + L_tmp = Dot_product( y2_fx, y2_fx, L_SUBFR ); /* -18 (y2 Q9) */ + exp_den = norm_l( L_tmp ); + den = extract_h( L_shl( L_tmp, exp_den ) ); + exp_den = sub( add( exp_den, 18 ), shl( Q_xn, 1 ) ); + + /* Compute scalar product */ + L_tmp1 = Dot_product( xn_fx, y2_fx, L_SUBFR ); /* -9 (y2 Q9) */ + exp_num = sub( norm_l( L_tmp1 ), 1 ); + num = extract_h( L_shl( L_tmp1, exp_num ) ); + exp_num = sub( add( exp_num, 8 ), Q_xn ); + + tmp16 = s_or( shr( num, 16 ), 1 ); /* extract sign if num < 0 tmp16 = -1 else tmp16 = 1 */ + num = abs_s( num ); + + /*----------------------------------------------------------------* + * compute gain = xy/yy + *----------------------------------------------------------------*/ + g_code_fx = div_s( num, den ); + + i = sub( exp_num, exp_den ); /* Gain_trans in Q7 */ + g_code_fx = i_mult2( g_code_fx, tmp16 ); /* apply sign */ +#ifdef BASOP_NOGLOB + *gain_code_fx = L_shr_sat( L_deposit_l( g_code_fx ), i ); +#else + *gain_code_fx = L_shr( L_deposit_l( g_code_fx ), i ); +#endif + move32(); + + /*----------------------------------------------------------------* + * calculate the predicted gain code + * decode codebook gain + *----------------------------------------------------------------*/ + + *gain_pit_fx = 0; move16(); - exp_max[4] = add( exp_coeff[4], add( 1, exp_code ) ); + + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12( code_fx, code_fx, L_SUBFR, &expg ); + expg = sub( expg, 18 + 6 ); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc( L_tmp, &expg ); + + *gain_inov_fx = extract_h( L_shl( L_tmp, sub( expg, 3 ) ) ); + move16(); /* gain_inov in Q12 */ + + /*Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l( L_tmp1 ); + f_tmp = Log2_norm_lc( L_shl( L_tmp1, e_tmp ) ); + e_tmp = sub( expg2, add( 1, e_tmp ) ); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 12330 ); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei_fx = round_fx( L_shl( L_tmp1, 11 ) ); /* Q8 */ + /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0_fx = sub( Es_pred_fx, Ei_fx ); /* Q8 */ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult( gcode0_fx, 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ + gcode0_fx = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + exp_gcode0 = sub( exp_gcode0, 14 ); + IF( GT_16( nBits, 3 ) ) + { + /*g_code = *gain_code / gcode0;*/ + IF( gcode0_fx != 0 ) + { + tmp16 = div_s( 16384, gcode0_fx ); /*Q15*/ + L_tmp = Mult_32_16( *gain_code_fx, tmp16 ); /*Q16*/ + *gain_code_fx = L_shr( L_tmp, add( 14, exp_gcode0 ) ); /*Q16*/ + } + ELSE + { + *gain_code_fx = MAX_32; + move32(); + } + + /*index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits );*/ + index = gain_quant_fx( gain_code_fx, &gain_code16, LG10_G_CODE_MIN_TC_Q14, LG10_G_CODE_MAX_TC_Q13, nBits, &expg ); + + /**gain_code = g_code * gcode0;*/ + L_tmp = L_mult( gain_code16, gcode0_fx ); /*Q0*Q0 -> Q1*/ + *gain_code_fx = L_shl( L_tmp, add( add( expg, exp_gcode0 ), 15 ) ); /*Q16*/ + move32(); + + push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); + } + ELSE + { + index = N_GAIN_CODE_TC - 1; + move16(); + FOR( i = 0; i < N_GAIN_CODE_TC - 1; i++ ) + { + L_tmp = L_mult( tbl_gain_code_tc_quant_mean[i], gcode0_fx ); /* Q13*Q0 -> Q14 */ + L_tmp = L_shl( L_tmp, add( exp_gcode0, 2 ) ); /* Q14 -> Q16 */ + + IF( LT_32( *gain_code_fx, L_tmp ) ) + { + index = i; + move16(); + BREAK; + } + } + /*----------------------------------------------------------------* + * 3-bit -> 2-bit encoding + *----------------------------------------------------------------*/ + IF( EQ_16( nBits, 2 ) ) + { + /* 2-bit -> 3-bit decoding */ + index = shr( index, 1 ); + wgain_code = tbl_gain_code_tc_fx[shl( index, 1 )]; + move16(); + /**gain_code *= gcode0;*/ + L_tmp = L_mult( wgain_code, gcode0_fx ); /* Q13*Q0 -> Q14 */ + *gain_code_fx = L_shl( L_tmp, add( exp_gcode0, 2 ) ); + move32(); /* Q14 -> Q16 */ + push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); + } + ELSE /* nBits == 3 */ + { + wgain_code = tbl_gain_code_tc_fx[index]; + move16(); + /**gain_code *= gcode0;*/ + L_tmp = L_mult( wgain_code, gcode0_fx ); /* Q13*Q0 -> Q14 */ +#ifdef BASOP_NOGLOB + *gain_code_fx = L_shl_sat( L_tmp, add( exp_gcode0, 2 ) ); +#else + *gain_code_fx = L_shl( L_tmp, add( exp_gcode0, 2 ) ); +#endif + move32(); /* Q14 -> Q16 */ + push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits ); + } + } + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub( norm_s( *gain_inov_fx ), 1 ); + expg = s_max( expg, 0 ); + + tmp_fx = div_s( shr( 8192, expg ), *gain_inov_fx ); + *norm_gain_code_fx = L_shr( Mult_32_16( *gain_code_fx, tmp_fx ), sub( 1, expg ) ); + move32(); + return; +} +/*-----------------------------------------------------------------* + * Find_Opt_gainQ_fx() + * + * Find the best quantizer + *-----------------------------------------------------------------*/ +static Word16 Find_Opt_gainQ_fx( + Word16 *coeff, + Word16 *exp_coeff, + Word16 *gain_pit, + Word32 *gain_code, + Word16 gcode0, + Word16 exp_gcode0, + const Word16 *cdbk, /* i : Codebook used */ + const Word16 size /* i : size of Codebook used */ +) +{ + Word16 index, i, j; + const Word16 *p; + Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; + Word32 dist_min; + Word16 coeff_lo[5]; + Word16 exp_max[5]; + Word16 exp_code, e_max; + Word32 L_tmp, L_tmp1; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to align exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q9 and + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0-9+15 = exp_gcode0+6 + * + * g_pitch*g_pitch = -14-14+15 + * g_pitch = -14 + * g_code*g_code = (2*exp_code)+15 + * g_code = exp_code + * g_pitch*g_code = -14 + exp_code +15 + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + exp_code = add( exp_gcode0, 6 ); + + exp_max[0] = sub( exp_coeff[0], 13 ); + move16(); + exp_max[1] = sub( exp_coeff[1], 14 ); + move16(); + exp_max[2] = add( exp_coeff[2], add( 15, shl( exp_code, 1 ) ) ); + move16(); + exp_max[3] = add( exp_coeff[3], exp_code ); + move16(); + exp_max[4] = add( exp_coeff[4], add( 1, exp_code ) ); + move16(); + + /* Find maximum exponant */ + e_max = exp_max[0]; + move16(); + FOR( i = 1; i < 5; i++ ) + { + e_max = s_max( exp_max[i], e_max ); + } + + /* align coeff[] and save in special 32 bit double precision */ + FOR( i = 0; i < 5; i++ ) + { + j = add( sub( e_max, exp_max[i] ), 2 ); /* /4 to avoid overflow */ + L_tmp = L_deposit_h( coeff[i] ); + L_tmp = L_shr( L_tmp, j ); + L_Extract( L_tmp, &coeff[i], &coeff_lo[i] ); + coeff_lo[i] = shr( coeff_lo[i], 3 ); /* lo >> 3 */ + move16(); + } + + /* searching of codebook */ + p = cdbk; + move16(); + dist_min = L_deposit_h( MAX_16 ); + index = 0; + move16(); + FOR( i = 0; i < size; i++ ) + { + g_pitch = *p++; + move16(); + g_code = *p++; + move16(); + + g_code = mult_r( g_code, gcode0 ); + g2_pitch = mult_r( g_pitch, g_pitch ); + g_pit_cod = mult_r( g_code, g_pitch ); + L_tmp = L_mult( g_code, g_code ); + g2_code_lo = L_Extract_lc( L_tmp, &g2_code ); + + L_tmp = L_mult( coeff[2], g2_code_lo ); + L_tmp = L_shr( L_tmp, 3 ); + L_tmp = L_mac( L_tmp, coeff_lo[0], g2_pitch ); + L_tmp = L_mac( L_tmp, coeff_lo[1], g_pitch ); + L_tmp = L_mac( L_tmp, coeff_lo[2], g2_code ); + L_tmp = L_mac( L_tmp, coeff_lo[3], g_code ); + L_tmp = L_mac( L_tmp, coeff_lo[4], g_pit_cod ); + L_tmp = L_shr( L_tmp, 12 ); + L_tmp = L_mac( L_tmp, coeff[0], g2_pitch ); + L_tmp = L_mac( L_tmp, coeff[1], g_pitch ); + L_tmp = L_mac( L_tmp, coeff[2], g2_code ); + L_tmp = L_mac( L_tmp, coeff[3], g_code ); + L_tmp = L_mac( L_tmp, coeff[4], g_pit_cod ); + +#ifdef BASOP_NOGLOB + L_tmp1 = L_sub_o( L_tmp, dist_min, &Overflow ); +#else /* BASOP_NOGLOB */ + L_tmp1 = L_sub( L_tmp, dist_min ); +#endif /* BASOP_NOGLOB */ + if ( L_tmp1 < 0 ) + { + index = i; + move16(); + } + dist_min = L_min( L_tmp, dist_min ); + } + + p = &cdbk[add( index, index )]; + move16(); + + *gain_pit = *p++; /* selected pitch gain in Q14 */ + move16(); + g_code = *p++; /* selected code gain in Q9 */ + move16(); + + L_tmp = L_mult( g_code, gcode0 ); /* Q9*Q0 -> Q10 */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( L_tmp, add( exp_gcode0, 6 ) ); /* Q10 -> Q16 */ +#else + L_tmp = L_shl( L_tmp, add( exp_gcode0, 6 ) ); /* Q10 -> Q16 */ +#endif + *gain_code = L_tmp; /* gain of code in Q16 */ + move16(); + return index; +} +/*---------------------------------------------------------------------* + * gain_enc_lbr() + * + * Quantization of pitch and codebook gains without prediction (memory-less) + * in ACELP at 6.6 and 7.5 kbps + * - the gain codebooks and gain estimation constants are different in each subframe + * - the estimated gain, gcode0, is first determined based on + * classification and/or previous quantized gains (from previous subframes in the current frame) + * - a correction factor gamma = g_code / gcode0 is then vector quantized + * along with gain_pit + * - the mean-squared error criterion is used for codebook search + *---------------------------------------------------------------------*/ + +void gain_enc_lbr_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *xn, /* i : target vector Q_xn*/ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn*/ + const Word16 Q_xn, /* i : xn and y1 format */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9*/ + const Word16 *code, /* i : algebraic excitation Q9*/ + Word16 *gain_pit, /* o : quantized pitch gain Q14*/ + Word32 *gain_code, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + const int16_t L_subfr /* i : subframe length */ +) +{ + + Word16 index = 0, size, nBits, n_pred, ctype; + const Word16 *b, *cdbk = 0; + Word16 gcode0, aux[10]; + Word16 coeff[5], exp_coeff[5]; + Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp, L_subfr_sf; + Word32 L_tmp, L_tmp1, L_inov; + + L_subfr_sf = 6; + move16(); + if ( GT_16( L_subfr, L_SUBFR ) ) + { + L_subfr_sf = 7; + move16(); + } + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2, c5* = + * c5* - not necessary to calculate + *-----------------------------------------------------------------*/ + + coeff[0] = g_corr[0]; + move16(); + exp_coeff[0] = g_corr[1]; + move16(); + coeff[1] = negate( g_corr[2] ); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add( g_corr[3], 1 ); + move16(); + + /* Compute scalar product */ +#ifdef DEBUG + if ( L_subfr != L_SUBFR ) + { + PMT( "Entire function needs review to accommode for L_subfr > L_SUBFR" ); + } +#endif + coeff[2] = extract_h( Dot_product12( y2, y2, L_subfr, &exp ) ); + exp_coeff[2] = add( sub( exp, 18 ), shl( Q_xn, 1 ) ); /* -18 (y2 Q9) */ + move16(); + + /* Compute scalar product -2* */ + + coeff[3] = extract_h( L_negate( Dot_product12( xn, y2, L_subfr, &exp ) ) ); + exp_coeff[3] = add( sub( exp, 9 - 1 ), Q_xn ); /* -9 (y2 Q9), +1 (2 xn y2) */ + move16(); + + /* Compute scalar product 2* */ + + coeff[4] = extract_h( Dot_product12( y1, y2, L_subfr, &exp ) ); + exp_coeff[4] = add( sub( exp, 9 - 1 ), Q_xn ); /* -9 (y2 Q9), +1 (2 yy1 y2) */ + move16(); + + /*g_corr[2] += 0.01F; g_corr[3] -= 0.02F; g_corr[4] += 0.02F;*/ + + /*Ecode = ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt(Ecode);*/ + L_tmp = Dot_product12( code, code, L_subfr, &exp_code ); + L_inov = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + /* exp_code: -18 (code in Q9), -6 (/L_SUBFR), -31 (L_tmp Q31->Q0) */ + /* output gain_inov*/ + exp_inov = sub( exp_code, add( 18, L_subfr_sf ) ); + L_inov = Isqrt_lc( L_inov, &exp_inov ); + *gain_inov = extract_h( L_shl( L_inov, sub( exp_inov, 3 ) ) ); /* gain_inov in Q12 */ + + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gains_mode[shr( i_subfr, L_subfr_sf )]; + move16(); + size = shl( 1, nBits ); + + ctype = shl( sub( coder_type, 1 ), 1 ); + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + IF( i_subfr == 0 ) + { + b = b_1sfr_fx; + move16(); + n_pred = 2; + move16(); + + SWITCH( nBits ) + { + case 8: + { + cdbk = gp_gamma_1sfr_8b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 60 ); + } + move16(); + BREAK; + } + case 7: + { + cdbk = gp_gamma_1sfr_7b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 27 ); + } + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_1sfr_6b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 10 ); + } + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl( ctype, 12 ); + + /* gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); + gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ + + exp_code = sub( exp_code, 18 + 6 + 1 ); + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); + exp = sub( exp_code, exp ); + L_tmp1 = Mpy_32_16( exp, frac, 24660 ); /* Q14 */ /* 10*log10(2) in Q13*/ + + L_tmp = Dot_product( b, aux, n_pred ); /*Q25*/ + L_tmp = Mult_32_16( L_tmp, 320 ); /*Q14, 20 in Q4*/ + L_tmp = L_sub( L_tmp, L_tmp1 ); /*Q14*/ + + gcode0 = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + + L_tmp = L_mult( gcode0, 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ + + gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub( exp_gcode0, 14 ); + index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); + + gc_mem[0] = *gain_code; + move16(); /*Q16*/ + gp_mem[0] = *gain_pit; + move16(); /*Q14*/ + } + ELSE IF( EQ_16( i_subfr, L_SUBFR ) || EQ_16( L_subfr, 2 * L_SUBFR ) ) + { + b = b_2sfr_fx; + move16(); + n_pred = 4; + move16(); + + switch ( nBits ) + { + case 7: + { + cdbk = gp_gamma_2sfr_7b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 30 ); + } + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_2sfr_6b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 12 ); + } + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl( ctype, 12 ); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l( gc_mem[0] ); + frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_1sfr_fx)=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); + move16(); /* Q16 */ + aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + + aux[3] = shr( gp_mem[0], 2 ); + move16(); /*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product( b, aux, n_pred ); /*Q25*/ + L_tmp = Mult_32_16( L_tmp, 27213 ); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr( L_tmp, 7 ); /* From Q23 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ + + gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub( exp_gcode0, 14 ); + + index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); + gc_mem[1] = *gain_code; + move32(); + gp_mem[1] = *gain_pit; + move16(); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + b = b_3sfr_fx; + move16(); + n_pred = 6; + move16(); + IF( EQ_16( nBits, 7 ) ) + { +#ifdef IVAS_CODE + cdbk = gp_gamma_3sfr_7b_fx; + if ( clip_gain == 1 ) + { + size -= 28; + } +#else + // PMT("gp_gamma_3sfr_7b_fx is missing") +#endif + } + ELSE + { + cdbk = gp_gamma_3sfr_6b_fx; + move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 11 ); + } + } + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl( ctype, 12 ); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l( gc_mem[0] ); + frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ + aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l( gc_mem[1] ); + frac = Log2_norm_lc( L_shl( gc_mem[1], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ + aux[3] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + + aux[4] = shr( gp_mem[0], 2 ); + move16(); /*Q12*/ + aux[5] = shr( gp_mem[1], 2 ); + move16(); /*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product( b, aux, n_pred ); /*Q25*/ + L_tmp = Mult_32_16( L_tmp, 27213 ); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr( L_tmp, 7 ); /* From Q23 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ - /* Find maximum exponant */ - e_max = exp_max[0]; - move16(); - FOR( i = 1; i < 5; i++ ) - { - e_max = s_max( exp_max[i], e_max ); - } + gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub( exp_gcode0, 14 ); - /* align coeff[] and save in special 32 bit double precision */ - FOR( i = 0; i < 5; i++ ) - { - j = add( sub( e_max, exp_max[i] ), 2 ); /* /4 to avoid overflow */ - L_tmp = L_deposit_h( coeff[i] ); - L_tmp = L_shr( L_tmp, j ); - L_Extract( L_tmp, &coeff[i], &coeff_lo[i] ); - coeff_lo[i] = shr( coeff_lo[i], 3 ); /* lo >> 3 */ + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to align exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q9 and + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0-9+15 = exp_gcode0+6 + * + * g_pitch*g_pitch = -14-14+15 + * g_pitch = -14 + * g_code*g_code = (2*exp_code)+15 + * g_code = exp_code + * g_pitch*g_code = -14 + exp_code +15 + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); + + gc_mem[2] = *gain_code; + move32(); + gp_mem[2] = *gain_pit; move16(); } - - /* searching of codebook */ - p = cdbk; - move16(); - dist_min = L_deposit_h( MAX_16 ); - index = 0; - move16(); - FOR( i = 0; i < size; i++ ) + ELSE IF( EQ_16( i_subfr, 3 * L_SUBFR ) ) { - g_pitch = *p++; + b = b_4sfr_fx; move16(); - g_code = *p++; + n_pred = 8; move16(); - - g_code = mult_r( g_code, gcode0 ); - g2_pitch = mult_r( g_pitch, g_pitch ); - g_pit_cod = mult_r( g_code, g_pitch ); - L_tmp = L_mult( g_code, g_code ); - g2_code_lo = L_Extract_lc( L_tmp, &g2_code ); - - L_tmp = L_mult( coeff[2], g2_code_lo ); - L_tmp = L_shr( L_tmp, 3 ); - L_tmp = L_mac( L_tmp, coeff_lo[0], g2_pitch ); - L_tmp = L_mac( L_tmp, coeff_lo[1], g_pitch ); - L_tmp = L_mac( L_tmp, coeff_lo[2], g2_code ); - L_tmp = L_mac( L_tmp, coeff_lo[3], g_code ); - L_tmp = L_mac( L_tmp, coeff_lo[4], g_pit_cod ); - L_tmp = L_shr( L_tmp, 12 ); - L_tmp = L_mac( L_tmp, coeff[0], g2_pitch ); - L_tmp = L_mac( L_tmp, coeff[1], g_pitch ); - L_tmp = L_mac( L_tmp, coeff[2], g2_code ); - L_tmp = L_mac( L_tmp, coeff[3], g_code ); - L_tmp = L_mac( L_tmp, coeff[4], g_pit_cod ); - -#ifdef BASOP_NOGLOB - L_tmp1 = L_sub_o( L_tmp, dist_min, &Overflow ); -#else /* BASOP_NOGLOB */ - L_tmp1 = L_sub( L_tmp, dist_min ); -#endif /* BASOP_NOGLOB */ - if ( L_tmp1 < 0 ) + IF( EQ_16( nBits, 7 ) ) { - index = i; +#ifdef IVAS_CODE + cdbk = gp_gamma_4sfr_7b_fx; + if ( clip_gain == 1 ) + { + size -= 25; + } +#else + // PMT("gp_gamma_4sfr_7b_fx is missing") +#endif + } + ELSE + { + cdbk = gp_gamma_4sfr_6b_fx; move16(); + if ( EQ_16( clip_gain, 1 ) ) + { + size = sub( size, 11 ); + move16(); + } } - dist_min = L_min( L_tmp, dist_min ); - } + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl( ctype, 12 ); + move16(); - p = &cdbk[add( index, index )]; - move16(); + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l( gc_mem[0] ); + frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ + aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ - *gain_pit = *p++; /* selected pitch gain in Q14 */ - move16(); - g_code = *p++; /* selected code gain in Q9 */ - move16(); + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l( gc_mem[1] ); + frac = Log2_norm_lc( L_shl( gc_mem[1], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ + aux[3] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ - L_tmp = L_mult( g_code, gcode0 ); /* Q9*Q0 -> Q10 */ -#ifdef BASOP_NOGLOB - L_tmp = L_shl_sat( L_tmp, add( exp_gcode0, 6 ) ); /* Q10 -> Q16 */ -#else - L_tmp = L_shl( L_tmp, add( exp_gcode0, 6 ) ); /* Q10 -> Q16 */ -#endif - *gain_code = L_tmp; /* gain of code in Q16 */ - move16(); - return index; + + /*aux[4] = (float)log10(gc_mem[2]); + = log2(gc_mem[2])*log10(2);*/ + exp = norm_l( gc_mem[2] ); + frac = Log2_norm_lc( L_shl( gc_mem[2], exp ) ); + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[2])=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ + aux[4] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + + aux[5] = shr( gp_mem[0], 2 ); + move16(); /*Q12*/ + aux[6] = shr( gp_mem[1], 2 ); + move16(); /*Q12*/ + aux[7] = shr( gp_mem[2], 2 ); + move16(); /*Q12*/ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product( b, aux, n_pred ); /*Q25*/ + L_tmp = Mult_32_16( L_tmp, 27213 ); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr( L_tmp, 7 ); /* From Q23 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ + + gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub( exp_gcode0, 14 ); + + index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); + } + + /* *norm_gain_code = *gain_code / *gain_inov; */ + exp = sub( norm_s( *gain_inov ), 1 ); + exp = s_max( exp, 0 ); + + tmp = div_s( shr( 8192, exp ), *gain_inov ); + *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); + move32(); + { + push_indice_fx( hBstr, IND_GAIN, index, nBits ); + } + return; } -/*---------------------------------------------------------------------* - * gain_enc_lbr() - * - * Quantization of pitch and codebook gains without prediction (memory-less) - * in ACELP at 6.6 and 7.5 kbps - * - the gain codebooks and gain estimation constants are different in each subframe - * - the estimated gain, gcode0, is first determined based on - * classification and/or previous quantized gains (from previous subframes in the current frame) - * - a correction factor gamma = g_code / gcode0 is then vector quantized - * along with gain_pit - * - the mean-squared error criterion is used for codebook search - *---------------------------------------------------------------------*/ -void gain_enc_lbr_fx( +void gain_enc_lbr_ivas_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 gains_mode[], /* i : gain bits */ const Word16 coder_type, /* i : coding type */ @@ -1274,8 +2063,8 @@ void gain_enc_lbr_fx( Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/ Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/ Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/ - Word32 gc_mem[], /* i/o: gain_code from previous subframes */ - Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */ + Word32 gc_mem[], /* i/o: gain_code from previous subframes Q16*/ + Word16 gp_mem[], /* i/o: gain_pitch from previous subframes Q14*/ const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ const int16_t L_subfr /* i : subframe length */ ) @@ -1344,7 +2133,7 @@ void gain_enc_lbr_fx( /* output gain_inov*/ exp_inov = sub( exp_code, add( 18, L_subfr_sf ) ); L_inov = Isqrt_lc( L_inov, &exp_inov ); - *gain_inov = extract_h( L_shl( L_inov, sub( exp_inov, 3 ) ) ); /* gain_inov in Q12 */ + *gain_inov = extract_h( L_shl_sat( L_inov, sub( exp_inov, 3 ) ) ); /* gain_inov in Q12 */ /*-----------------------------------------------------------------* @@ -1412,8 +2201,8 @@ void gain_enc_lbr_fx( aux[1] = shl( ctype, 12 ); /* gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); - gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); - gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); + gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ exp_code = sub( exp_code, 18 + 6 + 1 ); exp = norm_l( L_tmp ); @@ -1438,8 +2227,8 @@ void gain_enc_lbr_fx( frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ - /* output of Pow2() will be: */ - /* 16384 < Pow2() <= 32767 */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ exp_gcode0 = sub( exp_gcode0, 14 ); index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); @@ -1465,7 +2254,6 @@ void gain_enc_lbr_fx( { size = sub( size, 30 ); } - move16(); BREAK; } case 6: @@ -1476,7 +2264,6 @@ void gain_enc_lbr_fx( { size = sub( size, 12 ); } - move16(); BREAK; } } @@ -1488,13 +2275,13 @@ void gain_enc_lbr_fx( move16(); /*aux[2] = (float)log10(gc_mem[0]); - = log2(gc_mem[0])*log10(2);*/ + = log2(gc_mem[0])*log10(2);*/ exp = norm_l( gc_mem[0] ); frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); - exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_1sfr_fx)=16*/ - L_tmp1 = Mpy_32_16( exp, frac, 9864 ); - move16(); /* Q16 */ + exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_1sfr_fx)=16*/ + L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + move16(); aux[3] = shr( gp_mem[0], 2 ); move16(); /*Q12*/ @@ -1509,8 +2296,8 @@ void gain_enc_lbr_fx( frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ - /* output of Pow2() will be: */ - /* 16384 < Pow2() <= 32767 */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ exp_gcode0 = sub( exp_gcode0, 14 ); index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); @@ -1527,15 +2314,11 @@ void gain_enc_lbr_fx( move16(); IF( EQ_16( nBits, 7 ) ) { -#ifdef IVAS_CODE cdbk = gp_gamma_3sfr_7b_fx; - if ( clip_gain == 1 ) + if ( EQ_16( clip_gain, 1 ) ) { - size -= 28; + size = sub( size, 28 ); } -#else - // PMT("gp_gamma_3sfr_7b_fx is missing") -#endif } ELSE { @@ -1553,7 +2336,7 @@ void gain_enc_lbr_fx( move16(); /*aux[2] = (float)log10(gc_mem[0]); - = log2(gc_mem[0])*log10(2);*/ + = log2(gc_mem[0])*log10(2);*/ exp = norm_l( gc_mem[0] ); frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[0])=16*/ @@ -1561,12 +2344,13 @@ void gain_enc_lbr_fx( aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ /*aux[3] = (float)log10(gc_mem[1]); - = log2(gc_mem[1])*log10(2);*/ + = log2(gc_mem[1])*log10(2);*/ exp = norm_l( gc_mem[1] ); frac = Log2_norm_lc( L_shl( gc_mem[1], exp ) ); exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[1])=16*/ L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ aux[3] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + move16(); aux[4] = shr( gp_mem[0], 2 ); move16(); /*Q12*/ @@ -1583,8 +2367,8 @@ void gain_enc_lbr_fx( frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ - /* output of Pow2() will be: */ - /* 16384 < Pow2() <= 32767 */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ exp_gcode0 = sub( exp_gcode0, 14 ); /*----------------------------------------------------------------* @@ -1629,15 +2413,12 @@ void gain_enc_lbr_fx( move16(); IF( EQ_16( nBits, 7 ) ) { -#ifdef IVAS_CODE cdbk = gp_gamma_4sfr_7b_fx; - if ( clip_gain == 1 ) + move16(); + if ( EQ_16( clip_gain, 1 ) ) { - size -= 25; + size = sub( size, 25 ); } -#else - // PMT("gp_gamma_4sfr_7b_fx is missing") -#endif } ELSE { @@ -1646,7 +2427,6 @@ void gain_enc_lbr_fx( if ( EQ_16( clip_gain, 1 ) ) { size = sub( size, 11 ); - move16(); } } /* calculate predicted gain */ @@ -1656,48 +2436,50 @@ void gain_enc_lbr_fx( move16(); /*aux[2] = (float)log10(gc_mem[0]); - = log2(gc_mem[0])*log10(2);*/ + = log2(gc_mem[0])*log10(2);*/ exp = norm_l( gc_mem[0] ); frac = Log2_norm_lc( L_shl( gc_mem[0], exp ) ); exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[0])=16*/ L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ aux[2] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + move16(); /*aux[3] = (float)log10(gc_mem[1]); - = log2(gc_mem[1])*log10(2);*/ + = log2(gc_mem[1])*log10(2);*/ exp = norm_l( gc_mem[1] ); frac = Log2_norm_lc( L_shl( gc_mem[1], exp ) ); exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[1])=16*/ L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ aux[3] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ - + move16(); /*aux[4] = (float)log10(gc_mem[2]); - = log2(gc_mem[2])*log10(2);*/ + = log2(gc_mem[2])*log10(2);*/ exp = norm_l( gc_mem[2] ); frac = Log2_norm_lc( L_shl( gc_mem[2], exp ) ); exp = sub( sub( 30, exp ), 16 ); /*Q_format(gc_mem[2])=16*/ L_tmp1 = Mpy_32_16( exp, frac, 9864 ); /* Q16 */ aux[4] = round_fx( L_shl( L_tmp1, 12 ) ); /* Q12 */ + move16(); aux[5] = shr( gp_mem[0], 2 ); move16(); /*Q12*/ aux[6] = shr( gp_mem[1], 2 ); move16(); /*Q12*/ aux[7] = shr( gp_mem[2], 2 ); - move16(); /*Q12*/ - /*-----------------------------------------------------------------* - * gcode0 = pow(10.0, dotp(b, aux, n_pred) - * = pow(2, 3.321928*dotp(b, aux, n_pred) - *-----------------------------------------------------------------*/ + move16(); /*Q12*/ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ L_tmp = Dot_product( b, aux, n_pred ); /*Q25*/ L_tmp = Mult_32_16( L_tmp, 27213 ); /* *3.321928 in Q13 -> Q23 */ L_tmp = L_shr( L_tmp, 7 ); /* From Q23 to Q16 */ frac = L_Extract_lc( L_tmp, &exp_gcode0 ); /* Extract exponent of gcode0 */ gcode0 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ - /* output of Pow2() will be: */ - /* 16384 < Pow2() <= 32767 */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ exp_gcode0 = sub( exp_gcode0, 14 ); index = Find_Opt_gainQ_fx( coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size ); @@ -1711,7 +2493,7 @@ void gain_enc_lbr_fx( *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); move32(); { - push_indice_fx( hBstr, IND_GAIN, index, nBits ); + push_indice( hBstr, IND_GAIN, index, nBits ); } return; } diff --git a/lib_enc/gp_clip_fx.c b/lib_enc/gp_clip_fx.c index c3c2dc0d01c5185868d2223fc29be789880a8892..6a98b1d4717d051ae5d77572ab209279fd098aef 100644 --- a/lib_enc/gp_clip_fx.c +++ b/lib_enc/gp_clip_fx.c @@ -497,15 +497,15 @@ void gp_clip_test_lsf_ivas_fx( test(); test(); - IF( EQ_32( core_brate, ACELP_6k60 ) || EQ_32( core_brate, ACELP_8k85 ) || GT_16( element_mode, EVS_MONO ) ) + IF( EQ_32( core_brate, ACELP_6k60 ) || EQ_32( core_brate, ACELP_8k85 ) || ( element_mode > EVS_MONO ) ) { - IF( GT_16( dist, DIST_ISF_MAX_IO ) ) + if ( GT_16( dist, DIST_ISF_MAX_IO ) ) { dist = DIST_ISF_MAX_IO; move16(); } } - ELSE if ( GT_16( dist, DIST_ISF_MAX ) ) + ELSE IF( GT_16( dist, DIST_ISF_MAX ) ) { dist = DIST_ISF_MAX; move16(); diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c index 0caa1ea0d5702ba8a5ba603c00c941f2974691e4..b2e599e1d5ed9332a0fc65a9fca5ab9e5ac97810 100644 --- a/lib_enc/hq_core_enc.c +++ b/lib_enc/hq_core_enc.c @@ -53,6 +53,368 @@ * HQ core encoder *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void hq_core_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 *audio_fx, /* i : input audio signal Q0 */ + const Word16 input_frame_orig, /* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag, /* i : Voicing flag for FER method selection */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word16 i, is_transient, num_bits, extra_unused; + + Word32 t_audio_fx[L_FRAME48k_EXT]; + Word16 wtda_audio_fx16[2 * L_FRAME48k]; + Word32 wtda_audio_fx32[2 * L_FRAME48k]; + Word16 two_frames_buffer[2 * L_FRAME48k]; + Word16 tmp; + Word16 Aq_old_fx[M + 1]; + Word16 output_fx[L_FRAME16k]; + Word16 Q_audio; + Word16 out_q = 0, old_q = 0; + move16(); + move16(); + Word16 inner_frame, input_frame, L_frame; + Word16 L_spec, overlap, nz, tcx_offset; + Word16 left_overlap, right_overlap; + BSTR_ENC_HANDLE hBstr = st->hBstr; + Word16 q = 0; + Word16 exp; + move16(); + + push_wmops( "hq_core_enc" ); + + set16_fx( wtda_audio_fx16, 0, 2 * L_FRAME48k ); + set32_fx( wtda_audio_fx32, 0, 2 * L_FRAME48k ); + st->Nb_ACELP_frames = 0; + move16(); + set_zero_fx( t_audio_fx, L_FRAME48k ); + /* set input_frame length */ + input_frame = input_frame_orig; + + /* Sanity check, it should never happen at the encoder side (no BFI) */ + IF( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) + { + st->hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW; + } + ELSE + { + st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; + } + move16(); + st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + + /*-------------------------------------------------------------------------- + * Preprocessing in the first HQ frame after ACELP frame + * Find the number of bits for PVQ coding + * Write signaling information + *--------------------------------------------------------------------------*/ + + num_bits = BASOP_Util_Divide3232_Scale( st->total_brate, FRAMES_PER_SEC, &exp ); + num_bits = shr( num_bits, sub( 15, exp ) ); + extra_unused = 0; + move16(); + + /*-------------------------------------------------------------------------- + * Detect signal transition + *--------------------------------------------------------------------------*/ + + is_transient = detect_transient_fx( audio_fx, input_frame, 0, st ); + move16(); + + test(); + test(); + IF( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || EQ_16( st->last_core, AMR_WB_CORE ) ) ) + { + /*-------------------------------------------------------------------------- + * IVAS switching frame + *--------------------------------------------------------------------------*/ + + L_spec = input_frame; + left_overlap = -1; + right_overlap = -1; + move16(); + move16(); + move16(); + + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, TRANSITION_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX, &L_spec, wtda_audio_fx16, 1, 1 ); + + q = st->hTcxEnc->q_speech_TCX; + move16(); + Q_audio = sub( Q16, q ); + TCX_MDCT( wtda_audio_fx16, t_audio_fx, &Q_audio, left_overlap, sub( L_spec, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, st->element_mode ); + Q_audio = sub( Q31, Q_audio ); + Copy_Scale_sig_16_32( wtda_audio_fx16, wtda_audio_fx32, 2 * L_FRAME48k, sub( Q_audio, q ) ); + + inner_frame = inner_frame_tbl[st->bwidth]; + L_spec = l_spec_ext_tbl[st->bwidth]; + is_transient = 0; + move16(); + move16(); + move16(); + } + ELSE + { + /*-------------------------------------------------------------------------- + * Windowing and time-domain aliasing + * DCT transform + *--------------------------------------------------------------------------*/ + Q_audio = 0; + move16(); + floatToFixed_arr( st->old_input_signal, st->old_input_signal_fx, 0, add( L_FRAME48k, add( L_FRAME48k, NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ) ) ); + st->q_inp = 0; + move16(); + Copy( st->old_input_signal_fx, two_frames_buffer, input_frame ); + Copy( audio_fx, two_frames_buffer + input_frame, input_frame ); + + wtda_fx( two_frames_buffer + input_frame, &Q_audio, wtda_audio_fx32, NULL, 0, + st->hTcxCfg->tcx_last_overlap_mode, st->hTcxCfg->tcx_curr_overlap_mode, input_frame ); + + test(); + IF( st->last_core == ACELP_CORE || EQ_16( st->last_core, AMR_WB_CORE ) ) + { + /* Preprocessing in the first HQ frame after ACELP frame */ + core_switching_hq_prepare_enc_fx( st, &num_bits, input_frame, wtda_audio_fx32, two_frames_buffer + input_frame ); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + IF( GT_16( num_bits, ACELP_48k_BITS ) ) + { + extra_unused = sub( num_bits, ACELP_48k_BITS ); + num_bits = ACELP_48k_BITS; + move16(); + } + } + + Word16 tmp_q = Q_audio; + move16(); + direct_transform_fx( wtda_audio_fx32, t_audio_fx, is_transient, input_frame, &Q_audio, st->element_mode ); + scale_sig32( wtda_audio_fx32, L_FRAME48k_EXT, sub( Q_audio, tmp_q ) ); + + /* scale coefficients to their nominal level (8kHz) */ + IF( NE_16( input_frame, NORM_MDCT_FACTOR ) ) + { + UWord16 lsb; + tmp = mult_r( input_frame, 410 / 2 ); /* 1/8000 in Q15 */ + Word16 ener_match_fx = hq_nominal_scaling[tmp]; + FOR( i = 0; i < input_frame; i++ ) + { + /*t_audio_q[i] *= ener_match; */ + Mpy_32_16_ss( t_audio_fx[i], ener_match_fx, &t_audio_fx[i], &lsb ); + move16(); /* Q12 */ + } + } + + /* limit encoded band-width according to the command-line OR BWD limitation */ + inner_frame = inner_frame_tbl[st->bwidth]; + L_spec = l_spec_tbl[st->bwidth]; + + move16(); + move16(); + + + IF( GT_16( input_frame, inner_frame ) ) + { + IF( EQ_16( is_transient, 1 ) ) + { + FOR( i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + tmp = shr( inner_frame, 2 ); + Copy32( t_audio_fx + i_mult2( i, shr( input_frame, 2 ) ), t_audio_fx + i_mult2( i, tmp ), tmp ); + } + } + + set32_fx( t_audio_fx + inner_frame, 0, sub( input_frame, inner_frame ) ); + } + } + + + /* subtract signaling bits */ + num_bits = sub( num_bits, hBstr->nb_bits_tot ); + + /*-------------------------------------------------------------------------- + * High-band gain control in case of BWS + *--------------------------------------------------------------------------*/ + + IF( st->bwidth_sw_cnt > 0 ) + { + Word32 L_tmp; + tmp = BASOP_Util_Divide1616_Scale( 3, BWS_TRAN_PERIOD, &exp ); + shr( tmp, exp ); + L_tmp = L_deposit_h( tmp ); + IF( is_transient ) + { + FOR( i = 0; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + v_multc_fixed( t_audio_fx + add( i_mult2( i, shr( inner_frame, 2 ) ), L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS ), L_tmp, t_audio_fx + add( i_mult2( i, shr( inner_frame, 2 ) ), L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS ), sub( shr( inner_frame, 2 ), L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS ) ); // Q_audio + Q31 - Q31 -> Q_audio + } + } + ELSE + { + v_multc_fixed( t_audio_fx + L_FRAME16k, L_tmp, t_audio_fx + L_FRAME16k, L_spec - L_FRAME16k ); // Q_audio + Q31 - Q31 -> Q_audio + } + } + + /*-------------------------------------------------------------------------- + * Classify whether to put extra bits for FER mitigation + *--------------------------------------------------------------------------*/ + + test(); + test(); + test(); + IF( ( EQ_16( st->last_core, TCX_20_CORE ) || EQ_16( st->last_core, TCX_10_CORE ) || EQ_16( st->last_core, HQ_CORE ) ) && GT_32( st->core_brate, MINIMUM_RATE_TO_ENCODE_VOICING_FLAG ) ) + { + IF( Voicing_flag > 0 ) + { + push_indice( hBstr, IND_HQ_VOICING_FLAG, 1, 1 ); + num_bits = sub( num_bits, 1 ); + } + ELSE + { + push_indice( hBstr, IND_HQ_VOICING_FLAG, 0, 1 ); + num_bits = sub( num_bits, 1 ); + } + } + + /*-------------------------------------------------------------------------- + * Transform-domain encoding + *--------------------------------------------------------------------------*/ + + scale_sig32( t_audio_fx, L_FRAME48k, sub( Q12, Q_audio ) ); + scale_sig32( wtda_audio_fx32, 2 * L_FRAME48k, sub( Q12, Q_audio ) ); + Q_audio = 12; + move16(); + IF( EQ_16( hq_core_type, LOW_RATE_HQ_CORE ) ) + { + + hq_lr_enc_ivas_fx( st, t_audio_fx, inner_frame, &num_bits, is_transient ); + } + ELSE + { + /* HQ high rate encoder */ + hq_hr_enc_ivas_fx( st, t_audio_fx, L_spec, &num_bits, is_transient, vad_hover_flag ); + } + + /* write all unused bits to the bitstream */ + num_bits = add( num_bits, extra_unused ); + + WHILE( GT_16( num_bits, 16 ) ) + { + push_indice( hBstr, IND_UNUSED, 0, 16 ); + num_bits = sub( num_bits, 16 ); + } + + IF( num_bits != 0 ) + { + push_indice( hBstr, IND_UNUSED, 0, num_bits ); + } + + test(); + test(); + IF( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || EQ_16( st->last_core, AMR_WB_CORE ) ) ) + { + overlap = st->hTcxCfg->tcx_mdct_window_length; + move16(); + + nz = NS2SA( st->sr_core, N_ZERO_MDCT_NS ); + move16(); + L_frame = sub( st->L_frame + st->hTcxCfg->tcx_offset, st->hTcxCfg->lfacNext ); + tcx_offset = st->hTcxCfg->lfacNext; + move16(); + + set16_fx( Aq_old_fx, 0, M + 1 ); /* Dummy filter */ + Aq_old_fx[0] = 1; + move16(); + + /* Code taken from InternalTCXDecoder() */ + Copy_Scale_sig_32_16( wtda_audio_fx32, wtda_audio_fx16, 2 * L_FRAME48k, negate( Q_audio ) ); // Q0 + TCX_MDCT_Inverse( t_audio_fx, sub( sub( 31, Q_audio ), 15 ), wtda_audio_fx16, overlap, sub( L_frame, overlap ), overlap, st->element_mode ); + + + /* Window current frame */ + Word16 tcx_offset_tmp; + + IF( tcx_offset < 0 ) + { + tcx_offset_tmp = negate( tcx_offset ); + } + ELSE + { + tcx_offset_tmp = 0; + move16(); + } + tcx_windowing_synthesis_current_frame( wtda_audio_fx16, st->hTcxCfg->tcx_aldo_window_2, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, overlap, /*st->hTcxCfg->tcx_mdct_window_length*/ st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, st->last_core == ACELP_CORE, st->hTcxCfg->tcx_last_overlap_mode, /*left mode*/ st->hTcxEnc->acelp_zir, st->hTcxEnc->Txnq, NULL, Aq_old_fx, st->hTcxCfg->tcx_mdct_window_trans, shr( st->L_frame, 1 ), tcx_offset_tmp, st->last_core, 0, 0 ); + + + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + Copy( wtda_audio_fx16 + sub( L_frame, nz ), st->hTcxEnc->old_out_fx, nz + overlap ); + set16_fx( st->hTcxEnc->old_out_fx + add( nz, overlap ), 0, nz ); + + tcx_windowing_synthesis_past_frame( st->hTcxEnc->old_out_fx + nz, st->hTcxCfg->tcx_aldo_window_1_trunc, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, overlap, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, FULL_OVERLAP ); + + FOR( i = 0; i < nz; i++ ) + { + Word16 reverse_index = sub( sub( nz, 1 ), i ); + + IF( LT_16( reverse_index, shr( nz, 1 ) ) ) + { + // Imaginary part: reverse index corresponds to imaginary part + st->hTcxEnc->old_out_fx[nz + overlap + i] = mult( wtda_audio_fx16[L_frame - 1 - i], st->hTcxCfg->tcx_aldo_window_1_trunc[-1 - i].v.im ); // Q0 + Q15 - Q15 -> Q0 + move16(); + } + ELSE + { + // Real part: reverse index - nz/2 corresponds to real part + st->hTcxEnc->old_out_fx[nz + overlap + i] = mult( wtda_audio_fx16[L_frame - 1 - i], st->hTcxCfg->tcx_aldo_window_1_trunc[-1 - ( i - shr( nz, 1 ) )].v.re ); // Q0 + Q15 - Q15 -> Q0 + move16(); + } + } + + Copy( wtda_audio_fx16 + sub( shr( overlap, 1 ), tcx_offset ), output_fx, st->L_frame ); + } + ELSE + { + Word16 tmp_q = Q_audio; + move16(); + Word32 ener_match_fx = SQRT2_FIXED; + move32(); + FOR( i = 0; i < input_frame; i++ ) + { + t_audio_fx[i] = Mpy_32_32( t_audio_fx[i], ener_match_fx ); + move32(); /* Q12 - 1 -> Q11 */ + } + + Q_audio = sub( Q_audio, 1 ); + scale_sig32( wtda_audio_fx32, 2 * L_FRAME48k, sub( Q_audio, tmp_q ) ); + Inverse_Transform( t_audio_fx, &Q_audio, wtda_audio_fx32, is_transient, L_FRAME16k, inner_frame, st->element_mode ); + + + out_q = Q_audio; + move16(); + window_ola_fx( wtda_audio_fx32, output_fx, &out_q, st->hTcxEnc->old_out_fx, &old_q, L_FRAME16k, st->hTcxCfg->tcx_last_overlap_mode, st->hTcxCfg->tcx_curr_overlap_mode, 0, 0, NULL ); + + Scale_sig( output_fx, L_FRAME16k, negate( out_q ) ); + Scale_sig( st->hTcxEnc->old_out_fx, L_FRAME32k, negate( old_q ) ); + st->hTcxEnc->Q_old_out = 0; + move16(); + } + + IF( st->element_mode > EVS_MONO ) + { + /* Store LB synthesis in case of switch to ACELP */ + Copy( output_fx, st->hLPDmem->old_exc, L_FRAME16k ); + st->hLPDmem->e_old_exc = 15; + move16(); + } + pop_wmops(); + + return; +} +#endif + +#ifndef IVAS_FLOAT_FIXED void hq_core_enc( Encoder_State *st, /* i/o: encoder state structure */ const float *audio, /* i : input audio signal */ @@ -71,10 +433,6 @@ void hq_core_enc( int16_t L_spec, overlap, nz, tcx_offset; float Aq_old[M + 1]; float output[L_FRAME16k]; - -#ifdef IVAS_FLOAT_FIXED - Word32 t_audio_fx[L_FRAME48k_EXT]; -#endif BSTR_ENC_HANDLE hBstr = st->hBstr; push_wmops( "hq_core_enc" ); @@ -108,23 +466,17 @@ void hq_core_enc( /*-------------------------------------------------------------------------- * Detect signal transition *--------------------------------------------------------------------------*/ - is_transient = detect_transient( st, audio, input_frame ); - if ( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) { /*-------------------------------------------------------------------------- * IVAS switching frame *--------------------------------------------------------------------------*/ - L_spec = input_frame; left_overlap = -1; right_overlap = -1; - WindowSignal_flt( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, TRANSITION_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, st->hTcxEnc->speech_TCX_flt, &L_spec, wtda_audio, 1, 1 ); - TCX_MDCT_flt( wtda_audio, t_audio, left_overlap, L_spec - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); - inner_frame = inner_frame_tbl[st->bwidth]; L_spec = l_spec_ext_tbl[st->bwidth]; is_transient = 0; @@ -230,51 +582,11 @@ void hq_core_enc( { /* HQ low rate encoder */ -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arr32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); -#endif - hq_lr_enc_ivas_fx( st, t_audio_fx, inner_frame, &num_bits, is_transient ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arrL( st->hHQ_core->last_ni_gain_fx, st->hHQ_core->last_ni_gain, Q17, BANDS_MAX ); - fixedToFloat_arr( st->hHQ_core->last_env_fx, st->hHQ_core->last_env, Q1, BANDS_MAX ); - fixedToFloat_arrL( t_audio_fx, t_audio, Q12, L_FRAME48k_EXT ); -#endif -#else hq_lr_enc( st, t_audio, inner_frame, &num_bits, is_transient ); -#endif } else { -#ifdef IVAS_FLOAT_FIXED - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); - IF( NE_16( st->element_mode, EVS_MONO ) ) - { - Word16 temp_e; - - f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); - st->hHQ_core->crest_lp_q = 31 - temp_e; - f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); - st->hHQ_core->crest_mod_lp_q = 31 - temp_e; - } -#endif - /* HQ high rate encoder */ - hq_hr_enc_ivas_fx( st, t_audio_fx, L_spec, &num_bits, is_transient, vad_hover_flag ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - IF( NE_16( st->element_mode, EVS_MONO ) ) - { - - st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); - st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); - } - fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k ); -#endif -#else hq_hr_enc( st, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag ); -#endif } /* write all unused bits to the bitstream */ @@ -338,6 +650,7 @@ void hq_core_enc( return; } +#endif /*-------------------------------------------------------------------* * hq_core_enc_init() diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 7fa5ed9f0ef5920d63325eafa41637cc80ac2b7f..4acf05384a5be334a797d10739b11ef43609ab16 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -50,6 +50,7 @@ #define INV_Log2_10_Q15 9864 /*1/log2(10) in Q15*/ +#define INV_Log2_10_Q12 1233 /*1/log2(10) in Q12*/ #define INV_Log2_e_Q15 22713 /*1/log2(e) in Q15*/ /*-------------------------------------------------------------------* * IGF_write_bit() @@ -186,8 +187,12 @@ static Word16 IGF_getCrest_new_fx( x_eff = BASOP_Util_Divide3216_Scale( x_eff, sub( stop, start ), &temp_e ); temp_e = add( temp_e, 16 ); /*exp += 31 - 15 + 16(because x_eff is word32)*/ + x_eff = L_shr( x_eff, sub( 15, temp_e ) ); + temp_e = 15; + move16(); temp = Sqrt16( extract_l( x_eff ), &temp_e ); + test(); IF( x_eff > 0 && x_max > 0 ) { temp = BASOP_Util_Divide1616_Scale( x_max, temp, &exp ); @@ -268,9 +273,9 @@ static Word16 IGF_getSFM_new_fx( Word16 tmp_e; num = 0; - denom = 1; - denom_e = 31; - sfm = 1; + denom = ONE_IN_Q30; + denom_e = 1; + sfm = MAX16B; // Q15 move16(); move32(); move16(); @@ -292,10 +297,10 @@ static Word16 IGF_getSFM_new_fx( IF( denom != 0 ) { - tmp = BASOP_util_Pow2( L_add( numf, shl_sat( 1, sub( 14, numf_e ) ) ), 16 + numf_e, &tmp_e ); + tmp = BASOP_util_Pow2( L_add( numf, shl_sat( 1, sub( 14, numf_e ) ) ), add( 16, numf_e ), &tmp_e ); sfm = BASOP_Util_Divide3232_Scale( tmp, denom, &sfm_e ); sfm_e = add( sfm_e, sub( tmp_e, denom_e ) ); - sfm = shl_sat( extract_l( L_min( sfm, L_shl( 1, 15 - sfm_e ) ) ), sfm_e ); + sfm = shl_sat( extract_l( L_min( sfm, L_shl_sat( 1, sub( 15, sfm_e ) ) ) ), sfm_e ); } return sfm; @@ -441,7 +446,6 @@ static float IGF_getTilt( return slope; } - /*-------------------------------------------------------------------* * IGF_getTNR() * @@ -517,17 +521,25 @@ static Word32 IGF_getTNR_fx( } } - /*tonalToNoise=20.f * log10f( max( 1e-018f, tonal / noise ) )*/ - Word16 temp = BASOP_Util_Divide3232_Scale( tonal, noise, &tmp_e ); /*tonal / noise*/ - tmp_e = add( tmp_e, sub( tonal_e, noise_e ) ); - IF( GE_16( temp, 1 ) ) + /*tonalToNoise = 20.f * log10f( max( 1e-018f, tonal / noise ) )*/ + IF( noise == 0 ) // To handle condition if denom = 0 { - tonalToNoise = L_shr( imult3216( Mult_32_16( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/, 20 ) /*25*/, 3 ); /*Q22*/ + tonalToNoise = imult3216( L_shr( L_add( L_shl( 18 /* log10f(1e-018f) */, Q25 ), Mpy_32_16_1( L_add( BASOP_Util_Log2( tonal ), L_shl( tonal_e, Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/ ), 3 ) /*Q22*/, 20 ); + move32(); } ELSE { - tonalToNoise = -1509949440; /*-360.f Q22*/ - move32(); + Word16 temp = BASOP_Util_Divide3232_Scale( tonal, noise, &tmp_e ); /*tonal / noise*/ + tmp_e = add( tmp_e, sub( tonal_e, noise_e ) ); + IF( GE_16( temp, 1 ) ) + { + tonalToNoise = imult3216( Mult_32_16( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), Q25 ) ) /*Q25*/, INV_Log2_10_Q12 ) /*25+12-15*/, 20 ); /*Q22*/ + } + ELSE + { + tonalToNoise = -1509949440; /*-360.f Q22*/ + move32(); + } } return tonalToNoise; @@ -898,6 +910,554 @@ static void IGF_CalculateEnvelope( return; } +#ifdef IVAS_FLOAT_FIXED +static void IGF_CalculateEnvelope_ivas_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + Word32 *pMDCTSpectrum_fx, /* i : MDCT spectrum */ + Word16 e_mdct, /* i : exp of MDCT spectrum */ + Word32 *pPowerSpectrum_fx, /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exp of power spectrum */ + const Word16 igfGridIdx, /* i : IGF grid index */ + const Word16 isTransient, /* i : flag indicating if transient is detected */ + const Word16 last_core_acelp, /* i : indicator if last frame was ACELP core */ + const Word16 element_mode, /* i : IVAS element_mode */ + const Word16 att /* i : attenuation */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + Word16 sfb; /* this is the actual scalefactor band */ + Word16 width; /* this is width in subbands of the actual scalefactor band */ + Word16 tile_idx; + Word16 strt_cpy; + Word32 gain; /* the gain which has to be applied to the source tile to get the destination energy */ + Word16 sb; + Word32 sfbEnergyR; + Word32 sfbEnergyC; /* the energy of the destination region of the tile */ + Word32 sfbEnergyTileR; + Word32 sfbEnergyTileC; /* the energy of the destination region of the tile */ + Word16 tmp, x, y; + Word16 mean_x_fx, mean_y_fx; + Word32 mean_xy_fx, mean_x2_fx; + Word16 tmp_tb; + Word16 tmp_sb; + Word16 sfbCnt; + Word16 sfm; + Word16 crest; + Word16 temp; + Word16 mean_x_e, mean_y_e; /*Stores exponent for mean_x and mean_y respectively*/ + Word16 mean_xy_e, mean_x2_e; /*stores exponent for mean_xy and mean_x2 respectively*/ + Word16 sfbEnergyTileR_e; /*Exponent for sfbEnergyTileR*/ + Word16 sfbEnergyTileC_e; /*Exponent for sfbEnergyTileC*/ + Word16 sfbEnergyC_e; /*Exponent for sfbEnergyC*/ + Word16 sfbEnergyR_e; + Word16 gain_e; /*exponent for gain*/ + Word16 tmp_tb_e; /*Stores exponent for tmp_tb*/ + Word16 tmp_sb_e; /*stores exponent for tmp_sb*/ + Word16 crest_exp; /*Stores the exponent of the result(return value)*/ + Word16 sfm_exp; /*stores exponent for ouput from sfm*/ + Word16 tmp_e; + + hPrivateData = &hIGFEnc->igfData; + hGrid = &hPrivateData->igfInfo.grid[(int16_t) igfGridIdx]; + swb_offset = hGrid->swb_offset; + + IF( element_mode > EVS_MONO ) + { + IF( igfGridIdx != IGF_GRID_LB_NORM ) + { + FOR( sfbCnt = 0; sfbCnt < sub( hGrid->sfbWrap[hGrid->nTiles], hGrid->sfbWrap[0] ); sfbCnt++ ) + { + /* reset filter */ + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_TB_e[sfbCnt] + hPrivateData->prevSFB_FIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_TB_e[sfbCnt] + hPrivateData->prevSFB_IIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_SB_e[sfbCnt] + hPrivateData->prevSFB_FIR_SB_e[sfbCnt] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_SB_e[sfbCnt] + hPrivateData->prevSFB_IIR_SB_e[sfbCnt] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfbCnt] = MIN16B; /* -1.f in Q15*/ + hPrivateData->prevDampingFactor_IIR_e[sfbCnt] = 0; + hPrivateData->dampingFactorSmoothing[sfbCnt] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + } + + IF( pPowerSpectrum_fx ) + { + FOR( sb = hGrid->sbWrap[0]; sb < swb_offset[hGrid->sfbWrap[hGrid->nTiles]]; sb++ ) + { + IF( LT_32( 1, pPowerSpectrum_fx[sb] ) ) + { + hPrivateData->logSpec[sb] = s_max( 0, (Word16) L_shr( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( e_ps, Q25 ) ), Q25 ) ); + move16(); + } + ELSE + { + hPrivateData->logSpec[sb] = 0; + move16(); + } + } + } + + FOR( tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++ ) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + FOR( sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++ ) + { + width = sub( swb_offset[sfb + 1], swb_offset[sfb] ); + sfbEnergyTileR = EPSILON_FIX; + sfbEnergyTileC = EPSILON_FIX; + sfbEnergyC = EPSILON_FX; + sfbEnergyTileR_e = 0; + sfbEnergyTileC_e = 0; + sfbEnergyC_e = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + IF( pPowerSpectrum_fx != NULL ) + { + tmp = strt_cpy; + move16(); + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + sfbEnergyC = BASOP_Util_Add_Mant32Exp( sfbEnergyC, sfbEnergyC_e, pPowerSpectrum_fx[sb], e_ps, &sfbEnergyC_e ); + sfbEnergyTileR = BASOP_Util_Add_Mant32Exp( sfbEnergyTileR, sfbEnergyTileR_e, Mult_32_32( pMDCTSpectrum_fx[strt_cpy], pMDCTSpectrum_fx[strt_cpy] ), shl( e_mdct, 1 ), &sfbEnergyTileR_e ); + sfbEnergyTileC = BASOP_Util_Add_Mant32Exp( sfbEnergyTileC, sfbEnergyTileC_e, pPowerSpectrum_fx[strt_cpy], e_ps, &sfbEnergyTileC_e ); + + strt_cpy = add( strt_cpy, 1 ); + } + + sfbEnergyTileR = L_deposit_l( BASOP_Util_Divide3232_Scale( sfbEnergyTileR, width, &tmp_e ) ); + sfbEnergyTileR_e = add( sub( sfbEnergyTileR_e, Q15 ), tmp_e ); + + IF( sfbEnergyTileR == 0 ) + { + sfbEnergyTileR = EPSILON_FX; + sfbEnergyTileR_e = 0; + move32(); + move16(); + } + IF( sfbEnergyC == 0 ) + { + sfbEnergyC = EPSILON_FX; + sfbEnergyC_e = 0; + move32(); + move16(); + } + IF( sfbEnergyTileC == 0 ) + { + sfbEnergyTileC = EPSILON_FX; + sfbEnergyTileC_e = 0; + temp = BASOP_Util_Divide3232_Scale( sfbEnergyC, sfbEnergyTileC, &tmp_e ); + tmp_e = add( tmp_e, sub( sfbEnergyC_e, sfbEnergyTileC_e ) ); + move32(); + move16(); + } + ELSE + { + /*gain = (float) ( sfbEnergyTileR * ( sfbEnergyC / sfbEnergyTileC ) );*/ + temp = BASOP_Util_Divide3232_Scale( sfbEnergyC, sfbEnergyTileC, &tmp_e ); + tmp_e = add( tmp_e, sub( sfbEnergyC_e, sfbEnergyTileC_e ) ); + } + + gain = Mult_32_16( sfbEnergyTileR, temp ); // gain_e + gain_e = add( tmp_e, sfbEnergyTileR_e ); + + test(); + IF( element_mode > EVS_MONO ) + { + test(); + IF( !isTransient ) + { + Word16 diffSFM; + Word16 shiftedSFM = 0; + Word16 shiftedSFM_e = 0; + move16(); + move16(); + + // tmp_tb = IGF_getSFM_new( pPowerSpectrum, hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1] ) / IGF_getCrest_new( hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1] ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1], e_ps ); + sfm_exp = 0; + move16(); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1], &crest_exp ); + tmp_tb = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); // tmp_tb_e + tmp_tb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); + + // tmp_sb = IGF_getSFM_new( pPowerSpectrum, hPrivateData->logSpec, tmp, strt_cpy ) / IGF_getCrest_new( hPrivateData->logSpec, tmp, strt_cpy ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, tmp, strt_cpy, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, tmp, strt_cpy, &crest_exp ); + tmp_sb = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); // tmp_sb_e + tmp_sb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); + + test(); + IF( last_core_acelp || hPrivateData->wasTransient ) + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = tmp_tb; /*Exponent for hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] : hPrivateData->prevSFB_FIR_TB_e[sfb] and hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] : hPrivateData->prevSFB_IIR_TB_e[sfb] */ + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = tmp_sb; /*Exponent for hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] : hPrivateData->prevSFB_FIR_SB_e[sfb] and hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] : hPrivateData->prevSFB_IIR_SB_e[sfb] */ + hPrivateData->prevSFB_FIR_TB_e[sfb] = hPrivateData->prevSFB_IIR_TB_e[sfb] = tmp_tb_e; + hPrivateData->prevSFB_FIR_SB_e[sfb] = hPrivateData->prevSFB_IIR_SB_e[sfb] = tmp_sb_e; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + + tmp_tb = shr( tmp_tb, 2 ); /*taking 2 guard bits so it's exponent tmp_sb_e=+2*/ + tmp_sb = shr( tmp_sb, 2 ); /*taking 2 guard bits so it's exponent tmp_tb_e=+2 */ + tmp_sb_e = add( tmp_sb_e, 2 ); + tmp_tb_e = add( tmp_tb_e, 2 ); + + Word16 tmp0, tmp2, tmp3, tmp4; + Word16 tmp0_e, tmp2_e, tmp3_e, tmp4_e; + tmp0 = shr( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], 2 ); + tmp0_e = hPrivateData->prevSFB_FIR_TB_e[sfb] + 2; + tmp2 = shr( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], 2 ); + tmp2_e = hPrivateData->prevSFB_IIR_TB_e[sfb] + 2; + tmp3 = shr( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], 2 ); + tmp3_e = hPrivateData->prevSFB_FIR_SB_e[sfb] + 2; + tmp4 = shr( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], 2 ); + tmp4_e = hPrivateData->prevSFB_IIR_SB_e[sfb] + 2; + + Word16 x1, x2; + + Word16 x1_e = BASOP_Util_Add_MantExp( tmp0, tmp0_e, tmp2, tmp2_e - 1, &x1 ); + Word16 x2_e = BASOP_Util_Add_MantExp( tmp3, tmp3_e, tmp4, tmp4_e - 1, &x2 ); + hPrivateData->sfb_tb_e[sfb] = BASOP_Util_Add_MantExp( tmp_tb, tmp_tb_e, x1, x1_e, &hPrivateData->SFM_tb_fx[sfb] ); // hPrivateData->sfb_sb_e[sfb] + move16(); + BASOP_Util_Add_MantExp( 22118, 2, negate( hPrivateData->SFM_tb_fx[sfb] ), hPrivateData->sfb_tb_e[sfb], &tmp ); + + IF( tmp < 0 ) + { + hPrivateData->sfb_tb_e[sfb] = 2; + hPrivateData->SFM_tb_fx[sfb] = 22118; + move16(); + move16(); + } + + hPrivateData->sfb_sb_e[sfb] = BASOP_Util_Add_MantExp( tmp_sb, tmp_sb_e, x2, x2_e, &hPrivateData->SFM_sb_fx[sfb] ); // hPrivateData->sfb_tb_e[sfb] + move16(); + BASOP_Util_Add_MantExp( 22118, 2, negate( hPrivateData->SFM_sb_fx[sfb] ), hPrivateData->sfb_sb_e[sfb], &tmp ); + + IF( tmp < 0 ) + { + hPrivateData->sfb_sb_e[sfb] = 2; + hPrivateData->SFM_sb_fx[sfb] = 22118; + move16(); + move16(); + } + + BASOP_Util_Add_MantExp( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb], negate( hPrivateData->SFM_tb_fx[sfb] ), hPrivateData->sfb_tb_e[sfb], &diffSFM ); + + test(); + IF( diffSFM > 0 && LT_32( hPrivateData->SFM_tb_fx[sfb], L_shr( 3277 /*0.1 Q15*/, tmp_tb_e ) ) ) /* check whether target SFB is more tonal than source SFB */ + { + Word16 currDampingFactor, dampingFactor; + Word16 slope, threshold; + Word16 alpha; + Word16 slope_e, threshold_e, currDampingFactor_e, dampingFactor_e, alpha_e; + + /* calculate spectral tilt to detect sudden drops (or increases) in energy in the current SFB */ + // slope = IGF_getTilt_fx( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1], e_ps, &slope_e ); + + x = 1; + mean_x_fx = mean_y_fx = 0; + mean_xy_fx = mean_x2_fx = 0; + mean_x_e = mean_y_e = 15; + mean_xy_e = mean_x2_e = 31; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + test(); + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + mean_x_fx = add( mean_x_fx, x ); /*Q0*/ + mean_x2_fx = L_add( mean_x2_fx, L_mult0( x, x ) ); /*Q0*/ + + test(); + /*y = 20 * (int16_t) log10f( max( 1e-018f, pPowerSpectrum[sb] ) );*/ + IF( LT_32( pPowerSpectrum_fx[sb], 1 ) ) + { + y = imult1616( 20, ( -18 /* log10f(1e-018f) */ ) ); + } + ELSE + { + y = imult1616( 20, extract_l( L_shr( Mult_32_16( ( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( e_ps, Q25 ) ) ), INV_Log2_10_Q15 ), Q25 ) ) ); /*Q0*/ + } + mean_y_fx = add( mean_y_fx, y ); /*Q0*/ + mean_xy_fx = L_add( mean_xy_fx, L_mult0( y, x ) ); /*Q0*/ + + x = add( x, 1 ); + } + mean_y_fx = BASOP_Util_Divide1616_Scale( mean_y_fx, width, &tmp_e ); /* mean_y_e*/ + mean_y_e = add( mean_y_e, sub( tmp_e, 15 ) ); + mean_x_fx = BASOP_Util_Divide1616_Scale( mean_x_fx, width, &tmp_e ); /* mean_x_e*/ + mean_x_e = add( mean_x_e, sub( tmp_e, 15 ) ); + mean_xy_fx = BASOP_Util_Divide3216_Scale( mean_xy_fx, width, &tmp_e ); /* mean_xy_e*/ + mean_xy_e = add( mean_xy_e, sub( tmp_e, 15 ) ); + mean_x2_fx = BASOP_Util_Divide3216_Scale( mean_x2_fx, width, &tmp_e ); /* mean_x2_e*/ + mean_x2_e = add( mean_x2_e, sub( tmp_e, 15 ) ); + + /*slope = ( mean_xy - mean_x * mean_y ) / ( mean_x2 - mean_x * mean_x );*/ + slope = BASOP_Util_Divide3232_Scale( ( L_sub( mean_xy_fx, L_shl( mult( mean_x_fx, mean_y_fx ), sub( add( mean_x_e, mean_y_e ), mean_xy_e ) ) ) ), ( L_sub( mean_x2_fx, L_shl( mult( mean_x_fx, mean_x_fx ), sub( add( mean_x_e, mean_x_e ), mean_x2_e ) ) ) ), &slope_e ); + slope_e = add( slope_e, sub( mean_xy_e, mean_x2_e ) ); + + /* determine whether strong tilt is due to a step in the spectrum (e.g. band limitation, no damping) + or a tonal component close the band border (apply damping) by calculating SFM for a shift of 1/2 SFB width*/ + threshold = BASOP_Util_Divide1616_Scale( 60, width, &threshold_e ); + + test(); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope, add( slope_e, 16 ), negate( threshold ), add( threshold_e, 16 ) ), -1 ) ) + { + Word16 shift = shr( width, 1 ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift, &crest_exp ); + shiftedSFM = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + ELSE IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope, add( slope_e, 16 ), threshold, add( threshold_e, 16 ) ), 1 ) && ( NE_16( sfb, sub( hGrid->sfbWrap[hGrid->nTiles], 1 ) ) ) ) + { + Word16 shift = shr( width, 1 ); + shiftedSFM = BASOP_Util_Divide1616_Scale( IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, e_ps ), IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, &crest_exp ), &tmp_e ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, &crest_exp ); + shiftedSFM = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + shiftedSFM_e = add( shiftedSFM_e, sub( sfm_exp, crest_exp ) ); + + IF( GT_32( shiftedSFM, L_shl( 1311 /*0.04f Q15*/, negate( shiftedSFM_e ) ) ) ) + { + currDampingFactor = 32767; /*1.f Q15*/ + currDampingFactor_e = 0; + move16(); + move16(); + } + ELSE + { + // alpha = min( 320.f / (float) swb_offset[sfb + 1], 1.25f ); + temp = BASOP_Util_Divide1616_Scale( 320, swb_offset[sfb + 1], &alpha_e ); + alpha = extract_l( L_min( temp, L_shl( 20480 /*1.25 Q14*/, sub( 1, alpha_e ) ) ) ); // alpha_e + + // currDampingFactor = expf( 1.25f * alpha * logf( hPrivateData->SFM_tb[sfb] / hPrivateData->SFM_sb[sfb] ) ); + temp = BASOP_Util_Divide1616_Scale( hPrivateData->SFM_tb_fx[sfb], hPrivateData->SFM_sb_fx[sfb], &tmp_e ); // tmp_e + tmp_e = add( tmp_e, sub( hPrivateData->sfb_tb_e[sfb], hPrivateData->sfb_sb_e[sfb] ) ); + Word16 temp1 = mult( 20480 /* 1.25f in Q14 */, alpha ); + Word16 tmp1_e = add( 1, alpha_e ); + currDampingFactor = round_fx( BASOP_util_Pow2( Mpy_32_16_1( L_add( BASOP_Util_Log2( temp ), L_shl_sat( add( 16, tmp_e ), 25 ) ), temp1 ), add( tmp1_e, 6 ), &currDampingFactor_e ) ); // currDampingFactor_e + + /* calculate tonal-to-noise ratio and reduce damping for low values*/ + + Word32 tonalToNoise; + Word16 adap; + Word16 adap_e; /*stores exp for adap*/ + Word16 tonalToNoise_e; /*stores exponent for tonalToNoise*/ + tonalToNoise_e = 9; + move16(); + adap = BASOP_Util_Divide1616_Scale( width, 40, &adap_e ); + tonalToNoise = IGF_getTNR_fx( pPowerSpectrum_fx, swb_offset[sfb], swb_offset[sfb + 1], adap, e_ps, adap_e ); /*Q22*/ + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tonalToNoise, tonalToNoise_e, L_add( L_shl( 10, sub( 15, adap_e ) ), adap ), add( 16, adap_e ) ), -1 ) ) + { + // currDampingFactor += 0.03f * ( ( 10 + adap ) - tonalToNoise ); + Word32 temp2 = BASOP_Util_Add_Mant32Exp( L_add( L_shl( 10, sub( 15, adap_e ) ) /*exp:adap_e*/, adap ), add( adap_e, 16 ), L_negate( tonalToNoise ), tonalToNoise_e, &tmp_e ); // tmp_e + currDampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor, currDampingFactor_e, extract_l( Mult_32_32( 983 /*0.03f Q15*/, temp2 ) ), tmp_e, &currDampingFactor ); // currDampingFactor_e + } + } + + Word32 L_tmp = hPrivateData->prevDampingFactor_IIR_fx[sfb]; + move32(); + L_tmp = L_shl( L_tmp, hPrivateData->prevDampingFactor_IIR_e[sfb] ); + test(); + test(); + IF( last_core_acelp || hPrivateData->wasTransient || EQ_32( L_tmp, MIN16B ) ) + { + tmp = BASOP_Util_Cmp_Mant32Exp( currDampingFactor, currDampingFactor_e, 3277 /* 0.1f in Q15 */, 0 ); + IF( tmp >= 0 ) + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = currDampingFactor; + hPrivateData->prevDampingFactor_IIR_e[sfb] = currDampingFactor_e; + move16(); + move16(); + } + ELSE + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = 3277; /* 0.1 in Q15 */ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + move16(); + move16(); + } + } + IF( last_core_acelp ) + { + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + } + + dampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor, currDampingFactor_e, hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb], &dampingFactor ); // dampingFactor_e + dampingFactor = shr( dampingFactor, 1 ); + + gain = Mult_32_16( gain, shl_sat( extract_l( L_min( L_add( dampingFactor, Mult_32_16( L_shl( hPrivateData->dampingFactorSmoothing[sfb], sub( 15, dampingFactor_e ) ) /*Q:15-dampingFactor_e*/, 3277 /*0.1f Q15*/ ) /*Q:15-dampingFactor_e*/ ), shl_sat( 1, sub( 15, dampingFactor_e ) ) ) ), dampingFactor_e ) /*Q15*/ ); + + hPrivateData->prevDampingFactor_IIR_fx[sfb] = dampingFactor; + move16(); + hPrivateData->prevDampingFactor_IIR_e[sfb] = dampingFactor_e; + move16(); + test(); + IF( hPrivateData->dampingFactorSmoothing[sfb] > 0 ) + { + hPrivateData->dampingFactorSmoothing[sfb] = sub( hPrivateData->dampingFactorSmoothing[sfb], 1 ); + move16(); + } + } + ELSE + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; // exponent : hPrivateData->prevDampingFactor_IIR_e[sfb] + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 1; + move16(); + move16(); + move16(); + } + + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = tmp_tb; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = tmp_tb_e; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = hPrivateData->SFM_tb_fx[sfb]; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = hPrivateData->sfb_tb_e[sfb]; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = tmp_sb; // hPrivateData->prevSFB_FIR_SB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = hPrivateData->SFM_sb_fx[sfb]; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = hPrivateData->sfb_sb_e[sfb]; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; /* hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + } + ELSE + { + tmp_e = e_mdct; + sfbEnergyR = add_sat( EPSILON_FX, BASOP_Util_Divide3216_Scale( sum2_32_fx( pMDCTSpectrum_fx + swb_offset[sfb], width, &tmp_e ) /*exp: tmp_e*/, width, &sfbEnergyR_e ) ); // sfbEnergyR_e + sfbEnergyR_e = add( sfbEnergyR_e, add( tmp_e, -15 ) ); + gain = sfbEnergyR; // gain_e + move32(); + gain_e = add( sfbEnergyR_e, 16 ); + + IF( element_mode > EVS_MONO ) + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; /* hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + + gain = Mult_32_16( gain, att ); // gain_e + gain_e = add( gain_e, 0 ); + + /*gain=0.5f+log2f(gain)*2+16 becuase 2.885390081777927f=2*1/loge(2) so 2*1/loge(2)*loge(x) can be written as 2*log2(x)*/ + gain = L_add( ONE_IN_Q22, L_add( L_add( L_shr( BASOP_Util_Log2( gain ), 1 ), L_shl( gain_e, Q24 ) ), L_shl( 16, Q23 ) ) ); /*Q23*/ + test(); + test(); + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_48000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_48000_CPE ) ) ) + { + gain = L_add( gain, ONE_IN_Q21 ); /* better preservation of original HF band energy */ + } + test(); + test(); + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_64000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_64000_CPE ) ) ) + { + gain = L_add( gain, ONE_IN_Q20 ); + } + gain = L_min( gain, 91 << Q23 ); /* 13+15+63, see arithcode encode residual */ + gain = L_max( gain, 0 ); + gain_e = 8; /* stores exponent for gain_fx*/ + move16(); + hPrivateData->igfScfQuantized[sfb] = extract_l( L_shr( gain, Q23 ) ); /*Q0*/ + move16(); + } + } + + return; +} +#endif /*-------------------------------------------------------------------* * IGF_CalculateStereoEnvelope_fx() @@ -971,12 +1531,16 @@ static void IGF_CalculateStereoEnvelope_fx( FOR( sfbCnt = 0; sfbCnt < sub( hGrid->sfbWrap[hGrid->nTiles], hGrid->sfbWrap[0] ); sfbCnt++ ) { /* reset filter */ - hPrivateData->prevSFM_FIR_SFB_TB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_tb_e*/ - hPrivateData->prevSFM_IIR_SFB_TB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_tb_e*/ - hPrivateData->prevSFM_FIR_SFB_SB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_sb_e*/ - hPrivateData->prevSFM_IIR_SFB_SB_fx[sfbCnt] = 0; /* Exponent is hPrivateData->sfb_sb_e*/ - hPrivateData->sfb_sb_e[sfbCnt] = 0; - hPrivateData->sfb_tb_e[sfbCnt] = 0; + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_TB_e[sfbCnt] + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_TB_e[sfbCnt] + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_SB_e[sfbCnt] + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_SB_e[sfbCnt] + hPrivateData->prevSFB_FIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFB_IIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFB_FIR_SB_e[sfbCnt] = 0; + hPrivateData->prevSFB_IIR_SB_e[sfbCnt] = 0; + move16(); + move16(); move16(); move16(); move16(); @@ -1094,8 +1658,12 @@ static void IGF_CalculateStereoEnvelope_fx( { hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = tmp_tb_fx; /*Exponent for hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] values stored in hPrivateData->sfb_tb_e[sfb] */ hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = tmp_sb_fx; /*Exponent for hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] and hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] values stored in hPrivateData->sfb_sb_e[sfb]*/ - hPrivateData->sfb_tb_e[sfb] = tmp_tb_e; - hPrivateData->sfb_sb_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_FIR_TB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_IIR_TB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_FIR_SB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_IIR_SB_e[sfb] = tmp_sb_e; + move16(); + move16(); move16(); move16(); move16(); @@ -1123,7 +1691,9 @@ static void IGF_CalculateStereoEnvelope_fx( { hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = shr( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], diff_tb_e ); hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = shr( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], diff_tb_e ); - hPrivateData->sfb_tb_e[sfb] = tmp_tb_e; + hPrivateData->prevSFB_FIR_TB_e[sfb] = tmp_tb_e; + hPrivateData->prevSFB_IIR_TB_e[sfb] = tmp_tb_e; + move16(); move16(); move16(); move16(); @@ -1138,7 +1708,9 @@ static void IGF_CalculateStereoEnvelope_fx( { hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = shr( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], diff_sb_e ); hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = shr( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], diff_sb_e ); - hPrivateData->sfb_sb_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_FIR_SB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFB_IIR_SB_e[sfb] = tmp_sb_e; + move16(); move16(); move16(); move16(); @@ -1333,6 +1905,14 @@ static void IGF_CalculateStereoEnvelope_fx( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = hPrivateData->SFM_tb_fx[sfb]; hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = tmp_sb_fx; hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = hPrivateData->SFM_sb_fx[sfb]; + hPrivateData->prevSFB_FIR_TB_e[sfb] = hPrivateData->sfb_tb_e[sfb]; + hPrivateData->prevSFB_IIR_TB_e[sfb] = hPrivateData->sfb_tb_e[sfb]; + hPrivateData->prevSFB_FIR_SB_e[sfb] = hPrivateData->sfb_sb_e[sfb]; + hPrivateData->prevSFB_IIR_SB_e[sfb] = hPrivateData->sfb_sb_e[sfb]; + move16(); + move16(); + move16(); + move16(); move16(); move16(); move16(); @@ -1344,6 +1924,10 @@ static void IGF_CalculateStereoEnvelope_fx( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; hPrivateData->dampingFactorSmoothing[sfb] = 2; move16(); @@ -1351,6 +1935,10 @@ static void IGF_CalculateStereoEnvelope_fx( move16(); move16(); move16(); + move16(); + move16(); + move16(); + move16(); } } ELSE @@ -1359,12 +1947,21 @@ static void IGF_CalculateStereoEnvelope_fx( sfbEnergyR_fx = add_sat( EPSILON_FX, BASOP_Util_Divide3216_Scale( sum2_32_fx( pMDCTSpectrum_fx + swb_offset[sfb], width, &tmp_e ) /*exp: tmp_e*/, width, &sfbEnergyR_e ) ); sfbEnergyR_e = add( sfbEnergyR_e, add( tmp_e, -15 ) ); /* stores resultant exponent for sfbEnergyR_fx*/ gain_fx = sfbEnergyR_fx; /*resultant exponent stored in gain_e=sfbEnergyR_e*/ - gain_e = add( sfbEnergyR_e, 16 ); /* because gain_fx is word32;only after adding 16 q of gain_fx is 15-sfbEnergyR_e*/ + move32(); + gain_e = add( sfbEnergyR_e, 16 ); /* because gain_fx is word32;only after adding 16 q of gain_fx is 15-sfbEnergyR_e*/ hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; + move16(); + move16(); + move16(); + move16(); move16(); move16(); move16(); @@ -1385,6 +1982,7 @@ static void IGF_CalculateStereoEnvelope_fx( gain_e = 8; /* stores exponent for gain_fx*/ move16(); hPrivateData->igfScfQuantized[sfb] = (Word16) ( L_shr( gain_fx, 23 ) ); /*Q0*/ + move16(); } } @@ -2291,8 +2889,8 @@ static void IGF_Whitening_ivas_fx( test(); test(); test(); - IF( ( EQ_16( hPrivateData->igfPrevWhiteningLevel[p], IGF_WHITENING_OFF ) && NE_16( hPrivateData->igfCurrWhiteningLevel[p], IGF_WHITENING_OFF ) ) || - ( EQ_16( hPrivateData->igfPrevWhiteningLevel[p + 1], IGF_WHITENING_OFF ) && NE_16( hPrivateData->igfCurrWhiteningLevel[p + 1], IGF_WHITENING_OFF ) ) ) + IF( ( hPrivateData->igfPrevWhiteningLevel[p] == IGF_WHITENING_OFF && hPrivateData->igfCurrWhiteningLevel[p] != IGF_WHITENING_OFF ) || + ( hPrivateData->igfPrevWhiteningLevel[p + 1] == IGF_WHITENING_OFF && hPrivateData->igfCurrWhiteningLevel[p + 1] != IGF_WHITENING_OFF ) ) { Word16 i; Word16 pastSfm_a[4], pastSfm_b[4]; @@ -2324,7 +2922,7 @@ static void IGF_Whitening_ivas_fx( /* if tonality oscillates between two tiles, turn whitening off in both */ IF( ( ( pastSfmDiffSum_a > 0 && pastSfmDiffSum_b < 0 ) || ( pastSfmDiffSum_a < 0 && pastSfmDiffSum_b > 0 ) ) && - ( GT_16( abs_s( sub( pastSfmDiffSum_a, pastSfmDiffSum_b ) ), ONE_IN_Q13 ) ) ) + ( GT_32( L_abs( L_sub( pastSfmDiffSum_a, pastSfmDiffSum_b ) ), ONE_IN_Q12 /* 0.5 in Q13 */ ) ) ) { hPrivateData->igfCurrWhiteningLevel[p] = hPrivateData->igfCurrWhiteningLevel[p + 1] = IGF_WHITENING_OFF; move16(); @@ -2374,7 +2972,7 @@ static void IGF_Whitening( const int16_t igfGridIdx, /* i : Q0 | IGF grid index */ const int16_t isTransient, /* i : Q0 | flag indicating if transient is detected */ const int16_t last_core_acelp, /* i : Q0 | indicator if last frame was ACELP core */ - const int8_t isTNSActive, /* i : Q0 | indicator if TNS is active */ + const int16_t isTNSActive, /* i : Q0 | indicator if TNS is active */ const int16_t sp_aud_decision0, /* i : Q0 | first stage classifier decision */ const int32_t brate, /* i : Q0 | bitrate */ const int16_t element_mode /* i : Q0 | element mode */ @@ -2741,7 +3339,7 @@ static Word16 IGF_WriteWhiteningTile( /**< out: Q0 | numb ELSE { IGF_write_bits( hBstr, pBitOffset, 1, 1 ); - IF( EQ_32( whiteningLevel, IGF_WHITENING_OFF ) ) + IF( whiteningLevel == IGF_WHITENING_OFF ) { IGF_write_bits( hBstr, pBitOffset, 0, 1 ); } @@ -3208,6 +3806,10 @@ void IGFEncSetMode( set_f( hPrivateData->prevSFM_FIR_SFB_TB, 0, IGF_MAX_SFB ); set_f( hPrivateData->prevSFM_IIR_SFB_TB, 0, IGF_MAX_SFB ); set_f( hPrivateData->prevDampingFactor_IIR, -1, IGF_MAX_SFB ); +#ifdef IVAS_FLOAT_FIXED + set_s( hPrivateData->prevDampingFactor_IIR_fx, MIN16B, IGF_MAX_SFB ); + set_s( hPrivateData->prevDampingFactor_IIR_e, 0, IGF_MAX_SFB ); +#endif set_s( hPrivateData->logSpec, 0, L_FRAME_PLUS ); set_f( hPrivateData->SFM_sb, 0.f, IGF_MAX_SFB ); set_f( hPrivateData->SFM_tb, 0.f, IGF_MAX_SFB ); @@ -3262,7 +3864,7 @@ void IGFEncSetMode_ivas_fx( set16_fx( hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES ); set16_fx( hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES ); set16_fx( hPrivateData->igfWhiteningHangoverCnt, 0, IGF_MAX_TILES ); - for ( i = 0; i < IGF_MAX_TILES; i++ ) + FOR( i = 0; i < IGF_MAX_TILES; i++ ) { set16_fx( hPrivateData->igfPastSFM_fx[i], -( ONE_IN_Q13 ), IGF_PAST_SFM_LEN ); } @@ -3285,6 +3887,7 @@ void IGFEncSetMode_ivas_fx( set16_fx( hPrivateData->prevSFM_FIR_SFB_TB_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->prevSFM_IIR_SFB_TB_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->prevDampingFactor_IIR_fx, -( ONE_IN_Q15 ), IGF_MAX_SFB ); + set16_fx( hPrivateData->prevDampingFactor_IIR_e, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->logSpec, 0, L_FRAME_PLUS ); set16_fx( hPrivateData->SFM_sb_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->SFM_tb_fx, 0, IGF_MAX_SFB ); @@ -3551,6 +4154,80 @@ int16_t IGFEncWriteConcatenatedBitstream( * * apply the IGF encoder, main encoder interface *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyMono_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + const Word16 igfGridIdx, /* i : IGF grid index */ + Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ + Word16 e_mdct, /* i : exponent of pMDCTspectrum */ + Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exponent of pPowerSpectrum */ + const Word16 isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const Word8 isTNSActive, /* i : flag indicating if the TNS is active */ + const Word16 sp_aud_decision0, /* i : first stage switching decision */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word32 *pPowerSpectrumParameter_fx; + Word16 att_fx = MAX16B; + Word16 last_core_acelp; + Word16 highPassEner_exp; + move16(); + + test(); + IF( st->last_core == ACELP_CORE ) + { + last_core_acelp = 1; + move16(); + } + ELSE + { + last_core_acelp = 0; + move16(); + } + + test(); + IF( !isTNSActive && isTCX20 ) + { + pPowerSpectrumParameter_fx = pPowerSpectrum_fx; + } + ELSE + { + pPowerSpectrumParameter_fx = NULL; + } + + IGF_UpdateInfo( st->hIGFEnc, igfGridIdx ); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); + } + + IGF_CalculateEnvelope_ivas_fx( st->hIGFEnc, pMDCTSpectrum_fx, e_mdct, pPowerSpectrumParameter_fx, e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, st->element_mode, att_fx ); + + test(); + IF( isTCX20 ) + { + pPowerSpectrumParameter_fx = pPowerSpectrum_fx; + } + ELSE + { + pPowerSpectrumParameter_fx = NULL; + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IGF_Whitening_ivas_fx( st->hIGFEnc, pPowerSpectrumParameter_fx, &e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, isTNSActive, sp_aud_decision0, st->element_brate, st->element_mode ); + } + ELSE + { + IGF_Whitening_ivas_fx( st->hIGFEnc, pPowerSpectrumParameter_fx, &e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, isTNSActive, sp_aud_decision0, st->total_brate, st->element_mode ); + } + + IGF_ErodeSpectrum( &highPassEner_exp, st->hIGFEnc, pMDCTSpectrum_fx, pPowerSpectrumParameter_fx, e_ps, igfGridIdx ); +} +#endif void IGFEncApplyMono( Encoder_State *st, /* i : Encoder state */ @@ -3558,41 +4235,27 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int16_t isTNSActive, /* i : flag indicating if the TNS is active */ const int16_t sp_aud_decision0, /* i : first stage switching decision */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ) { float *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ float att = 1.0f; - Word16 att_fx; int16_t last_core_acelp; last_core_acelp = ( st->last_core == ACELP_CORE ); pPowerSpectrumParameter = !isTNSActive && isTCX20 ? pPowerSpectrum : NULL; - IGF_UpdateInfo_ivas( st->hIGFEnc, igfGridIdx ); + IGF_UpdateInfo( st->hIGFEnc, igfGridIdx ); if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { -#ifndef IVAS_FLOAT_FIXED calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); -#else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - if ( st->hTdCngEnc != NULL ) - { - st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); - } -#endif - calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - att = fix16_to_float( att_fx, Q15 ); -#endif -#endif } + IGF_CalculateEnvelope( st->hIGFEnc, pMDCTSpectrum, pPowerSpectrumParameter, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, st->element_mode, att ); pPowerSpectrumParameter = isTCX20 ? pPowerSpectrum : NULL; @@ -3813,7 +4476,7 @@ void IGFSaveSpectrumForITF( return; } - +#ifndef IVAS_FLOAT_FIXED ivas_error IGF_Reconfig( IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ const int16_t igf, /* i : IGF on/off */ @@ -3848,3 +4511,43 @@ ivas_error IGF_Reconfig( return error; } +#else +ivas_error IGF_Reconfig( + IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word16 igf, /* i : IGF on/off */ + const Word16 reset, /* i : reset flag */ + const Word32 brate, /* i : bitrate for configuration */ + const Word16 bwidth, /* i : signal bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +) +{ + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + test(); + test(); + test(); + IF( igf && *hIGFEnc == NULL ) + { + IF( ( *hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); + } + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( igf && reset ) + { + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( !igf && *hIGFEnc != NULL ) + { + free( *hIGFEnc ); + *hIGFEnc = NULL; + } + + return error; +} +#endif diff --git a/lib_enc/igf_enc_fx.c b/lib_enc/igf_enc_fx.c index 8be8d54e2af56560ba82c900cea8bab6c85ab900..81907c403b166ee9ceb9dd88d2f6ba90769d7ad1 100644 --- a/lib_enc/igf_enc_fx.c +++ b/lib_enc/igf_enc_fx.c @@ -8,7 +8,7 @@ #include "options.h" #include "cnst.h" #include "stl.h" -//#include "prot_fx.h" +#include "prot.h" #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "stat_enc.h" @@ -1234,100 +1234,108 @@ void IGFEncSetMode_fx( set32_fx( hIGFEnc->spec_be_igf, 0, N_MAX_TCX - IGF_START_MN ); return; } -#ifdef IVAS_CODE_BITSTREAM +#ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * pack_bit() * * insert a bit into packed octet *-------------------------------------------------------------------*/ -static void pack_bit( - const int16_t bit, /* i : bit to be packed */ - uint8_t **pt, /* i/o: pointer to octet array into which bit will be placed */ - uint8_t *omask /* i/o: output mask to indicate where in the octet the bit is to be written */ +static void pack_bit_ivas_fx( + const Word16 bit, /* i : bit to be packed */ + UWord8 **pt, /* i/o: pointer to octet array into which bit will be placed */ + UWord8 *omask /* i/o: output mask to indicate where in the octet the bit is to be written */ ) { - if ( *omask == 0x80 ) + if ( EQ_16( *omask, 0x80 ) ) { **pt = 0; + move16(); } - if ( bit != 0 ) + IF( bit != 0 ) { - **pt = **pt | *omask; + **pt = (UWord8) s_or( **pt, *omask ); + move16(); } - *omask >>= 1; - if ( *omask == 0 ) + *omask = (UWord8) UL_lshr( *omask, 1 ); + move16(); + IF( *omask == 0 ) { *omask = 0x80; + move16(); ( *pt )++; } return; } + /*-------------------------------------------------------------------* * IGFEncConcatenateBitstream_fx() * * IGF bitstream concatenation for TCX10 modes *-------------------------------------------------------------------*/ -void IGFEncConcatenateBitstream_fx( - const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ - const int16_t bsBits, /* i : number of IGF bits written to list of indices */ - BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ +void IGFEncConcatenateBitstream_ivas_fx( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + const Word16 bsBits, /* i : number of IGF bits written to list of indices */ + BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ ) { - int16_t i; + Word16 i; IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; Indice *ind_list; - uint8_t *pFrame; /* byte array with bit packet and byte aligned coded speech data */ - int16_t *pFrame_size; /* number of bits in the binary encoded access unit [bits] */ - int16_t k, nb_bits_written; - int32_t imask; - uint8_t omask; + UWord8 *pFrame; /* byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size; /* number of bits in the binary encoded access unit [bits] */ + Word16 k, nb_bits_written; + Word32 imask; + UWord8 omask; hPrivateData = &hIGFEnc->igfData; ind_list = &hBstr->ind_list[hBstr->nb_ind_tot - bsBits]; /* here, we assume that each bit has been written as a single indice */ pFrame = hPrivateData->igfBitstream; + move16(); pFrame_size = &hPrivateData->igfBitstreamBits; + move16(); nb_bits_written = 0; + move16(); - omask = ( 0x80 >> ( *pFrame_size & 0x7 ) ); + omask = (UWord8) UL_lshr( 0x80, s_and( *pFrame_size, 0x7 ) ); pFrame += *pFrame_size >> 3; /* bitstream packing (conversion of individual indices into a serial stream) */ - for ( i = 0; i < bsBits; i++ ) - { - if ( ind_list[i].nb_bits > 0 ) - { + FOR( i = 0; i < bsBits; i++ ){ + IF( ind_list[i].nb_bits > 0 ){ /* mask from MSB to LSB */ - imask = 1 << ( ind_list[i].nb_bits - 1 ); + imask = L_shl( 1, sub( ind_list[i].nb_bits, 1 ) ); - /* write bit by bit */ - for ( k = 0; k < ind_list[i].nb_bits; k++ ) - { - pack_bit( ind_list[i].value & imask, &pFrame, &omask ); - imask >>= 1; - } - nb_bits_written += ind_list[i].nb_bits; - - /* delete the indice */ - ind_list[i].nb_bits = -1; - } + /* write bit by bit */ + FOR( k = 0; k < ind_list[i].nb_bits; k++ ) + { + pack_bit_ivas_fx( extract_l( L_and( ind_list[i].value, imask ) ), &pFrame, &omask ); + imask = L_shr( imask, 1 ); } + nb_bits_written = add( nb_bits_written, ind_list[i].nb_bits ); + + /* delete the indice */ + ind_list[i].nb_bits = -1; + move16(); +} +} - *pFrame_size += nb_bits_written; +*pFrame_size = add( *pFrame_size, nb_bits_written ); +move16(); - /* update list of indices */ - hBstr->nb_ind_tot -= bsBits; - hBstr->nb_bits_tot -= nb_bits_written; +/* update list of indices */ +hBstr->nb_ind_tot = sub( hBstr->nb_ind_tot, bsBits ); +hBstr->nb_bits_tot = sub( hBstr->nb_bits_tot, nb_bits_written ); - return; +return; } -#else +#endif + /**********************************************************************/ /* IGF bitsream concatenation for TCX10 modes **************************************************************************/ @@ -1353,7 +1361,7 @@ void IGFEncConcatenateBitstream_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /** return; } -#endif + /**********************************************************************/ /* IGF reset bitsream bit counter for TCX10 modes **************************************************************************/ @@ -1498,3 +1506,51 @@ void IGFEncApplyMono_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ igfGridIdx ); /* i: IGF grid index */ } + + +#ifdef IVAS_FLOAT_FIXED +ivas_error IGF_Reconfig_fx( + IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word16 igf, /* i : IGF on/off */ + const Word16 reset, /* i : reset flag */ + const Word32 brate, /* i : bitrate for configuration */ + const Word16 bwidth, /* i : signal bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +) +{ + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + test(); + test(); + test(); + IF( igf && *hIGFEnc == NULL ) + { + IF( ( *hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGFEncSetMode( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); +#endif + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( igf && reset ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGFEncSetMode( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); +#endif + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( !igf && *hIGFEnc != NULL ) + { + free( *hIGFEnc ); + *hIGFEnc = NULL; + } + + return error; +} +#endif // IVAS_FLOAT_FIXED diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index 31e075fd766ec928031c8437a7c06cd407fe7982..386466a08c651e6a018d1f7ba73d116736949a84 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -157,6 +157,9 @@ ivas_error init_encoder( init_gp_clip( st->clip_var ); pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); set_f( st->old_wsp, 0, L_WSP_MEM ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->old_wsp_fx, 0, L_WSP_MEM ); +#endif set_f( st->old_wsp2, 0, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); st->mem_preemph = 0.0f; @@ -183,11 +186,17 @@ ivas_error init_encoder( set_f( st->Bin_E, 0, L_FFT ); st->ee_old = 10.0f; +#ifdef IVAS_FLOAT_FIXED + st->ee_old_fx = 10 << 6; // 10 in Q6 +#endif st->Nb_ACELP_frames = 0; st->audio_frame_cnt = AUDIO_COUNTER_INI; /* Initialization of the audio frame counter mildly into the audio mode */ /* adaptive lag window memory */ st->old_pitch_la = 0; +#ifdef IVAS_FLOAT_FIXED + st->prev_Q_new = 0; +#endif if ( st->input_Fs == 8000 ) { @@ -232,6 +241,9 @@ ivas_error init_encoder( /* find_uv() parameters */ st->old_dE1 = 0.0f; +#ifdef IVAS_FLOAT_FIXED + st->old_dE1_fx = 0; +#endif st->old_ind_deltaMax = 0; set_f( st->old_enr_ssf, 0.0f, 2 * NB_SSF ); st->spike_hyst = -1; @@ -256,7 +268,12 @@ ivas_error init_encoder( st->noimix_seed = RANDOM_INITSEED; st->min_alpha = 1; st->exc_pe = 0; - +#ifdef IVAS_FLOAT_FIXED + st->exc_pe_fx = 0; + move16(); + st->Q_stat_noise = 15; + move16(); +#endif /* FEC */ st->last_clas = UNVOICED_CLAS; st->prev_fmerit_flt = 0.0f; @@ -310,10 +327,10 @@ ivas_error init_encoder( st->old_inp_12k8 = st->hSignalBuf->old_inp_12k8_flt; st->old_inp_16k = st->hSignalBuf->old_inp_16k_flt; #ifdef IVAS_FLOAT_FIXED - st->Bin_E_old_fx = st->hSignalBuf->Bin_E_old_fx; + st->mem_decim_fx = st->hSignalBuf->mem_decim_fx; + st->mem_decim16k_fx = st->hSignalBuf->mem_decim16k_fx; st->old_inp_12k8_fx = st->hSignalBuf->old_inp_12k8_fx; st->old_inp_16k_fx = st->hSignalBuf->old_inp_16k_fx; - st->mem_decim_fx = st->hSignalBuf->mem_decim_fx; #endif st->buf_speech_enc_pe_flt = st->hSignalBuf->buf_speech_enc_pe_flt; st->buf_synth_flt = st->hSignalBuf->buf_synth_flt; @@ -342,6 +359,8 @@ ivas_error init_encoder( set16_fx( st->mem_decim_fx, 0, 2 * L_FILT_MAX ); st->input_buff_fx = st->hSignalBuf->input_buff; st->input_buff32_fx = st->hSignalBuf->input_buff32; + set32_fx( st->hSignalBuf->input_buff32, 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + set16_fx( st->hSignalBuf->input_buff, 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); #endif st->input_buff = st->hSignalBuf->input_buff_flt; set_zero( st->input_buff, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); @@ -400,8 +419,11 @@ ivas_error init_encoder( { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ); } - +#ifdef IVAS_FLOAT_FIXED + noise_est_init_ivas_fx( st->hNoiseEst ); +#else noise_est_init( st->hNoiseEst ); +#endif } else { @@ -421,8 +443,11 @@ ivas_error init_encoder( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } - +#ifndef IVAS_FLOAT_FIXED wb_vad_init( st->hVAD ); +#else + wb_vad_init_fx( st->hVAD ); +#endif } else { @@ -457,6 +482,9 @@ ivas_error init_encoder( } speech_music_clas_init( st->hSpMusClas ); +#if 1 + speech_music_clas_init_ivas_fx( st->hSpMusClas ); +#endif st->sp_aud_decision0 = 0; st->sp_aud_decision1 = 0; @@ -693,6 +721,9 @@ ivas_error init_encoder( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); } else @@ -743,6 +774,10 @@ ivas_error init_encoder( st->EnergyLT = 0.0f; st->Energy_Old = 0; st->TransientHangOver = 0; +#ifdef IVAS_FLOAT_FIXED + st->last_enerBuffer_exp = 0; + move16(); +#endif /*-----------------------------------------------------------------* * Channel-aware mode @@ -823,6 +858,10 @@ ivas_error init_encoder( /* MDCT classifier */ MDCT_classifier_reset( st->hTcxEnc ); +#ifdef IVAS_FLOAT_FIXED + MDCT_classifier_reset_fx( st->hTcxEnc ); +#endif + if ( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); @@ -914,7 +953,13 @@ ivas_error init_encoder( /* Init Mode 2 core coder */ st->last_totalNoise = 0.f; +#ifdef IVAS_FLOAT_FIXED + st->last_totalNoise_fx = 0; +#endif set_f( st->totalNoise_increase_hist, 0.f, TOTALNOISE_HIST_SIZE ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->totalNoise_increase_hist_fx, 0, TOTALNOISE_HIST_SIZE ); +#endif st->totalNoise_increase_len = 0; init_coder_ace_plus( st, st->last_total_brate, 0 /* initialization value */ ); @@ -1019,35 +1064,60 @@ ivas_error init_encoder_ivas_fx( { st->last_core = -1; } + move16(); st->L_frame = L_FRAME; + move16(); st->last_coder_type = GENERIC; + move16(); st->coder_type = GENERIC; + move16(); st->last_total_brate = st->total_brate; + move32(); st->last_bits_frame_nominal = -1; + move16(); st->last_total_brate_cng = -1; + move16(); st->last_core_brate = st->total_brate; + move32(); st->dtx_sce_sba = 0; + move16(); st->extl = -1; + move16(); st->last_extl = -1; + move16(); st->last_L_frame = L_FRAME; + move16(); st->rate_switching_reset = 0; + move16(); st->rate_switching_reset_16kHz = 0; + move16(); st->clas = UNVOICED_CLAS; + move16(); st->low_rate_mode = 0; + move16(); st->ini_frame = 0; + move16(); st->inactive_coder_type_flag = 0; + move16(); st->sba_br_sw_while_no_data = 0; + move16(); st->coder_type_raw = VOICED; + move16(); st->last_coder_type_raw = st->coder_type_raw; + move16(); st->flag_ACELP16k = set_ACELP_flag_IVAS( st->element_mode, st->total_brate, st->total_brate, idchan, 0, -1, -1 ); + move16(); st->is_ism_format = 0; - IF( ism_mode != ISM_MODE_NONE ) + move16(); + + IF( NE_16( ism_mode, ISM_MODE_NONE ) ) { st->is_ism_format = 1; + move16(); } /*-----------------------------------------------------------------* @@ -1066,7 +1136,9 @@ ivas_error init_encoder_ivas_fx( st->hBstr->ivas_ind_list_zero = &st_ivas->ind_list; st->hBstr->ivas_max_num_indices = &st_ivas->ivas_max_num_indices; st->hBstr->nb_ind_tot = 0; + move16(); st->hBstr->nb_bits_tot = 0; + move16(); st->hBstr->st_ivas = st_ivas; } ELSE @@ -1082,11 +1154,24 @@ ivas_error init_encoder_ivas_fx( Copy( GEWB_Ave_fx, st->lsfoldbfi0_fx, M ); Copy( GEWB_Ave_fx, st->lsfoldbfi1_fx, M ); Copy( GEWB_Ave_fx, st->lsf_adaptive_mean_fx, M ); +#if 1 // TODO: Float Initializations. To be removed later + mvr2r( GEWB_Ave, st->mem_AR, M ); + mvr2r( GEWB_Ave, st->lsfoldbfi0, M ); + mvr2r( GEWB_Ave, st->lsfoldbfi1, M ); + mvr2r( GEWB_Ave, st->lsf_adaptive_mean, M ); + init_gp_clip( st->clip_var ); + set_zero( st->mem_MA, M ); + st->streaklimit = 1.0f; + pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); +#endif st->next_force_safety_net = 0; + move16(); st->pstreaklen = 0; + move16(); st->streaklimit_fx = MAX_WORD16; + move16(); set16_fx( st->mem_MA_fx, 0, M ); init_gp_clip_fx( st->clip_var_fx ); @@ -1095,40 +1180,127 @@ ivas_error init_encoder_ivas_fx( set16_fx( st->old_wsp2_fx, 0, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); // Needs to change depending on usage. st->mem_preemph_fx = 0; + move16(); st->mem_preemph16k_fx = 0; + move16(); st->mem_preemph_enc = 0; + move16(); + +#if 1 // TODO: Float Initializations. To be removed later + set_f( st->old_wsp, 0, L_WSP_MEM ); + set_f( st->old_wsp2, 0, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); // Needs to change depending on usage. + st->mem_preemph = 0.0f; + st->mem_preemph16k = 0.0f; + st->mem_preemph_enc_flt = 0.0; + st->mem_preemp_preQ = 0.0f; + st->mem_deemp_preQ = 0.0f; + st->mem_wsp_enc_flt = 0.0; + st->mem_wsp = 0.0f; + set_f( st->mem_decim2, 0, 3 ); + set_f( st->Bin_E, 0, L_FFT ); + st->ee_old = 10.0f; + st->old_dE1 = 0.0f; + if ( st->Opt_AMR_WB ) + { + mvr2r( mean_isf_amr_wb, st->lsf_old, M ); + isf2isp( st->lsf_old, st->lsp_old1, M, INT_FS_12k8 ); + } + else + { + mvr2r( GEWB_Ave, st->lsf_old, M ); + lsf2lsp( st->lsf_old, st->lsp_old1, M, INT_FS_12k8 ); + } + mvr2r( st->lsf_old, st->lsf_old1, M ); + mvr2r( st->lsp_old1, st->lsp_old, M ); + mvr2r( st->lsp_old, st->lsp_old16k, M ); + mvr2r( st->lsp_old, st->lspold_enc, M ); + st->stab_fac = 0.0f; + set_f( st->old_enr_ssf, 0.0f, 2 * NB_SSF ); + st->mem_preemph_DFT = 0.0f; + set_f( st->inp_12k8_mem_stereo_sw, 0, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); + st->mem_preemph16k_DFT = 0.0f; + set_f( st->inp_16k_mem_stereo_sw, 0, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + mvr2r( st->lsp_old, st->lspold_s, M ); + set_f( st->old_Aq_12_8 + 1, 0, M ); + st->old_Aq_12_8[0] = 4096; + st->voicing0_sm = 0; + st->voicing_sm = 0; + st->LF_EnergyRatio_sm = 1; + st->diff_sm = 0; + st->energy_sm = 0; + set_f( st->voicing, 0.0f, 3 ); + st->lt_mean_NB = 0; + st->lt_mean_WB = 0; + st->lt_mean_SWB = 0; + st->lp_speech = 45.0f; /* Initialize the long-term active speech level in dB */ + st->lp_noise = 0.0f; + st->bckr_tilt_lt_flt = 0.f; + st->active_cnt = 0; + st->currEnergyLookAhead = 6.1e-5f; + st->old_hpfilt_in = 0.0f; + st->old_hpfilt_out = 0.0f; + st->EnergyLT = 0.0f; + st->Energy_Old = 0; + st->last_totalNoise = 0.f; + set_f( st->totalNoise_increase_hist, 0.f, TOTALNOISE_HIST_SIZE ); + st->min_alpha = 1; + st->prev_fmerit_flt = 0; + st->fmerit_dt_flt = 0; + st->pst_mem_deemp_err = 0.0f; + st->pst_lp_ener = 0.0f; + +#endif /* AVQ pre-quantizer memory */ st->mem_preemp_preQ_fx = 0; + move16(); st->mem_deemp_preQ_fx = 0; + move16(); st->last_nq_preQ = 0; + move16(); st->last_code_preq = 0; + move16(); st->use_acelp_preq = 0; + move16(); st->last_harm_flag_acelp = 0; + move16(); /* (Decimated) Weighted Speech Memory */ st->mem_wsp_enc = 0; + move16(); st->mem_wsp_fx = 0; + move16(); set16_fx( st->mem_decim2_fx, 0, 3 ); set32_fx( st->Bin_E_fx, 0, L_FFT ); st->ee_old_fx = 640; /*chk //10 in Q6 */ + move16(); st->Nb_ACELP_frames = 0; + move16(); st->audio_frame_cnt = AUDIO_COUNTER_INI; /* Initialization of the audio frame counter mildly into the audio mode */ + move16(); /* adaptive lag window memory */ st->old_pitch_la = 0; + move16(); + + st->prev_Q_new = 0; + move16(); IF( EQ_32( st->input_Fs, 8000 ) ) { st->min_band = 1; + move16(); st->max_band = 16; + move16(); } ELSE { st->min_band = 0; + move16(); st->max_band = 19; + move16(); } IF( st->Opt_AMR_WB ) @@ -1148,61 +1320,100 @@ ivas_error init_encoder_ivas_fx( Copy( st->lsp_old_fx, st->lspold_enc_fx, M ); st->stab_fac_fx = 0; + move16(); /* Bass post-filter memories - encoder side of MODE2 */ st->bpf_off = 0; + move16(); st->pst_mem_deemp_err_fx = 0; + move16(); st->pst_lp_ener_fx = 0; + move16(); /* TC coder type */ st->tc_cnt = 0; + move16(); /* find_uv() parameters */ st->old_dE1_fx = 0; + move16(); st->old_ind_deltaMax = 0; + move16(); set32_fx( st->old_enr_ssf_fx, 0, shl( NB_SSF, 1 ) ); st->spike_hyst = -1; + move16(); /* stereo switching memories */ st->mem_preemph_DFT_fx = 0; + move16(); set16_fx( st->inp_12k8_mem_stereo_sw_fx, 0, sub( sub( STEREO_DFT_OVL_12k8, L_MEM_RECALC_12K8 ), L_FILT ) ); st->mem_preemph16k_DFT_fx = 0; + move16(); set16_fx( st->inp_16k_mem_stereo_sw_fx, 0, sub( sub( STEREO_DFT_OVL_16k, L_MEM_RECALC_16K ), L_FILT16k ) ); st->sharpFlag = 0; /* Stationary noise UV modification */ st->ge_sm_fx = 10; /*chk //10 in Q6 */ + move16(); + st->ge_sm = 10; /*chk //10 in Q6 */ + move16(); st->uv_count = 0; + move16(); st->act_count = 3; + move16(); Copy( st->lsp_old_fx, st->lspold_s_fx, M ); st->noimix_seed = RANDOM_INITSEED; - st->min_alpha_fx = 1; + move16(); + st->min_alpha_fx = 32767; + move16(); st->exc_pe = 0; - + move16(); +#ifdef IVAS_FLOAT_FIXED + st->exc_pe_fx = 0; + move16(); + st->Q_stat_noise = 15; + move16(); +#endif /* FEC */ st->last_clas = UNVOICED_CLAS; + move16(); st->prev_fmerit = 0; + move16(); st->fmerit_dt = 0; + move16(); st->Last_pulse_pos = 0; + move16(); FOR( i = 0; i < shl( NB_SUBFR16k, 1 ); i++ ) { +#if 1 // TODO: To be removed later st->old_pitch_buf[i] = L_SUBFR; +#endif + st->old_pitch_buf_fx[i] = L_SUBFR_Q6; + move16(); } /* mode1 core switching */ st->old_Es_pred = 0; + move16(); set16_fx( st->old_Aq_12_8_fx + 1, 0, M ); - st->old_Aq_12_8_fx[0] = 1; + st->old_Aq_12_8_fx[0] = ONE_IN_Q12; + move16(); /* stable short pitch detection */ st->voicing0_sm_fx = 0; + move16(); st->voicing_sm_fx = 0; + move16(); st->LF_EnergyRatio_sm_fx = 1; + move16(); st->predecision_flag = 0; + move16(); st->diff_sm_fx = 0; + move32(); st->energy_sm_fx = 0; + move32(); set16_fx( st->pitch, L_SUBFR, 3 ); set16_fx( st->voicing_fx, 0, 3 ); @@ -1228,6 +1439,8 @@ ivas_error init_encoder_ivas_fx( st->buf_speech_enc = st->hSignalBuf->buf_speech_enc; st->buf_wspeech_enc = st->hSignalBuf->buf_wspeech_enc; + set16_fx( st->hSignalBuf->buf_speech_enc, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + set16_fx( st->hSignalBuf->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); /* initializations */ set32_fx( st->Bin_E_old_fx, 0, shr( L_FFT, 2 ) ); set16_fx( st->mem_decim_fx, 0, shl( L_FILT_MAX, 1 ) ); @@ -1236,19 +1449,52 @@ ivas_error init_encoder_ivas_fx( set16_fx( st->old_inp_16k_fx, 0, L_INP_MEM ); st->input_buff_fx = st->hSignalBuf->input_buff; + st->input_buff32_fx = st->hSignalBuf->input_buff32; set16_fx( st->input_buff_fx, 0, add( L_FRAME48k, add( L_FRAME48k, NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ) ) ); + set32_fx( st->input_buff32_fx, 0, add( L_FRAME48k, add( L_FRAME48k, NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ) ) ); st->old_input_signal_fx = st->input_buff_fx; /* st->input_Fs / FRAMES_PER_SEC */ Word16 frame_length = extract_l( Mpy_32_32( st->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); - IF( EQ_16( st->element_mode, EVS_MONO ) ) + IF( st->element_mode == EVS_MONO ) { + st->input32_fx = st->input_buff32_fx + st->input_Fs / FRAMES_PER_SEC + NS2SA_FX2( st->input_Fs, DELAY_FIR_RESAMPL_NS ); st->input_fx = st->input_buff_fx + add( frame_length, (Word16) NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ) ); } ELSE { + st->input32_fx = st->input_buff32_fx + Mpy_32_32( st->input_Fs, 42949673 ) /* 1/50 in Q31*/; // st->input_Fs / FRAMES_PER_SEC st->input_fx = st->input_buff_fx + frame_length; } +#if 1 // TODO: To be removed later + st->Bin_E_old = st->hSignalBuf->Bin_E_old_flt; + st->mem_decim = st->hSignalBuf->mem_decim_flt; + st->mem_decim16k = st->hSignalBuf->mem_decim16k_flt; + st->old_inp_12k8 = st->hSignalBuf->old_inp_12k8_flt; + st->old_inp_16k = st->hSignalBuf->old_inp_16k_flt; + st->buf_speech_enc_pe_flt = st->hSignalBuf->buf_speech_enc_pe_flt; + st->buf_synth_flt = st->hSignalBuf->buf_synth_flt; + st->buf_speech_enc_flt = st->hSignalBuf->buf_speech_enc_flt; + st->buf_wspeech_enc_flt = st->hSignalBuf->buf_wspeech_enc_flt; + set_f( st->Bin_E_old, 0, L_FFT / 2 ); + set_f( st->mem_decim, 0, 2 * L_FILT_MAX ); + set_f( st->mem_decim16k, 0, 2 * L_FILT_MAX ); + set_f( st->old_inp_12k8, 0, L_INP_MEM ); + set_f( st->old_inp_16k, 0, L_INP_MEM ); + 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; + if ( st->element_mode == EVS_MONO ) + { + st->input = st->input_buff + st->input_Fs / FRAMES_PER_SEC + NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ); + } + else + { + st->input = st->input_buff + st->input_Fs / FRAMES_PER_SEC; + } + set_f( st->hSignalBuf->buf_speech_enc_flt, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + set_f( st->hSignalBuf->buf_wspeech_enc_flt, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); +#endif } ELSE { @@ -1263,20 +1509,35 @@ ivas_error init_encoder_ivas_fx( st->buf_speech_enc = NULL; st->buf_wspeech_enc = NULL; st->input_buff_fx = NULL; +#if 1 + st->Bin_E_old = NULL; + st->mem_decim = NULL; + st->mem_decim16k = NULL; + st->old_inp_12k8 = NULL; + st->old_inp_16k = NULL; + st->buf_speech_enc_pe_flt = NULL; + st->buf_synth_flt = NULL; + st->buf_speech_enc_flt = NULL; + st->buf_wspeech_enc_flt = NULL; + st->input_buff = NULL; +#endif } /*-----------------------------------------------------------------* * Noise estimator *-----------------------------------------------------------------*/ - IF( EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || EQ_16( st->element_mode, EVS_MONO ) ) + test(); + test(); + test(); + IF( idchan == 0 || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) { IF( ( st->hNoiseEst = (NOISE_EST_HANDLE) malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ); } - noise_est_init_fx( st->hNoiseEst ); + noise_est_init_ivas_fx( st->hNoiseEst ); } ELSE { @@ -1288,9 +1549,11 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ st->vad_flag = 1; + move16(); st->localVAD = 0; + move16(); - IF( ( EQ_16( idchan, 0 ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || EQ_16( st->element_mode, EVS_MONO ) ) && ( !vad_only_flag ) ) + IF( ( idchan == 0 || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) && ( !vad_only_flag ) ) { IF( ( st->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { @@ -1304,6 +1567,7 @@ ivas_error init_encoder_ivas_fx( st->hVAD = NULL; } st->Pos_relE_cnt = 20; + move16(); /* CLDFB-based VAD */ IF( st->element_mode == EVS_MONO ) @@ -1314,6 +1578,9 @@ ivas_error init_encoder_ivas_fx( } vad_init_ivas_fx( st->hVAD_CLDFB ); +#if 1 + vad_init( st->hVAD_CLDFB ); +#endif } ELSE { @@ -1324,18 +1591,23 @@ ivas_error init_encoder_ivas_fx( * Speech/music classifier *-----------------------------------------------------------------*/ - IF( EQ_16( idchan, 0 ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || EQ_16( st->element_mode, EVS_MONO ) ) + IF( idchan == 0 || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) || st->element_mode == EVS_MONO ) { IF( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n" ) ); } - speech_music_clas_init_fx( st->hSpMusClas ); - + speech_music_clas_init_ivas_fx( st->hSpMusClas ); +#if 1 + speech_music_clas_init( st->hSpMusClas ); +#endif st->sp_aud_decision0 = 0; + move16(); st->sp_aud_decision1 = 0; + move16(); st->sp_aud_decision2 = 0; + move16(); } ELSE { @@ -1348,16 +1620,27 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ st->lt_mean_NB_fx = 0; + move16(); st->lt_mean_WB_fx = 0; + move16(); st->lt_mean_SWB_fx = 0; + move16(); st->count_WB = BWD_COUNT_MAX; + move16(); st->count_SWB = BWD_COUNT_MAX; + move16(); st->count_FB = BWD_COUNT_MAX; + move16(); st->bwidth = st->max_bwidth; + move16(); st->last_input_bwidth = st->bwidth; + move16(); st->last_bwidth = st->bwidth; + move16(); st->last_bwidth_cng = st->bwidth; + move16(); st->bwidth_sw_cnt = 0; + move16(); /*-----------------------------------------------------------------* @@ -1365,20 +1648,34 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ st->lp_speech_fx = 11520; /*Q8 (45.0) */ /* Initialize the long-term active speech level in dB */ + move16(); st->lp_noise_fx = 0; + move16(); st->flag_noisy_speech_snr = 0; + move16(); st->fd_cng_reset_flag = 0; + move16(); st->cng_type = -1; + move16(); st->bckr_tilt_lt = 0; + move16(); st->active_cnt = 0; + move16(); - IF( ( ( EQ_16( idchan, 0 ) && st->Opt_DTX_ON ) || EQ_16( st->element_mode, EVS_MONO ) ) || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) + test(); + test(); + test(); + test(); + IF( ( ( idchan == 0 && st->Opt_DTX_ON ) || st->element_mode == EVS_MONO ) || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) { IF( ( st->hDtxEnc = (DTX_ENC_HANDLE) malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX variables\n" ) ); } dtx_enc_init_fx( st, var_SID_rate_flag, interval_SID ); +#if 1 + dtx_enc_init( st, var_SID_rate_flag, interval_SID ); +#endif } ELSE { @@ -1411,9 +1708,13 @@ ivas_error init_encoder_ivas_fx( st->hTranDet = NULL; st->element_mode = IVAS_SCE; + move16(); st->idchan = 100; /* indicates hCoreCoderVAD */ + move16(); st->core = -1; + move16(); st->rf_mode = 0; + move16(); return error; } @@ -1422,7 +1723,12 @@ ivas_error init_encoder_ivas_fx( * LP-CNG *-----------------------------------------------------------------*/ - IF( ( ( EQ_16( idchan, 0 ) && st->Opt_DTX_ON && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || EQ_16( st->element_mode, EVS_MONO ) ) && !( EQ_16( ism_mode, ISM_MODE_PARAM ) || EQ_16( ism_mode, ISM_MODE_DISC ) ) ) + test(); + test(); + test(); + test(); + test(); + IF( ( ( idchan == 0 && st->Opt_DTX_ON && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || st->element_mode == EVS_MONO ) && !( EQ_16( ism_mode, ISM_MODE_PARAM ) || EQ_16( ism_mode, ISM_MODE_DISC ) ) ) { IF( ( st->hTdCngEnc = (TD_CNG_ENC_HANDLE) malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) { @@ -1430,6 +1736,9 @@ ivas_error init_encoder_ivas_fx( } td_cng_enc_init_fx( st->hTdCngEnc, st->Opt_DTX_ON, st->max_bwidth ); +#if 1 + td_cng_enc_init( st->hTdCngEnc, st->Opt_DTX_ON, st->max_bwidth ); +#endif } ELSE { @@ -1439,8 +1748,10 @@ ivas_error init_encoder_ivas_fx( /*-----------------------------------------------------------------* * CLDFB & resampling tools parameters *-----------------------------------------------------------------*/ - - IF( ( NE_16( st->element_mode, IVAS_CPE_MDCT ) && EQ_16( idchan, 0 ) ) || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) + test(); + test(); + test(); + IF( ( NE_16( st->element_mode, IVAS_CPE_MDCT ) && idchan == 0 ) || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) { IF( ( error = openCldfb_ivas_enc( &st->cldfbAnaEnc, CLDFB_ANALYSIS, st->input_Fs, CLDFB_PROTOTYPE_1_25MS ) ) != IVAS_ERR_OK ) { @@ -1452,13 +1763,17 @@ ivas_error init_encoder_ivas_fx( st->cldfbAnaEnc = NULL; } - st->currEnergyLookAhead = 130996; /* 6.1e-5f in Q31 */ + st->energyCoreLookahead_Fx = 2; /* 6.1e-5f in Q15 */ + move32(); + st->sf_energyCoreLookahead_Fx = 2; /* 6.1e-5f in Q15 */ + move16(); /*-----------------------------------------------------------------* * SC-VBR parameters *-----------------------------------------------------------------*/ - IF( st->Opt_SC_VBR || EQ_16( st->element_mode, EVS_MONO ) ) + test(); + IF( st->Opt_SC_VBR || st->element_mode == EVS_MONO ) { IF( ( st->hSC_VBR = (SC_VBR_ENC_HANDLE) malloc( sizeof( SC_VBR_ENC_DATA ) ) ) == NULL ) { @@ -1466,6 +1781,9 @@ ivas_error init_encoder_ivas_fx( } sc_vbr_enc_init_fx( st->hSC_VBR ); +#if 1 + sc_vbr_enc_init( st->hSC_VBR ); +#endif } ELSE { @@ -1473,13 +1791,15 @@ ivas_error init_encoder_ivas_fx( } st->last_Opt_SC_VBR = 0; + move16(); /*-----------------------------------------------------------------* * AMR-WB IO initialization *-----------------------------------------------------------------*/ - IF( st->Opt_AMR_WB || EQ_16( st->element_mode, EVS_MONO ) ) + test(); + IF( st->Opt_AMR_WB || st->element_mode == EVS_MONO ) { IF( ( st->hAmrwb_IO = (AMRWB_IO_ENC_HANDLE) malloc( sizeof( AMRWB_IO_ENC_DATA ) ) ) == NULL ) { @@ -1487,6 +1807,9 @@ ivas_error init_encoder_ivas_fx( } amr_wb_enc_init_fx( st->hAmrwb_IO ); +#if 1 + amr_wb_enc_init( st->hAmrwb_IO ); +#endif } ELSE { @@ -1497,7 +1820,9 @@ ivas_error init_encoder_ivas_fx( * ACELP LPDmem *-----------------------------------------------------------------*/ - IF( ( EQ_16( idchan, 0 ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + test(); + test(); + IF( ( idchan == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) { IF( ( st->hLPDmem = (LPD_state_HANDLE) malloc( sizeof( LPD_state ) ) ) == NULL ) { @@ -1505,6 +1830,9 @@ ivas_error init_encoder_ivas_fx( } LPDmem_enc_init_fx( st->hLPDmem ); +#if 1 + LPDmem_enc_init( st->hLPDmem ); +#endif } ELSE { @@ -1516,9 +1844,13 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ st->GSC_noisy_speech = 0; + move16(); st->GSC_IVAS_mode = 0; + move16(); - IF( ( EQ_16( idchan, 0 ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + test(); + test(); + IF( ( idchan == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) { IF( ( st->hGSCEnc = (GSC_ENC_HANDLE) malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) { @@ -1526,6 +1858,9 @@ ivas_error init_encoder_ivas_fx( } GSC_enc_init_fx( st->hGSCEnc ); +#if 1 + GSC_enc_init( st->hGSCEnc ); +#endif } ELSE { @@ -1536,7 +1871,8 @@ ivas_error init_encoder_ivas_fx( * TBE parameters *-----------------------------------------------------------------*/ - IF( EQ_16( idchan, 0 ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + test(); + IF( idchan == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { IF( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) { @@ -1550,6 +1886,10 @@ ivas_error init_encoder_ivas_fx( InitSWBencBuffer_fx( st ); ResetSHBbuffer_Enc_fx( st ); +#if 1 + InitSWBencBuffer( st->hBWE_TD ); + ResetSHBbuffer_Enc( st->hBWE_TD ); +#endif } ELSE { @@ -1561,7 +1901,8 @@ ivas_error init_encoder_ivas_fx( * SWB BWE parameters *-----------------------------------------------------------------*/ - IF( EQ_16( idchan, 0 ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + test(); + IF( idchan == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { IF( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) { @@ -1569,6 +1910,9 @@ ivas_error init_encoder_ivas_fx( } fd_bwe_enc_init_fx( st->hBWE_FD ); +#if 1 + fd_bwe_enc_init( st->hBWE_FD ); +#endif } ELSE { @@ -1579,7 +1923,7 @@ ivas_error init_encoder_ivas_fx( * HQ core parameters *-----------------------------------------------------------------*/ - IF( NE_16( st->element_mode, IVAS_CPE_TD ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) && EQ_16( idchan, 0 ) ) + IF( NE_16( st->element_mode, IVAS_CPE_TD ) && NE_16( st->element_mode, IVAS_CPE_MDCT ) && idchan == 0 ) { IF( ( st->hHQ_core = (HQ_ENC_HANDLE) malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) { @@ -1587,6 +1931,9 @@ ivas_error init_encoder_ivas_fx( } HQ_core_enc_init_fx( st->hHQ_core ); +#if 1 + HQ_core_enc_init( st->hHQ_core ); +#endif } ELSE { @@ -1595,27 +1942,40 @@ ivas_error init_encoder_ivas_fx( /* init memory for detect_transient(), used by HQ core and swb_bwe_enc */ st->old_hpfilt_in_fx = 0; + move16(); st->old_hpfilt_out_fx = 0; + move16(); st->EnergyLT_fx = 0; + move32(); st->Energy_Old_fx = 0; + move32(); st->TransientHangOver = 0; + move16(); + st->last_enerBuffer_exp = 0; + move16(); /*-----------------------------------------------------------------* * Channel-aware mode *-----------------------------------------------------------------*/ + test(); + test(); + test(); IF( !st->Opt_RF_ON || ( NE_16( st->bwidth, WB ) && NE_16( st->bwidth, SWB ) ) || NE_32( st->total_brate, ACELP_13k20 ) ) { st->rf_mode = 0; + move16(); } ELSE { st->rf_mode = st->Opt_RF_ON; + move16(); } st->rf_mode_last = st->rf_mode; + move16(); - IF( st->Opt_RF_ON || EQ_16( st->element_mode, EVS_MONO ) ) + IF( st->Opt_RF_ON || st->element_mode == EVS_MONO ) { IF( ( st->hRF = (RF_ENC_HANDLE) malloc( sizeof( RF_ENC_DATA ) ) ) == NULL ) { @@ -1624,6 +1984,9 @@ ivas_error init_encoder_ivas_fx( /* initialize RF indice buffers */ reset_rf_indices_fx( st ); +#if 1 + reset_rf_indices( st->hRF, st->L_frame, &st->rf_target_bits_write ); +#endif } ELSE { @@ -1634,7 +1997,7 @@ ivas_error init_encoder_ivas_fx( * Temporal Envelope Coding *-----------------------------------------------------------------*/ - IF( EQ_16( st->element_mode, EVS_MONO ) ) + IF( st->element_mode == EVS_MONO ) { IF( ( st->hTECEnc = (TEC_ENC_HANDLE) malloc( sizeof( TEC_ENC_DATA ) ) ) == NULL ) { @@ -1652,7 +2015,8 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ // ToDo: reduction possible for MCT_CHAN_MODE_LFE channel - IF( EQ_16( idchan, 0 ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + test(); + IF( idchan == 0 || EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) { IF( ( st->hTcxEnc = (TCX_ENC_HANDLE) malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) { @@ -1662,6 +2026,12 @@ ivas_error init_encoder_ivas_fx( /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ st->hTcxEnc->spectrum_fx[0] = st->hTcxEnc->spectrum_long_fx; st->hTcxEnc->spectrum_fx[1] = st->hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#if 1 + set_f( st->hTcxEnc->spectrum_long, 0, N_MAX ); + st->hTcxEnc->spectrum[0] = st->hTcxEnc->spectrum_long; + st->hTcxEnc->spectrum[1] = st->hTcxEnc->spectrum_long + N_TCX10_MAX; + set_f( st->hTcxEnc->old_out, 0, L_FRAME32k ); +#endif set16_fx( st->hTcxEnc->old_out_fx, 0, L_FRAME32k ); @@ -1670,6 +2040,10 @@ ivas_error init_encoder_ivas_fx( /* MDCT classifier */ MDCT_classifier_reset_fx( st->hTcxEnc ); +#if 1 + MDCT_selector_reset( st->hTcxEnc ); + MDCT_classifier_reset( st->hTcxEnc ); +#endif IF( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) { @@ -1687,6 +2061,15 @@ ivas_error init_encoder_ivas_fx( *-----------------------------------------------------------------*/ igf_brate = st->total_brate; + move32(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); IF( EQ_16( st->element_mode, IVAS_SCE ) && ( EQ_16( st_ivas->hEncoderConfig->ivas_format, ISM_FORMAT ) || EQ_16( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) ) { igf_brate = L_sub( st->total_brate, i_mult( ISM_NB_BITS_METADATA_NOMINAL, FRAMES_PER_SEC ) ); @@ -1714,10 +2097,11 @@ ivas_error init_encoder_ivas_fx( igf_brate = ACELP_24k40; } } - ELSE IF( st->element_mode == IVAS_CPE_MDCT ) + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) { igf_brate = element_brate; } + move32(); IF( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) { @@ -1727,8 +2111,12 @@ ivas_error init_encoder_ivas_fx( { st->igf = 0; } + move16(); - IF( ( EQ_16( idchan, 0 ) || EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) && ( st->igf || EQ_16( st->element_mode, EVS_MONO ) ) ) + test(); + test(); + test(); + IF( ( idchan == 0 || EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) && ( st->igf || st->element_mode == EVS_MONO ) ) { IF( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) { @@ -1744,11 +2132,12 @@ ivas_error init_encoder_ivas_fx( * Mode 2 initialization *-----------------------------------------------------------------*/ - st->last_sr_core = L_mult( st->last_L_frame, FRAMES_PER_SEC ); + st->last_sr_core = L_mult0( st->last_L_frame, FRAMES_PER_SEC ); + move32(); /* PLC encoder */ - IF( EQ_16( st->element_mode, EVS_MONO ) ) + IF( st->element_mode == EVS_MONO ) { IF( ( st->hPlcExt = (PLC_ENC_EVS_HANDLE) malloc( sizeof( PLC_ENC_EVS ) ) ) == NULL ) { @@ -1762,30 +2151,41 @@ ivas_error init_encoder_ivas_fx( /* Init Mode 2 core coder */ st->last_totalNoise_fx = 0; + move16(); set16_fx( st->totalNoise_increase_hist_fx, 0, TOTALNOISE_HIST_SIZE ); st->totalNoise_increase_len = 0; + move16(); - init_coder_ace_plus_fx( st, st->last_total_brate, 0, -10 /* initialization value */ ); + init_coder_ace_plus_ivas_fx( st, st->last_total_brate, 0 ); /*-----------------------------------------------------------------* * FD-CNG encoder *-----------------------------------------------------------------*/ - IF( ( EQ_16( idchan, 0 ) && st->Opt_DTX_ON ) || EQ_16( st->element_mode, EVS_MONO ) || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) + test(); + test(); + test(); + test(); + IF( ( idchan == 0 && st->Opt_DTX_ON ) || st->element_mode == EVS_MONO || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) { #if 0 - IF ((error = createFdCngEnc_fx(&st->hFdCngEnc)) != IVAS_ERR_OK) - { - return error; - } + IF ((error = createFdCngEnc_fx(&st->hFdCngEnc)) != IVAS_ERR_OK) + { + return error; + } #endif createFdCngEnc_fx( &st->hFdCngEnc ); initFdCngEnc_fx( st->hFdCngEnc, st->input_Fs, st->cldfbAnaEnc->scale ); - +#if 1 + initFdCngEnc( st->hFdCngEnc, st->input_Fs, st->cldfbAnaEnc->scale ); +#endif /* initialization for IVAS modes happens in first frame pre-processing */ - IF( EQ_16( st->element_mode, EVS_MONO ) ) + IF( st->element_mode == EVS_MONO ) { configureFdCngEnc_fx( st->hFdCngEnc, st->bwidth, st->rf_mode && st->total_brate == ACELP_13k20 ? ACELP_9k60 : st->total_brate ); +#if 1 + configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode && st->total_brate == ACELP_13k20 ? ACELP_9k60 : st->total_brate ); +#endif } } ELSE @@ -1814,14 +2214,29 @@ ivas_error init_encoder_ivas_fx( InitTransientDetection_ivas_fx( frame_length, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), st->hTranDet, 0 ); } +#if 1 + if ( GT_16( st->element_mode, EVS_MONO ) ) + { + InitTransientDetection( frame_length, 0, st->hTranDet, 1 ); + } + else + { + InitTransientDetection( frame_length, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), st->hTranDet, 0 ); + } +#endif + /*-----------------------------------------------------------------* * IVAS parameters *-----------------------------------------------------------------*/ st->tdm_LRTD_flag = 0; + move16(); st->cng_sba_flag = 0; + move16(); st->bits_frame_channel = 0; + move16(); st->side_bits_frame_channel = 0; + move16(); st->Q_syn2 = 0; move16(); st->Q_syn = 0; diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c index aa7a2954988e09070aab8c9222cd631d69faec8a..e21e082254136989b4fa9edd5a1289c7ac5ca5e9 100644 --- a/lib_enc/init_enc_fx.c +++ b/lib_enc/init_enc_fx.c @@ -157,7 +157,7 @@ ivas_error init_encoder_fx( Copy( GEWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); Copy( GEWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); init_lvq_fx( st_fx->offset_scale1_fx, st_fx->offset_scale2_fx, st_fx->offset_scale1_p_fx, st_fx->offset_scale2_p_fx, st_fx->no_scales_fx, st_fx->no_scales_p_fx ); - st_fx->next_force_safety_net_fx = 0; + st_fx->next_force_safety_net = 0; st_fx->pstreaklen = 0; move16(); diff --git a/lib_enc/inov_enc_fx.c b/lib_enc/inov_enc_fx.c index bb573b1c421e7674dbcaeb10e8f2eea1a7dddb00..448c95ab6e0d768aaea8ca1a5526c199fc01e974 100644 --- a/lib_enc/inov_enc_fx.c +++ b/lib_enc/inov_enc_fx.c @@ -6,10 +6,12 @@ #include "cnst.h" /* Common constants */ //#include "prot_fx.h" /* Function prototypes */ #include "basop_util.h" -#include "rom_com_fx.h" /* Static table prototypes */ -#include "rom_com.h" /* Static table prototypes */ -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "rom_com.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ /*==============================================================================*/ @@ -419,3 +421,389 @@ Word16 inov_encode_fx( return stack_pulses; } + +#ifdef IVAS_FLOAT_FIXED +Word16 inov_encode_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16 *cn, /* i/o: target vector in residual domain Q_new*/ + const Word16 *exc, /* i : pointer to excitation signal frame Q_new*/ + Word16 *h2, /* i/o: weighted filter input response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16 *xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16 *code, /* o : algebraic excitation Q9*/ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16 *unbits, /* o : number of unused bits for PI */ + const Word16 L_subfr, /* i : subframe length */ + Word16 shift, + Word16 Q_new ) +{ + Word16 dn[2 * L_SUBFR]; + Word16 nBits, cmpl_flag; + Word16 stack_pulses; + Word16 g1, g2; + Word16 Rw[L_SUBFR]; + Word16 acelpautoc; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + Word16 i, k; +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void) last_L_frame; +#endif + stack_pulses = 0; + move16(); + + IF( EQ_16( L_frame, L_FRAME ) ) + { + g1 = FORMANT_SHARPENING_G1; + move16(); + g2 = FORMANT_SHARPENING_G2; + move16(); + } + ELSE + { + g1 = FORMANT_SHARPENING_G1_16k; + move16(); + g2 = FORMANT_SHARPENING_G2_16k; + move16(); + } + + /*----------------------------------------------------------------* + * Update target vector for codebook search in residual domain + * Preemphasize the impulse response and include fixed-gain pitch contribution into impulse resp. h1[] (pitch sharpenning) + * Correlation between target xn2[] and impulse response h1[] + *----------------------------------------------------------------*/ + + test(); + test(); + IF( GT_32( core_brate, ACELP_13k20 ) && !Opt_AMR_WB && EQ_16( L_subfr, L_SUBFR ) ) + { + acelpautoc = 1; + move16(); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr( add( pt_pitch, 26 ), 6 ), 0, L_SUBFR ); + /* h2: Q11, Rw: (Rw_e)Q */ + /* Rw_e = */ E_ACELP_hh_corr( h2, Rw, L_SUBFR, 3 ); + + E_ACELP_conv( xn2, h2, cn ); + + /* dn_e -> Rw_e*Q_xn */ + /*dn_e = */ E_ACELP_toeplitz_mul_fx( Rw, cn, dn, L_SUBFR, 1 ); + } + ELSE + { + acelpautoc = 0; + move16(); + updt_tar_fx( cn, cn, &exc[i_subfr], gain_pit, L_subfr ); + /* scaling of cn[] to limit dynamic at 12 bits */ + Scale_sig( cn, L_subfr, shift ); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr( add( pt_pitch, 26 ), 6 ), 0, L_subfr ); + corr_xh_ivas_fx( xn2, dn, h2, L_subfr ); // Q(dn) = Q_new+1 + } + + /*-----------------------------------------------------------------* + * Set complexity reduction flag to limit the number of iterations + * in algebraic innovation search + *-----------------------------------------------------------------*/ + cmpl_flag = 0; + move16(); + test(); + IF( st_fx->acelp_cfg.fcb_mode ) + { + /* set number of iterations in TD stereo, secondary channel */ + if ( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) && EQ_16( st_fx->idchan, 1 ) ) + { + cmpl_flag = 1; + move16(); + } + } + ELSE IF( EQ_16( L_frame, L_FRAME ) && EQ_16( coder_type, TRANSITION ) ) + { + test(); + test(); + if ( EQ_32( core_brate, ACELP_8k00 ) && i_subfr == 0 && LT_16( tc_subfr, L_SUBFR ) ) + { + cmpl_flag = 3; + move16(); + } + test(); + test(); + test(); + test(); + test(); + if ( EQ_32( core_brate, ACELP_11k60 ) && ( ( i_subfr == 0 && LT_16( tc_subfr, L_SUBFR ) ) || EQ_16( tc_subfr, TC_0_0 ) || ( EQ_16( i_subfr, 3 * L_SUBFR ) && EQ_16( tc_subfr, TC_0_64 ) ) ) ) + { + cmpl_flag = 3; + move16(); + } + test(); + test(); + test(); + test(); + if ( ( EQ_32( core_brate, ACELP_13k20 ) || EQ_32( core_brate, ACELP_12k15 ) ) && ( ( i_subfr == 0 && LT_16( tc_subfr, L_SUBFR ) ) || LE_16( tc_subfr, TC_0_64 ) ) ) + { + cmpl_flag = 3; + move16(); + } + } + + IF( EQ_16( L_frame, L_FRAME16k ) ) + { + IF( LE_32( core_brate, ACELP_32k ) ) + { + cmpl_flag = 4; + move16(); + + test(); + IF( EQ_16( coder_type, TRANSITION ) && GT_16( bwidth, WB ) ) + { + IF( LE_16( i_subfr, L_SUBFR ) ) + { + cmpl_flag = sub( cmpl_flag, 1 ); + } + ELSE + { + cmpl_flag = sub( cmpl_flag, 2 ); + } + } + } + ELSE IF( LE_32( core_brate, ACELP_48k ) ) + { + cmpl_flag = 3; + move16(); + + IF( EQ_16( coder_type, TRANSITION ) ) + { + IF( LE_16( i_subfr, L_SUBFR ) ) + { + cmpl_flag = sub( cmpl_flag, 1 ); + } + ELSE + { + cmpl_flag = sub( cmpl_flag, 2 ); + } + } + } + ELSE + { + cmpl_flag = 4; + move16(); + + IF( EQ_16( coder_type, TRANSITION ) ) + { + IF( LE_16( i_subfr, L_SUBFR ) ) + { + cmpl_flag = sub( cmpl_flag, 1 ); + } + ELSE + { + cmpl_flag = sub( cmpl_flag, 2 ); + } + } + + if ( EQ_16( coder_type, INACTIVE ) ) + { + cmpl_flag = 4; + move16(); + } + } + } + + test(); + test(); + test(); + IF( NE_16( L_frame, st_fx->last_L_frame ) && GT_32( core_brate, ACELP_13k20 ) && ( LT_32( core_brate, ACELP_32k ) || EQ_16( bwidth, WB ) ) ) + { + if ( GT_16( cmpl_flag, 1 ) ) + { + cmpl_flag = sub( cmpl_flag, 1 ); + } + } + + /*-----------------------------------------------------------------* + * Find and encode the algebraic innovation + *-----------------------------------------------------------------*/ + + set16_fx( y2, 0, L_SUBFR ); + + IF( !Opt_AMR_WB ) + { + IF( st_fx->acelp_cfg.fcb_mode ) + { // PMTE() +#if 1 + //#ifdef IVAS_CODE + Word16 idx = 0, idx2 = 0; + move16(); + move16(); + + IF( i_subfr != 0 ) + { + idx = idiv1616( i_subfr, L_subfr ); + idx2 = idiv1616( i_subfr, L_SUBFR ); + } + + IF( LT_16( st_fx->acelp_cfg.fixed_cdk_index[idx], ACELP_FIXED_CDK_NB ) ) + { + Word16 wordcnt, bitcnt; + Word16 prm[8]; + + test(); + test(); + test(); + IF( st_fx->acelp_cfg.fixed_cdk_index[idx] >= 0 ) + { + IF( EQ_16( L_subfr, 2 * L_SUBFR ) ) + { + nBits = st_fx->acelp_cfg.fixed_cdk_index[idx]; + move16(); + + IF( EQ_16( nBits, 8 ) ) + { + acelp_1t64_fx( hBstr, dn, h2, code, y2, L_subfr ); + } + ELSE + { + acelp_fast_fx( hBstr, nBits, dn, add( Q_new, 1 ), cn, h2, code, y2, L_subfr ); + } + } + ELSE IF( ( EQ_16( st_fx->idchan, 1 ) && LE_16( st_fx->acelp_cfg.fixed_cdk_index[idx2], 7 ) ) || ( st_fx->idchan == 0 && LE_16( st_fx->acelp_cfg.fixed_cdk_index[idx2], 3 ) ) ) + { + IF( st_fx->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR] == 0 ) + { + acelp_1t64_fx( hBstr, dn, h2, code, y2, L_subfr ); + } + ELSE + { + acelp_fast_fx( hBstr, st_fx->acelp_cfg.fixed_cdk_index[idx2], dn, add( Q_new, 1 ), cn, h2, code, y2, L_SUBFR ); + } + } + ELSE + { + E_ACELP_4t_fx( dn, cn, h2, Rw, (Word8) acelpautoc, code, st_fx->acelp_cfg.fixed_cdk_index[idx2], prm, L_frame, last_L_frame, st_fx->total_brate, i_subfr, cmpl_flag ); + + wordcnt = shr( ACELP_FIXED_CDK_BITS( st_fx->acelp_cfg.fixed_cdk_index[idx2] ), 4 ); + move16(); + bitcnt = s_and( ACELP_FIXED_CDK_BITS( st_fx->acelp_cfg.fixed_cdk_index[idx2] ), 15 ); + move16(); + + FOR( i = 0; i < wordcnt; i++ ) + { + push_indice( hBstr, IND_ALG_CDBK_4T64, prm[i], 16 ); + } + IF( bitcnt ) + { + push_indice( hBstr, IND_ALG_CDBK_4T64, prm[i], bitcnt ); + } + + /* Generate weighted code */ + set16_fx( y2, 0, L_SUBFR ); + FOR( i = 0; i < L_SUBFR; i++ ) + { + /* Code is sparse, so check which samples are non-zero */ + IF( code[i] != 0 ) + { + FOR( k = 0; k < L_SUBFR - i; k++ ) + { + y2[i + k] += code[i] * h2[k]; + } + } + } + } + } + ELSE + { + set16_fx( code, 0, L_SUBFR ); + set16_fx( y2, 0, L_SUBFR ); + } + } +#ifdef DEBUGGING + else + { + IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid mode for acelp frame!\n" ); + } +#endif +#endif + } + ELSE + { + nBits = st_fx->acelp_cfg.fixed_cdk_index[shr( i_subfr, 6 )]; + move16(); + + + IF( EQ_16( nBits, 7 ) ) + { + acelp_1t64_fx( hBstr, dn, h2, code, y2, L_SUBFR ); + } + ELSE IF( EQ_16( nBits, 12 ) ) + { + acelp_2t32_fx( hBstr, dn, h2, code, y2 ); + } + ELSE + { + *unbits = add( *unbits, acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, nBits, cmpl_flag, Opt_AMR_WB ) ); + move16(); + } + } + } + ELSE + { + IF( EQ_32( core_brate, ACELP_6k60 ) ) + { + acelp_2t32_fx( hBstr, dn, h2, code, y2 ); + } + ELSE IF( ( EQ_32( core_brate, ACELP_8k85 ) ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 20, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_12k65 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 36, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_14k25 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 44, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_15k85 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 52, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_18k25 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 64, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_19k85 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 72, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_23k05 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 88, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32( core_brate, ACELP_23k85 ) ) + { + acelp_4t64_fx( hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 88, 1, Opt_AMR_WB ); + } + } + + + /*----------------------------------------------------------------* + * Pitch sharpening + *----------------------------------------------------------------*/ + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, shr( add( pt_pitch, 26 ), 6 ), 0, L_subfr ); + + return stack_pulses; +} + +#endif diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index eb369c78a7a99ee4826e2d9165db3a7671a8a588..e219c00be7a6efe42facdc8c1c5165a251e4a86b 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -41,7 +41,9 @@ #include #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot_fx.h" +#include "prot_fx_enc.h" #endif #ifdef DEBUGGING #include "debug.h" @@ -88,27 +90,55 @@ ivas_error ivas_core_enc( STEREO_ICBWE_ENC_HANDLE hStereoICBWE; STEREO_TD_ENC_DATA_HANDLE hStereoTD; float *inp[CPE_CHANNELS]; - float new_inp_resamp16k[CPE_CHANNELS][L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ - float old_syn_12k8_16k[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + float new_inp_resamp16k[CPE_CHANNELS][L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + float old_syn_12k8_16k[CPE_CHANNELS][L_FRAME16k] = { { 0 } }; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ float shb_speech[L_FRAME16k]; float hb_speech[L_FRAME16k / 4]; float *new_swb_speech; float new_swb_speech_buffer[L_FRAME48k + STEREO_DFT_OVL_MAX]; + float bwe_exc_extended[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; + Word16 Q_new[CPE_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float fixed conversions + float voice_factors[CPE_CHANNELS][NB_SUBFR16k] = { 0 }; +#else + float voice_factors[CPE_CHANNELS][NB_SUBFR16k]; +#endif #ifdef IVAS_FLOAT_FIXED Word32 *new_swb_speech_fx; + Word16 shb_speech_fx[L_FRAME16k]; // Q_shb_spch + Word32 shb_speech_fx_32[L_FRAME16k]; // Q_shb_spch + Word16 Q_shb_spch; Word32 new_swb_speech_buffer_fx[L_FRAME48k + STEREO_DFT_OVL_MAX]; + Word16 new_inp_resamp16k_fx[CPE_CHANNELS][L_FRAME16k]; + Word16 hb_speech_fx[L_FRAME16k / 4]; + Word32 bwe_exc_extended_fx[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; /* 2 * Q_new */ + Word16 voice_factors_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q15 */ + Word16 old_syn_12k8_16k_fx[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + Word16 *new_swb_speech_fx1; + Word16 new_swb_speech_buffer_fx1[L_FRAME48k + STEREO_DFT_OVL_MAX]; #endif - float bwe_exc_extended[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; - float voice_factors[CPE_CHANNELS][NB_SUBFR16k]; int16_t Voicing_flag[CPE_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float fixed conversions + float pitch_buf[CPE_CHANNELS][NB_SUBFR16k] = { 0 }; +#else float pitch_buf[CPE_CHANNELS][NB_SUBFR16k]; +#endif +#ifdef IVAS_FLOAT_FIXED + Word16 pitch_buf_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q6 */ +#endif int16_t unbits[CPE_CHANNELS]; float tdm_lspQ_PCh[M], tdm_lsfQ_PCh[M]; +#ifdef IVAS_FLOAT_FIXED + Word16 tdm_lspQ_PCh_fx[M], tdm_lsfQ_PCh_fx[M]; /* 1 : Q15, 2 : Q2.56 */ +#endif int16_t last_element_mode, tdm_Pitch_reuse_flag; int32_t element_brate, last_element_brate, input_Fs; int16_t diff_nBits; ivas_error error; int16_t max_num_indices_BWE; +#ifdef IVAS_FLOAT_FIXED + Word16 i; +#endif push_wmops( "ivas_core_enc" ); @@ -178,12 +208,139 @@ ivas_error ivas_core_enc( /*---------------------------------------------------------------------* * Pre-processing, incl. Decision matrix *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - if ( ( error = pre_proc_ivas( st, last_element_mode, element_brate, ivas_format == SBA_FORMAT ? last_element_brate : element_brate, input_frame, old_inp_12k8[n], old_inp_16k[n], &inp[n], &ener[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], new_inp_resamp16k[n], &Voicing_flag[n], old_wsp[n], loc_harm[n], cor_map_sum[n], vad_flag_dtx[n], enerBuffer[n], fft_buff[n], MCT_flag, vad_hover_flag[n], flag_16k_smc ) ) != IVAS_ERR_OK ) + Word32 enerBuffer_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 fft_buff_fx[2 * L_FFT]; + Word32 cor_map_sum_fx = 0; + Word16 exp_cor_map_sum = 0; + Word16 q_fft_buff; + Word16 e_enerBuffer; + + st->gamma = (Word16) floatToFixed( st->gamma_flt, Q15 ); + st->preemph_fac = (Word16) floatToFixed( st->preemph_fac_flt, Q15 ); + + floatToFixed_arr16( st->lsp_old, st->lsp_old_fx, Q15, M ); + floatToFixed_arr16( st->lsp_old1, st->lsp_old1_fx, Q15, M ); + floatToFixed_arr16( st->lspold_enc, st->lspold_enc_fx, Q15, M ); + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + + IF( st->hTcxEnc ) + { + st->hTcxEnc->tfm_mem_fx = floatToFixed_32( st->hTcxEnc->tfm_mem, Q31 ); + st->hTcxEnc->tcxltp_norm_corr_past = (Word16) floatToFixed( st->hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + } + + IF( st->hTranDet ) + { + floatToFixed_arr( st->hTranDet->subblockEnergies.subblockNrgChange_flt, st->hTranDet->subblockEnergies.subblockNrgChange, Q15 - NRG_CHANGE_E, NSUBBLOCKS + MAX_TD_DELAY ); + } + + f2me( cor_map_sum[n], &cor_map_sum_fx, &exp_cor_map_sum ); + + q_fft_buff = Q_factor_arrL( fft_buff[n], ( 2 * L_FFT ) ); + + if ( q_fft_buff <= 16 ) + { + q_fft_buff = 0; + } + else + { + q_fft_buff = q_fft_buff - 16; + } + + if ( q_fft_buff >= 2 ) + { + q_fft_buff -= 3; + } + else + { + q_fft_buff -= 4; + } + + floatToFixed_arr( fft_buff[n], fft_buff_fx, q_fft_buff, ( 2 * L_FFT ) ); + f2me_buf( enerBuffer[n], enerBuffer_fx, &e_enerBuffer, (Word32) CLDFB_NO_CHANNELS_MAX ); + Word16 tmp_shift = find_guarded_bits_fx( 5 ); // Computing guraded bits necessary in the energyBuffer + scale_sig32( enerBuffer_fx, CLDFB_NO_CHANNELS_MAX, -tmp_shift ); // Computing the shift as per guarded bits in the energyBuffer + e_enerBuffer += tmp_shift; // Shifting the exponent of energyBuffer with the tmp_shift + floatToFixed_arrL( st->Bin_E_old, st->Bin_E_old_fx, Q_factor_arrL( st->Bin_E_old, 129 ), 129 ); + + if ( st->element_mode != IVAS_SCE && !st->low_rate_mode && !( st->total_brate > MAX_ACELP_BRATE ) && st->element_mode != IVAS_CPE_MDCT && st->coder_type != INACTIVE && st->sp_aud_decision1 != 0 && st->sp_aud_decision2 != 0 && st->sp_aud_decision1 != 1 && st->sp_aud_decision2 != 0 && !( st->element_mode == IVAS_CPE_TD || st->sp_aud_decision0 == 0 ) ) + { + if ( st->hTcxEnc != NULL ) + { + st->hTcxEnc->clas_sec_old_fx = float_to_fix16( st->hTcxEnc->clas_sec_old_flt, Q13 ); + } + } + + /*setTcxmode*/ + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Word16 q_com = Q31; + q_com = L_get_q1( st->prevEnergyHF ); + q_com = s_min( q_com, L_get_q1( st->currEnergyHF ) ); + st->prevEnergyHF_fx = floatToFixed_32( st->prevEnergyHF, q_com ); + st->currEnergyHF_fx = floatToFixed_32( st->currEnergyHF, q_com ); + st->currEnergyHF_e_fx = sub( Q31, q_com ); + move16(); + move16(); + move16(); + } +#endif + if ( ( error = pre_proc_ivas( st, last_element_mode, element_brate, ivas_format == SBA_FORMAT ? last_element_brate : element_brate, input_frame, old_inp_12k8[n], old_inp_16k[n], + &inp[n], &ener[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], new_inp_resamp16k[n], &Voicing_flag[n], old_wsp[n], loc_harm[n], +#ifndef IVAS_FLOAT_FIXED + cor_map_sum[n], +#endif + vad_flag_dtx[n], +#ifndef IVAS_FLOAT_FIXED + enerBuffer[n], + fft_buff[n], +#endif + MCT_flag, vad_hover_flag[n], flag_16k_smc +#ifdef IVAS_FLOAT_FIXED + , + enerBuffer_fx, + e_enerBuffer, + fft_buff_fx, + cor_map_sum_fx, + exp_cor_map_sum +#endif + ) ) != IVAS_ERR_OK ) { return error; } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->gamma_flt = fixedToFloat_16( st->gamma, Q15 ); + st->preemph_fac_flt = fixedToFloat_16( st->preemph_fac, Q15 ); + + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + fixedToFloat_arr( st->lsp_old1_fx, st->lsp_old1, Q15, M ); + fixedToFloat_arr( st->lspold_enc_fx, st->lspold_enc, Q15, M ); + fixedToFloat_arr( st->voicing_fx, st->voicing, Q15, 3 ); + + IF( st->hTcxEnc ) + { + st->hTcxEnc->tfm_mem = fixedToFloat_32( st->hTcxEnc->tfm_mem_fx, Q31 ); + st->hTcxEnc->tcxltp_norm_corr_past_flt = fixedToFloat_16( st->hTcxEnc->tcxltp_norm_corr_past, Q15 ); + } + + IF( st->hTranDet ) + { + fixedToFloat_arr( st->hTranDet->subblockEnergies.subblockNrgChange, st->hTranDet->subblockEnergies.subblockNrgChange_flt, Q15 - NRG_CHANGE_E, NSUBBLOCKS + MAX_TD_DELAY ); + } + + /*decison matrix*/ + if ( st->element_mode != IVAS_SCE && !st->low_rate_mode && !( st->total_brate > MAX_ACELP_BRATE ) && st->element_mode != IVAS_CPE_MDCT && st->coder_type != INACTIVE && st->sp_aud_decision1 != 0 && st->sp_aud_decision2 != 0 && st->sp_aud_decision1 != 1 && st->sp_aud_decision2 != 0 && !( st->element_mode == IVAS_CPE_TD || st->sp_aud_decision0 == 0 ) ) + { + if ( st->hTcxEnc != NULL ) + { + st->hTcxEnc->clas_sec_old_flt = fix16_to_float( st->hTcxEnc->clas_sec_old_fx, Q13 ); + } + } +#endif + if ( st->element_mode == IVAS_CPE_MDCT || st->element_mode == IVAS_SCE ) { st->enablePlcWaveadjust = 0; @@ -290,7 +447,7 @@ ivas_error ivas_core_enc( if ( st->core == ACELP_CORE ) { /* ACELP core encoder */ - if ( ( error = acelp_core_enc( st, inp[n], ener[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], vad_hover_flag[0], attack_flag[n], bwe_exc_extended[n], voice_factors[n], old_syn_12k8_16k[n], pitch_buf[n], &unbits[n], hStereoTD, tdm_lsfQ_PCh ) ) != IVAS_ERR_OK ) + if ( ( error = acelp_core_enc( st, inp[n], /*ener[n],*/ A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], vad_hover_flag[0], attack_flag[n], bwe_exc_extended[n], voice_factors[n], old_syn_12k8_16k[n], pitch_buf[n], &unbits[n], hStereoTD, tdm_lsfQ_PCh ) ) != IVAS_ERR_OK ) { return error; } @@ -298,14 +455,286 @@ ivas_error ivas_core_enc( if ( ( st->core == TCX_20_CORE || st->core == TCX_10_CORE ) && st->element_mode != IVAS_CPE_MDCT ) { + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Aw_fx[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; + float Aw_flt[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; + // Word16 lsp_new_fx[M], lsp_mid_fx[M]; + // Word16 n_subframes = EQ_16( st->hTcxEnc->tcxMode, TCX_10 ) ? 2 : 1; + mvr2r( Aw[n], Aw_flt[n], st->nb_subfr * ( M + 1 ) ); + floatToFixed_arr( Aw_flt[n], Aw_fx[n], Q12, st->nb_subfr * ( M + 1 ) ); + // floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + // floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); + + if ( (Word16) ( st->gamma_flt * 100 ) == 92 ) + { + st->gamma = GAMMA1; + st->inv_gamma = GAMMA1_INV; + } + else if ( (Word16) ( st->gamma_flt * 100 ) == 94 ) + { + st->gamma = GAMMA16k; + st->inv_gamma = GAMMA16k_INV; + } + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + + { + st->clip_var_fx[0] = (Word16) ( st->clip_var[8] * 2.56f ); + st->clip_var_fx[1] = float_to_fix16( st->clip_var[1], Q14 ); + st->clip_var_fx[2] = float_to_fix16( st->clip_var[2], Q8 ); + st->clip_var_fx[3] = float_to_fix16( st->clip_var[3], 0 ); + st->clip_var_fx[4] = float_to_fix16( st->clip_var[4], Q14 ); + st->clip_var_fx[5] = float_to_fix16( st->clip_var[5], Q14 ); + } + st->hTcxEnc->tcx_target_bits_fac = float_to_fix16( st->hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxCfg->na_scale = float_to_fix16( st->hTcxCfg->na_scale_flt, Q15 ); + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + floatToFixed_arr( st->hTcxEnc->Txnq_flt, st->hTcxEnc->Txnq, -1, L_FRAME32k / 2 + 64 ); + + st->hTcxEnc->Q_old_out = Q_factor_arr( st->hTcxEnc->old_out, L_FRAME32k ) - 1; + floatToFixed_arr( st->hTcxEnc->old_out, st->hTcxEnc->old_out_fx, st->hTcxEnc->Q_old_out, L_FRAME32k ); + + IF( st->hTdCngEnc != NULL ) + { + floatToFixed_arrL( st->hTdCngEnc->ho_ener_circ, st->hTdCngEnc->ho_ener_circ_fx, Q6, HO_HIST_SIZE ); + floatToFixed_arr( st->hTdCngEnc->ho_lsp_circ, st->hTdCngEnc->ho_lsp_circ_fx, Q15, HO_HIST_SIZE * M ); + floatToFixed_arrL( st->hTdCngEnc->ho_env_circ, st->hTdCngEnc->ho_env_circ_fx, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); + st->hTdCngEnc->lp_ener_fx = float_to_fix( st->hTdCngEnc->lp_ener, Q6 ); + // floatToFixed_arr( st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_exc2_buf, Q_exc, HO_HIST_SIZE * L_FFT ); + } + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + + /* TCX core encoder */ + stereo_tcx_core_enc( st, old_inp_12k8[n] + L_INP_MEM, old_inp_16k[n] + L_INP_MEM, Aw_fx[n], lsp_new[n], lsp_mid[n], pitch_buf_fx[n], last_element_mode, vad_hover_flag[0] ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( pitch_buf_fx[n], pitch_buf[n], Q6, NB_SUBFR16k ); + + fixedToFloat_arr( st->hTcxEnc->old_out_fx, st->hTcxEnc->old_out, st->hTcxEnc->Q_old_out, L_FRAME32k ); + + IF( st->hTdCngEnc != NULL ) + { + fixedToFloat_arrL( st->hTdCngEnc->ho_ener_circ_fx, st->hTdCngEnc->ho_ener_circ, Q6, HO_HIST_SIZE ); + fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ_fx, st->hTdCngEnc->ho_lsp_circ, Q15, HO_HIST_SIZE * M ); + fixedToFloat_arrL( st->hTdCngEnc->ho_env_circ_fx, st->hTdCngEnc->ho_env_circ, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); + // fixedToFloat_arr( st->hTdCngEnc->cng_exc2_buf, st->hTdCngEnc->cng_exc2_buf_flt, Q_exc, HO_HIST_SIZE * L_FFT ); + fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ2_fx, st->hTdCngEnc->ho_lsp_circ2, M, Q15 ); + } + + st->hTcxEnc->measuredBwRatio_flt = fix16_to_float( st->hTcxEnc->measuredBwRatio, Q14 ); + + st->streaklimit = fix16_to_float( st->streaklimit_fx, Q15 ); + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + { + st->clip_var[0] = (float) st->clip_var_fx[0] / 2.56f; + st->clip_var[1] = fix16_to_float( st->clip_var_fx[1], Q14 ); + st->clip_var[2] = fix16_to_float( st->clip_var_fx[2], Q8 ); + st->clip_var[3] = fix16_to_float( st->clip_var_fx[3], 0 ); + st->clip_var[4] = fix16_to_float( st->clip_var_fx[4], Q14 ); + st->clip_var[5] = fix16_to_float( st->clip_var_fx[5], Q14 ); + } + + for ( int j = 0; j < M; j++ ) + { + st->lsf_old[j] = (float) st->lsf_old_fx[j] / 2.56f; + st->lsf_adaptive_mean[j] = (float) st->lsf_adaptive_mean_fx[j] / 2.56f; + st->mem_AR[j] = (float) st->mem_AR_fx[j] / 2.56f; + st->mem_MA[j] = (float) st->mem_MA_fx[j] / 2.56f; + } + if ( st->enablePlcWaveadjust ) + { + st->hTcxCfg->SFM2_flt = fix_to_float( st->hTcxCfg->SFM2, Q31 ); + } + for ( int k = 0; k < 2; k++ ) + { + fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[k], st->hTcxEnc->spectrum[k], 31 - st->hTcxEnc->spectrum_e[k], 720 ); + } + fixedToFloat_arr( st->hTcxEnc->Txnq, st->hTcxEnc->Txnq_flt, -1, L_FRAME32k / 2 + 64 ); + st->hTcxEnc->noiseTiltFactor_flt = fix16_to_float( st->hTcxEnc->noiseTiltFactor, Q15 ); + st->hTcxEnc->tcx_target_bits_fac_flt = me2f_16( st->hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else /* TCX core encoder */ stereo_tcx_core_enc( st, old_inp_12k8[n] + L_INP_MEM, old_inp_16k[n] + L_INP_MEM, Aw[n], lsp_new[n], lsp_mid[n], pitch_buf[n], last_element_mode, vad_hover_flag[0] ); +#endif } if ( st->core == HQ_CORE ) { /* HQ core encoder */ + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + PWord16 *p; + Word16 q = 0; + Word16 overlap, tmp; + Word16 left_overlap, right_overlap; + IF( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) + { + left_overlap = st->hTcxCfg->tcx_mdct_window_lengthFB; + right_overlap = st->hTcxCfg->tcx_mdct_window_delayFB; + Word16 L_frame1 = 640; + + p = st->hTcxCfg->tcx_mdct_window_minimumFB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + + Word16 q1 = Q_factor_arr( st->hTcxCfg->tcx_mdct_window_minimumFB_flt, tmp ); + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimumFB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimumFB_flt[i + tmp], q1 ); + } + + p = st->hTcxCfg->tcx_mdct_window_transFB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_transFB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_transFB_flt[i + tmp], q1 ); + } + + p = st->hTcxCfg->tcx_aldo_window_2_FB; + tmp = shr( st->hTcxCfg->tcx_mdct_window_delayFB, 1 ); + + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_FB_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_FB_flt[i + tmp], q1 ); + } + + tmp = st->hTcxCfg->tcx_mdct_window_min_length / 2; + p = st->hTcxCfg->tcx_mdct_window_minimum; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimum_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_minimum_flt[i + tmp], q1 ); + } + + + Word16 l1 = ( shr( left_overlap, 1 ) * 2 ) + sub( L_frame1, shr( add( left_overlap, right_overlap ), 1 ) ) + ( shr( right_overlap, 1 ) * 2 ) - shr( left_overlap, 1 ) + st->hTcxCfg->tcx_offsetFB; + q = Q_factor_arr( st->hTcxEnc->speech_TCX_flt, l1 ) - 1; + st->hTcxEnc->q_speech_TCX = q; + + Word16 offset, overlap1; + offset = negate( shr( st->hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); + overlap1 = st->hTcxCfg->tcx_mdct_window_trans_lengthFB; + + floatToFixed_arr( st->hTcxEnc->speech_TCX_flt - overlap1 / 2 + offset, st->hTcxEnc->speech_TCX - overlap1 / 2 + offset, q, l1 ); + floatToFixed_arr( st->hTcxEnc->speech_TCX_flt - overlap1 / 2 + offset, st->hTcxEnc->speech_TCX - overlap1 / 2 + offset, q, 2 * L_FRAME48k + 960 ); + + q1 = 15; + tmp = st->hTcxCfg->tcx_mdct_window_half_length / 2; + p = st->hTcxCfg->tcx_mdct_window_half; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_half_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_half_flt[i + tmp], q1 ); + } + + tmp = st->hTcxCfg->tcx_mdct_window_min_length / 2; + p = st->hTcxCfg->tcx_mdct_window_trans; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_mdct_window_trans_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_mdct_window_trans_flt[i + tmp], q1 ); + } + + overlap = st->hTcxCfg->tcx_mdct_window_length; + tmp = overlap / 2; + p = st->hTcxCfg->tcx_aldo_window_2; + FOR( i = 0; i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_flt[i], q1 ); + } + FOR( i = 0; i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_2_flt[i + tmp], q1 ); + } + + tmp = overlap / 2; + p = st->hTcxCfg->tcx_aldo_window_1_trunc; + FOR( i = -NS2SA( st->sr_core, N_ZERO_MDCT_NS ); i < tmp; i++ ) + { + p[i].v.im = float_to_fix16( st->hTcxCfg->tcx_aldo_window_1_trunc_flt[i], q1 ); + } + FOR( i = -NS2SA( st->sr_core, N_ZERO_MDCT_NS ); i < tmp; i++ ) + { + p[tmp - 1 - i].v.re = float_to_fix16( st->hTcxCfg->tcx_aldo_window_1_trunc_flt[i + tmp], q1 ); + } + + FOR( i = 0; i < L_FRAME32k / 2 + 64; i++ ) + { + st->hTcxEnc->Txnq[i] = float_to_fix16( st->hTcxEnc->Txnq_flt[i], 0 ); + } + } + ELSE + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + st->hTcxEnc->old_out_fx[i] = float_to_fix16_thrld( st->hTcxEnc->old_out[i], 0 ); + } + } + + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + Word16 temp_e; + + f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); + st->hHQ_core->crest_lp_q = sub( Q31, temp_e ); + f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); + st->hHQ_core->crest_mod_lp_q = sub( Q31, temp_e ); + } + + floatToFixed_arr( st->input, st->input_fx, 0, 960 ); +#endif + + hq_core_enc_ivas_fx( st, st->input_fx, input_frame, NORMAL_HQ_CORE, Voicing_flag[n], vad_hover_flag[0] ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); + st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); + } + IF( st->element_mode > EVS_MONO ) + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + st->hLPDmem->old_exc_flt[i] = fix16_to_float( st->hLPDmem->old_exc[i], 0 ); + } + } +#endif +#else hq_core_enc( st, st->input, input_frame, NORMAL_HQ_CORE, Voicing_flag[n], vad_hover_flag[0] ); +#endif } /*---------------------------------------------------------------------* @@ -314,7 +743,29 @@ ivas_error ivas_core_enc( if ( st->element_mode == IVAS_CPE_TD && n == 0 ) { +#ifndef IVAS_FLOAT_FIXED td_stereo_param_updt( st->lsp_old, st->lsf_old, pitch_buf[0], tdm_lspQ_PCh, tdm_lsfQ_PCh, hStereoTD->tdm_Pri_pitch_buf, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // lsp_old - Q15, lsf_old - Qlog2(2.56), pitch_buf - Q6 + floatToFixed_arr16( st->lsp_old, st->lsp_old_fx, Q15, M ); + for ( i = 0; i < M; i++ ) + { + st->lsf_old_fx[i] = (Word16) ( st->lsf_old[i] * 2.56f ); + } + floatToFixed_arr16( pitch_buf[0], pitch_buf_fx[0], Q6, NB_SUBFR ); +#endif + td_stereo_param_updt_fx( st->lsp_old_fx, st->lsf_old_fx, pitch_buf_fx[0], tdm_lspQ_PCh_fx, tdm_lsfQ_PCh_fx, hStereoTD->tdm_Pri_pitch_buf_fx, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // tdm_lspQ_PCh - Q15, tdm_lsfQ_PCh - Qlog2(2.56), hStereoTD->tdm_Pri_pitch_buf - Q6 + fixedToFloat_arr( tdm_lspQ_PCh_fx, tdm_lspQ_PCh, Q15, M ); + for ( i = 0; i < M; i++ ) + { + tdm_lsfQ_PCh[i] = tdm_lsfQ_PCh_fx[i] / 2.56f; + } + fixedToFloat_arr( hStereoTD->tdm_Pri_pitch_buf_fx, hStereoTD->tdm_Pri_pitch_buf, Q6, NB_SUBFR ); +#endif +#endif } } @@ -351,11 +802,19 @@ ivas_error ivas_core_enc( if ( sts[0]->cng_sba_flag ) { +#ifdef IVAS_FLOAT_FIXED + FdCngEncodeDiracMDCTStereoSID_fx( hCPE ); +#else FdCngEncodeDiracMDCTStereoSID( hCPE ); +#endif } else { +#ifdef IVAS_FLOAT_FIXED + FdCngEncodeMDCTStereoSID_fx( hCPE ); +#else FdCngEncodeMDCTStereoSID( hCPE ); +#endif } } } @@ -380,6 +839,7 @@ ivas_error ivas_core_enc( * WB BWE encoding *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED if ( input_Fs >= 16000 && st->bwidth < SWB && st->hBWE_TD != NULL ) { /* Common pre-processing for WB TBE and WB BWE */ @@ -396,6 +856,105 @@ ivas_error ivas_core_enc( /* WB BWE encoder */ wb_bwe_enc( st, new_inp_resamp16k[n] ); } +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* Temporarily calculating variable Q. Will get Q values from core processing */ + Q_new[n] = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); + Q_new[n] = Q_new[n] / 2; + if ( st->hBWE_TD != NULL ) + { + Word16 tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb, 2 * ALLPASSSECTIONS_STEEP + 1 ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb3, 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_syn_shbexc, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_lpc_syn, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->old_bwe_exc_extended, NL_BUFF_OFFSET ) ); + Word16 tmp_q_2 = Q_factor_arrL( st->hBWE_TD->mem_csfilt, 2 ); + st->prev_Q_bwe_exc = min( tmp_q_2, tmp_q_1 + 16 ) - 2 /* Guard bits */; /* This reset need to be looked into once core processing is complete */ + } + + floatToFixed_arr16( new_inp_resamp16k[n], new_inp_resamp16k_fx[n], -1, L_FRAME16k ); + floatToFixed_arr( voice_factors[n], voice_factors_fx[n], Q15, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr( pitch_buf[n], pitch_buf_fx[n], Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); + + // prev_lsp_wb_temp_fx, prev_lsp_wb_fx and prev_lpc_wb_fx in Q15. No float counterparts + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + + if ( st->hBWE_TD != NULL ) + { + st->hBWE_TD->prev_wb_GainShape = float_to_fix16( st->hBWE_TD->prev_wb_GainShape_flt, Q15 ); + floatToFixed_arr16( st->hBWE_TD->decim_state1, st->hBWE_TD->decim_state1_fx, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->decim_state2, st->hBWE_TD->decim_state2_fx, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->old_speech_wb, st->hBWE_TD->old_speech_wb_fx, -1, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_shb, st->hBWE_TD->mem_genSHBexc_filt_down_shb_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, st->hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_wb3, st->hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->state_syn_shbexc, st->hBWE_TD->state_syn_shbexc_fx, ( st->prev_Q_bwe_exc - 16 ), L_SHB_LAHEAD ); + floatToFixed_arr16( st->hBWE_TD->state_lpc_syn, st->hBWE_TD->state_lpc_syn_fx, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->old_bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended_fx, ( st->prev_Q_bwe_exc - 16 ), NL_BUFF_OFFSET ); + floatToFixed_arr16( st->hBWE_TD->syn_overlap, st->hBWE_TD->syn_overlap_fx, 0, L_SHB_LAHEAD ); + floatToFixed_arr32( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_csfilt_fx, st->prev_Q_bwe_exc, 2 ); + } + + if ( st->hBWE_FD != NULL ) + { + floatToFixed_arr16( st->hBWE_FD->old_input_wb, st->hBWE_FD->old_input_wb_fx, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + floatToFixed_arr16( st->hBWE_FD->old_wtda_swb, st->hBWE_FD->L_old_wtda_swb_fx, -1, L_FRAME48k ); + floatToFixed_arr16( &st->hBWE_FD->mem_old_wtda_swb, &st->hBWE_FD->mem_old_wtda_swb_fx, -1, 1 ); + st->Q_old_wtda = -1; // This reset is required for resolving crash issue. Needs to be looked into further + } +#endif + test(); + test(); + IF( GE_32( input_Fs, 16000 ) && LT_16( st->bwidth, SWB ) && st->hBWE_TD != NULL ) + { + /* Common pre-processing for WB TBE and WB BWE */ + wb_pre_proc_ivas_fx( st, last_element_mode, new_inp_resamp16k_fx[n], hb_speech_fx ); + } + + test(); + test(); + IF( EQ_16( st->extl, WB_TBE ) ) + { + /* WB TBE encoder */ + wb_tbe_enc_ivas_fx( st, hb_speech_fx, bwe_exc_extended_fx[n], Q_new[n], voice_factors_fx[n], pitch_buf_fx[n] ); + } + ELSE IF( EQ_16( st->extl, WB_BWE ) && n == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* WB BWE encoder */ + wb_bwe_enc_ivas_fx( st, new_inp_resamp16k_fx[n] ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( hb_speech_fx, hb_speech, -1, L_FRAME16k / 4 ); + fixedToFloat_arr( voice_factors_fx[n], voice_factors[n], Q15, NB_SUBFR16k ); + fixedToFloat_arr( pitch_buf_fx[n], pitch_buf[n], Q6, NB_SUBFR16k ); + fixedToFloat_arrL( bwe_exc_extended_fx[n], bwe_exc_extended[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); + + if ( st->hBWE_TD != NULL ) + { + st->hBWE_TD->prev_wb_GainShape_flt = fix_to_float( st->hBWE_TD->prev_wb_GainShape, Q15 ); + fixedToFloat_arr( st->hBWE_TD->decim_state1_fx, st->hBWE_TD->decim_state1, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->decim_state2_fx, st->hBWE_TD->decim_state2, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->old_speech_wb_fx, st->hBWE_TD->old_speech_wb, -1, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb_fx, st->hBWE_TD->mem_genSHBexc_filt_down_shb, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, st->hBWE_TD->mem_genSHBexc_filt_down_wb2, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, st->hBWE_TD->mem_genSHBexc_filt_down_wb3, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->state_syn_shbexc_fx, st->hBWE_TD->state_syn_shbexc, ( st->prev_Q_bwe_exc - 16 ), L_SHB_LAHEAD ); + fixedToFloat_arr( st->hBWE_TD->state_lpc_syn_fx, st->hBWE_TD->state_lpc_syn, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->old_bwe_exc_extended_fx, st->hBWE_TD->old_bwe_exc_extended, ( st->prev_Q_bwe_exc - 16 ), NL_BUFF_OFFSET ); + fixedToFloat_arr( st->hBWE_TD->syn_overlap_fx, st->hBWE_TD->syn_overlap, 0, L_SHB_LAHEAD ); + fixedToFloat_arrL( st->hBWE_TD->mem_csfilt_fx, st->hBWE_TD->mem_csfilt, st->prev_Q_bwe_exc, 2 ); + } + + if ( st->hBWE_FD != NULL ) + { + fixedToFloat_arr( st->hBWE_FD->old_input_wb_fx, st->hBWE_FD->old_input_wb, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + fixedToFloat_arr( st->hBWE_FD->L_old_wtda_swb_fx, st->hBWE_FD->old_wtda_swb, -1, L_FRAME48k ); + st->hBWE_FD->mem_old_wtda_swb = fixedToFloat( st->hBWE_FD->mem_old_wtda_swb_fx, st->Q_old_wtda ); + } +#endif +#endif /*---------------------------------------------------------------------* * SWB(FB) TBE encoding @@ -405,13 +964,97 @@ ivas_error ivas_core_enc( new_swb_speech = new_swb_speech_buffer + STEREO_DFT_OVL_MAX; #ifdef IVAS_FLOAT_FIXED new_swb_speech_fx = new_swb_speech_buffer_fx + STEREO_DFT_OVL_MAX; + new_swb_speech_fx1 = new_swb_speech_buffer_fx1 + STEREO_DFT_OVL_MAX; #endif if ( !st->Opt_SC_VBR && input_Fs >= 32000 && st->hBWE_TD != NULL ) { /* Common pre-processing for SWB(FB) TBE and SWB(FB) BWE */ #ifdef IVAS_FLOAT_FIXED - swb_pre_proc_ivas_fx( st, new_swb_speech, new_swb_speech_fx, shb_speech, realBuffer[n], imagBuffer[n], hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 realBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 imagBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 new_swb_speech_16_fx[L_FRAME48k] = { 0 }; + Word16 use_shb32 = 0; + Word16 q_realImagBuffer = Q_factor_arrL( (float *) &realBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + q_realImagBuffer = s_min( q_realImagBuffer, Q_factor_arrL( (float *) &imagBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ) ); + floatToFixed_arrL32( (float *) &realBuffer[n][0][0], (Word32 *) &realBuffer_fx[0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL32( (float *) &imagBuffer[n][0][0], (Word32 *) &imagBuffer_fx[0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL32( (float *) &st->cldfbSynTd->cldfb_state[0], (Word32 *) &st->cldfbSynTd->cldfb_state_fx[0], q_realImagBuffer, st->cldfbSynTd->p_filter_length ); + +#if 0 + floatToFixed_arr( &st->hSignalBuf->input_buff_flt[0], &st->hSignalBuf->input_buff[0], 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); +#else + for ( Word32 idx = 0; idx < ( L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); idx++ ) + { + st->hSignalBuf->input_buff[idx] = (Word16) st->hSignalBuf->input_buff_flt[idx]; + } +#endif + if ( st->element_mode == IVAS_CPE_DFT ) + { + f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); + f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input_fx[ii] = (Word16) st->hBWE_FD->old_input[ii]; + } +#if 0 + floatToFixed_arr( (float *) &st->hBWE_FD->old_wtda_swb[0], (Word16 *) &st->hBWE_FD->L_old_wtda_swb_fx[0], 0, L_FRAME48k ); + floatToFixed_arr( (float *) &st->hBWE_FD->old_fdbwe_speech[0], (Word16 *) &st->hBWE_FD->old_fdbwe_speech_fx[0], 0, L_FRAME48k ); + floatToFixed_arr( (float *) &st->hBWE_TD->old_speech_shb[0], (Word16 *) &st->hBWE_TD->old_speech_shb_fx[0], 0, L_LOOK_16k + L_SUBFR16k ); +#else + for ( Word32 idx = 0; idx < ( L_FRAME48k ); idx++ ) + { + st->hBWE_FD->L_old_wtda_swb_fx[idx] = (Word16) st->hBWE_FD->old_wtda_swb[idx]; + st->hBWE_FD->old_fdbwe_speech_fx[idx] = (Word16) st->hBWE_FD->old_fdbwe_speech[idx]; + } + for ( Word32 idx = 0; idx < ( L_LOOK_16k + L_SUBFR16k ); idx++ ) + { + st->hBWE_TD->old_speech_shb_fx[idx] = (Word16) st->hBWE_TD->old_speech_shb[idx]; + } +#endif +#endif + swb_pre_proc_ivas_fx( st, new_swb_speech_16_fx, new_swb_speech_fx, shb_speech_fx, shb_speech_fx_32, &use_shb32, realBuffer_fx, imagBuffer_fx, q_realImagBuffer, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( (Word16 *) &st->hBWE_TD->old_speech_shb_fx[0], (float *) &st->hBWE_TD->old_speech_shb[0], 0, L_LOOK_16k + L_SUBFR16k ); + fixedToFloat_arr( (Word16 *) &st->hBWE_FD->old_fdbwe_speech_fx[0], (float *) &st->hBWE_FD->old_fdbwe_speech[0], 0, L_FRAME48k ); + fixedToFloat_arr( (Word16 *) &st->hBWE_FD->L_old_wtda_swb_fx[0], (float *) &st->hBWE_FD->old_wtda_swb[0], 0, L_FRAME48k ); + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input[ii] = (Word16) st->hBWE_FD->old_input_fx[ii]; + } + fixedToFloat_arrL32( (Word32 *) &st->cldfbSynTd->cldfb_state_fx[0], (float *) &st->cldfbSynTd->cldfb_state[0], q_realImagBuffer, st->cldfbSynTd->p_filter_length ); + fixedToFloat_arr( new_swb_speech_16_fx, new_swb_speech, 0, L_FRAME48k ); + if ( use_shb32 == 0 ) + { + fixedToFloat_arr( shb_speech_fx, shb_speech, 0, L_FRAME16k ); + } + else + { + fixedToFloat_arrL( shb_speech_fx_32, shb_speech, q_realImagBuffer - 1, L_FRAME16k ); + } + fixedToFloat_arrL32( (Word32 *) &realBuffer_fx[0][0], (float *) &realBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + fixedToFloat_arrL32( (Word32 *) &imagBuffer_fx[0][0], (float *) &imagBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + st->hBWE_TD->cldfbHBLT_flt = fix16_to_float( st->hBWE_TD->cldfbHBLT, Q13 ); + + if ( st->element_mode == IVAS_CPE_DFT ) + { + hCPE->hStereoICBWE->icbweRefEner = me2f( hCPE->hStereoICBWE->icbweRefEner_fx, hCPE->hStereoICBWE->icbweRefEner_fx_e ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); + } +#endif #else swb_pre_proc( st, new_swb_speech, shb_speech, realBuffer[n], imagBuffer[n], hCPE ); #endif @@ -420,7 +1063,14 @@ ivas_error ivas_core_enc( { if ( st->hBWE_TD != NULL ) { +#ifdef IVAS_FLOAT_FIXED + InitSWBencBufferStates_fx( st->hBWE_TD, shb_speech_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS InitSWBencBufferStates( st->hBWE_TD, shb_speech ); +#endif +#else + InitSWBencBufferStates( st->hBWE_TD, shb_speech ); +#endif } } @@ -431,19 +1081,197 @@ ivas_error ivas_core_enc( { float fb_exc[L_FRAME16k]; +#ifdef IVAS_FLOAT_FIXED + Word16 fb_exc_fx[L_FRAME16k]; + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_fb_exc; + + /* Temporarily calculating variable Q. Will get Q values from core processing */ + Q_new[n] = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); + Q_new[n] = Q_new[n] / 2; + + Q_shb_spch = Q_factor_arr( shb_speech, L_FRAME16k ); + Q_shb_spch = min( Q_shb_spch, Q_factor_arr( st->hBWE_TD->old_speech_shb, L_LOOK_16k + L_SUBFR16k ) ); + Q_shb_spch = min( Q_shb_spch, Q_factor_arr( st->hBWE_TD->shb_inv_filt_mem, LPC_SHB_ORDER ) ); + + if ( st->hBWE_TD != NULL ) + { + Word16 tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb, 2 * ALLPASSSECTIONS_STEEP + 1 ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_syn_shbexc, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_lpc_syn, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->old_bwe_exc_extended, NL_BUFF_OFFSET ) ); + Word16 tmp_q_2 = Q_factor_arrL( st->hBWE_TD->mem_csfilt, 2 ); + st->prev_Q_bwe_exc = min( tmp_q_2, tmp_q_1 + 16 ) - 2 /* Guard bits */; /* This reset need to be looked into once core processing is complete */ + + tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_stp_swb, LPC_SHB_ORDER ); + st->prev_Q_bwe_syn = tmp_q_1; /* This reset need to be looked into once core processing is complete */ + } + + floatToFixed_arr( voice_factors[n], voice_factors_fx[n], Q15, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr( pitch_buf[n], pitch_buf_fx[n], Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); + + // prev_lsp_wb_temp_fx, prev_lsp_wb_fx and prev_lpc_wb_fx in Q15. No float counterparts + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + floatToFixed_arr( shb_speech, shb_speech_fx, Q_shb_spch, L_FRAME16k ); + + if ( st->hBWE_TD != NULL ) + { + floatToFixed_arr16( st->hBWE_TD->old_speech_shb, st->hBWE_TD->old_speech_shb_fx, Q_shb_spch, L_LOOK_16k + L_SUBFR16k ); + floatToFixed_arr16( st->hBWE_TD->shb_inv_filt_mem, st->hBWE_TD->shb_inv_filt_mem_fx, Q_shb_spch, LPC_SHB_ORDER ); // Check + floatToFixed_arr16( st->hBWE_TD->prev_lsp_shb, st->hBWE_TD->prev_lsp_shb_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_spacing, st->hBWE_TD->lsp_shb_spacing_fx, Q15, 3 ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_slow_interpl, st->hBWE_TD->lsp_shb_slow_interpl_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_fast_interpl, st->hBWE_TD->lsp_shb_fast_interpl_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->swb_lsp_prev_interp, st->hBWE_TD->swb_lsp_prev_interp_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->prev_lsf_diff, st->hBWE_TD->prev_lsf_diff_fx, Q15, LPC_SHB_ORDER - 2 ); + floatToFixed_arr16( st->hBWE_TD->cur_sub_Aq, st->hBWE_TD->cur_sub_Aq_fx, Q12, M + 1 ); + st->hBWE_TD->prev_tilt_para_fx = float_to_fix16( st->hBWE_TD->prev_tilt_para, Q10 ); + st->hBWE_TD->prev_pow_exc16kWhtnd_fx32 = floatToFixed( st->hBWE_TD->prev_pow_exc16kWhtnd, 0 ); + floatToFixed_arr16( st->hBWE_TD->state_lpc_syn, st->hBWE_TD->state_lpc_syn_fx, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + floatToFixed_arr32( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_csfilt_fx, st->prev_Q_bwe_exc, 2 ); + st->hBWE_TD->gain_prec_swb_fx = float_to_fix16( st->hBWE_TD->gain_prec_swb, Q14 ); + st->hBWE_TD->cldfbHBLT = float_to_fix16( st->hBWE_TD->cldfbHBLT_flt, Q13 ); + st->hBWE_TD->prev_mix_factor_fx = float_to_fix16( st->hBWE_TD->prev_mix_factor, Q15 ); + st->hBWE_TD->prev_gainFr_SHB_fx = floatToFixed( st->hBWE_TD->prev_gainFr_SHB, Q18 ); // Satruation conversion used. Need to look into this + st->hBWE_TD->old_mean_EnvSHBres_fx = float_to_fix16( st->hBWE_TD->old_mean_EnvSHBres, Q15 ); + floatToFixed_arr16( st->hBWE_TD->mem_stp_swb, st->hBWE_TD->mem_stp_swb_fx, st->prev_Q_bwe_syn, LPC_SHB_ORDER ); + st->hBWE_TD->prev_swb_GainShape_fx = float_to_fix16( st->hBWE_TD->prev_swb_GainShape, Q15 ); + floatToFixed_arr( &st->hBWE_TD->tbe_demph, &st->hBWE_TD->tbe_demph_fx, st->prev_Q_bwe_exc - 16 - NOISE_QADJ, 1 ); // Satruation conversion used as -ve Q not handled + floatToFixed_arr( &st->hBWE_TD->tbe_premph, &st->hBWE_TD->tbe_premph_fx, st->prev_Q_bwe_exc - 16, 1 ); // Satruation conversion used as -ve Q not handled + } +#endif + swb_tbe_enc_ivas_fx( st, hStereoICBWE, shb_speech_fx, bwe_exc_extended_fx[n], voice_factors_fx[n], fb_exc_fx, &Q_fb_exc, Q_new[n], Q_shb_spch, st->voicing_fx, pitch_buf_fx[n] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hBWE_TD != NULL ) + { + fixedToFloat_arr( st->hBWE_TD->old_speech_shb_fx, st->hBWE_TD->old_speech_shb, Q_shb_spch, L_LOOK_16k + L_SUBFR16k ); + fixedToFloat_arr( st->hBWE_TD->shb_inv_filt_mem_fx, st->hBWE_TD->shb_inv_filt_mem, Q_shb_spch, LPC_SHB_ORDER ); // Check + fixedToFloat_arr( st->hBWE_TD->prev_lsp_shb_fx, st->hBWE_TD->prev_lsp_shb, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_spacing_fx, st->hBWE_TD->lsp_shb_spacing, Q15, 3 ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_slow_interpl_fx, st->hBWE_TD->lsp_shb_slow_interpl, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_fast_interpl_fx, st->hBWE_TD->lsp_shb_fast_interpl, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->swb_lsp_prev_interp_fx, st->hBWE_TD->swb_lsp_prev_interp, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->prev_lsf_diff_fx, st->hBWE_TD->prev_lsf_diff, Q15, LPC_SHB_ORDER - 2 ); + fixedToFloat_arr( st->hBWE_TD->cur_sub_Aq_fx, st->hBWE_TD->cur_sub_Aq, Q12, M + 1 ); + st->hBWE_TD->prev_tilt_para = fixedToFloat( st->hBWE_TD->prev_tilt_para_fx, Q10 ); + st->hBWE_TD->prev_pow_exc16kWhtnd = fixedToFloat( st->hBWE_TD->prev_pow_exc16kWhtnd_fx32, 0 ); + fixedToFloat_arr( st->hBWE_TD->state_lpc_syn_fx, st->hBWE_TD->state_lpc_syn, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + fixedToFloat_arrL( st->hBWE_TD->mem_csfilt_fx, st->hBWE_TD->mem_csfilt, st->prev_Q_bwe_exc, 2 ); + st->hBWE_TD->gain_prec_swb = fixedToFloat( st->hBWE_TD->gain_prec_swb_fx, Q14 ); + st->hBWE_TD->cldfbHBLT_flt = fixedToFloat( st->hBWE_TD->cldfbHBLT, Q13 ); + st->hBWE_TD->prev_mix_factor = fixedToFloat( st->hBWE_TD->prev_mix_factor_fx, Q15 ); + st->hBWE_TD->prev_gainFr_SHB = fixedToFloat( st->hBWE_TD->prev_gainFr_SHB_fx, Q18 ); + st->hBWE_TD->old_mean_EnvSHBres = fixedToFloat( st->hBWE_TD->old_mean_EnvSHBres_fx, Q15 ); + fixedToFloat_arr( st->hBWE_TD->mem_stp_swb_fx, st->hBWE_TD->mem_stp_swb, st->prev_Q_bwe_syn, LPC_SHB_ORDER ); + st->hBWE_TD->prev_swb_GainShape = fixedToFloat( st->hBWE_TD->prev_swb_GainShape_fx, Q15 ); + st->hBWE_TD->tbe_demph = fixedToFloat( st->hBWE_TD->tbe_demph_fx, st->prev_Q_bwe_exc - 16 - NOISE_QADJ ); + st->hBWE_TD->tbe_premph = fixedToFloat( st->hBWE_TD->tbe_premph_fx, st->prev_Q_bwe_exc - 16 ); + } +#endif +#else swb_tbe_enc( st, hStereoICBWE, shb_speech, bwe_exc_extended[n], voice_factors[n], fb_exc, pitch_buf[n] ); +#endif if ( st->extl == FB_TBE ) { /* FB TBE encoder */ +#ifndef IVAS_FLOAT_FIXED fb_tbe_enc( st, st->input, fb_exc ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Q_fb_exc = Q_factor_arr( fb_exc, L_FRAME16k ); + floatToFixed_arr( fb_exc, fb_exc_fx, Q_fb_exc, L_FRAME16k ); + // Q_input is being calculated inside already + Word16 Q_input = 0; + floatToFixed_arr( st->input_buff, st->input_buff_fx, Q_input, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + Word16 len_old_input_fhb_fx = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2; + st->hBWE_TD->old_input_fhb_fx_Q = Q_factor_arr( st->hBWE_TD->old_input_fhb, len_old_input_fhb_fx ); + floatToFixed_arr( st->hBWE_TD->old_input_fhb, st->hBWE_TD->old_input_fhb_fx, st->hBWE_TD->old_input_fhb_fx_Q, len_old_input_fhb_fx ); + st->hBWE_TD->prev_fb_energy_fx = floatToFixed( st->hBWE_TD->prev_fb_energy, st->hBWE_TD->prev_fb_energy_fx_Q ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[0], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[1], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[2], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[3], 4 ); +#endif + fb_tbe_enc_ivas_fx( st, st->input_fx, fb_exc_fx, Q_fb_exc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( fb_exc_fx, fb_exc, Q_fb_exc, L_FRAME16k ); + fixedToFloat_arr( st->input_fx, st->input, Q_input, L_FRAME48k ); + fixedToFloat_arr( st->hBWE_TD->old_input_fhb_fx, st->hBWE_TD->old_input_fhb, st->hBWE_TD->old_input_fhb_fx_Q, len_old_input_fhb_fx ); + st->hBWE_TD->prev_fb_energy = fixedToFloat( st->hBWE_TD->prev_fb_energy_fx, st->hBWE_TD->prev_fb_energy_fx_Q ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[0], st->hBWE_TD->elliptic_bpf_2_48k_mem[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[0], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[1], st->hBWE_TD->elliptic_bpf_2_48k_mem[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[1], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[2], st->hBWE_TD->elliptic_bpf_2_48k_mem[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[2], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[3], st->hBWE_TD->elliptic_bpf_2_48k_mem[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[3], 4 ); +#endif +#endif } } } else if ( st->extl == SWB_BWE || st->extl == FB_BWE ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 old_inp_12k8_fx[L_INP_12k8], old_inp_16k_fx[L_INP]; + Word16 q_val; + Word16 q_old_inp_16k_fx, q_old_syn_12k8_16k_fx, q_old_input_lp; + Word16 q_old_inp_12k8_fx, q_shb_speech_fx, q_new_input_hp; + + q_old_inp_12k8_fx = Q_factor_arr( old_inp_12k8[n], L_INP_12k8 ); + q_old_inp_16k_fx = Q_factor_arr( old_inp_16k[n], L_INP ); + q_old_syn_12k8_16k_fx = Q_factor_arr( old_syn_12k8_16k[n], L_FRAME16k ); + q_shb_speech_fx = Q_factor_arr( shb_speech, L_FRAME16k ); + + q_val = s_min( q_old_inp_12k8_fx, q_old_inp_16k_fx ); + q_val = s_min( q_val, q_old_syn_12k8_16k_fx ); + + if ( st->hBWE_FD != NULL ) + { + q_old_input_lp = Q_factor_arr( st->hBWE_FD->old_input_lp, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + q_val = s_min( q_val, q_old_input_lp ); + q_new_input_hp = Q_factor_arr( st->hBWE_FD->new_input_hp, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + q_shb_speech_fx = s_min( q_shb_speech_fx, q_new_input_hp ); + st->Q_old_wtda = Q_factor_arr( st->hBWE_FD->old_wtda_swb, L_FRAME48k ); + floatToFixed_arr16( st->hBWE_FD->old_input_lp, st->hBWE_FD->old_input_lp_fx, q_val, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + floatToFixed_arr16( st->hBWE_FD->new_input_hp, st->hBWE_FD->new_input_hp_fx, q_shb_speech_fx, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + floatToFixed_arr16( st->hBWE_FD->old_wtda_swb, st->hBWE_FD->L_old_wtda_swb_fx, st->Q_old_wtda, L_FRAME48k ); + } + + floatToFixed_arr16( old_inp_12k8[n], old_inp_12k8_fx, q_val, L_INP_12k8 ); + floatToFixed_arr16( old_inp_16k[n], old_inp_16k_fx, q_val, L_INP ); + floatToFixed_arr16( old_syn_12k8_16k[n], old_syn_12k8_16k_fx[n], q_val, L_FRAME16k ); + floatToFixed_arr16( shb_speech, shb_speech_fx, q_shb_speech_fx, L_FRAME16k ); + + for ( int ii = 0; ii < L_FRAME48k + STEREO_DFT_OVL_MAX; ii++ ) + { + new_swb_speech_buffer_fx1[ii] = (Word16) new_swb_speech_buffer[ii]; + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input_fx[ii] = (Word16) st->hBWE_FD->old_input[ii]; + } +#endif + /* SWB(FB) BWE encoder */ + swb_bwe_enc_ivas_fx( st, last_element_mode, old_inp_12k8_fx, old_inp_16k_fx, old_syn_12k8_16k_fx[n], new_swb_speech_fx1, shb_speech_fx, q_shb_speech_fx, q_val ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hBWE_FD != NULL ) + { + fixedToFloat_arr( st->hBWE_FD->old_input_lp_fx, st->hBWE_FD->old_input_lp, q_val, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + fixedToFloat_arr( st->hBWE_FD->new_input_hp_fx, st->hBWE_FD->new_input_hp, q_shb_speech_fx, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + fixedToFloat_arr( st->hBWE_FD->L_old_wtda_swb_fx, st->hBWE_FD->old_wtda_swb, st->Q_old_wtda, L_FRAME48k ); + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input[ii] = (float) st->hBWE_FD->old_input_fx[ii]; + } + st->EnergyLT = fixedToFloat( st->EnergyLT_fx, st->EnergyLT_fx_exp ); +#endif +#else /* SWB(FB) BWE encoder */ swb_bwe_enc( st, last_element_mode, old_inp_12k8[n], old_inp_16k[n], old_syn_12k8_16k[n], new_swb_speech, shb_speech ); +#endif } /*---------------------------------------------------------------------* @@ -453,7 +1281,32 @@ ivas_error ivas_core_enc( if ( st->hTdCngEnc != NULL && st->Opt_DTX_ON && ( input_frame >= L_FRAME32k || st->element_mode == IVAS_CPE_DFT ) ) { /* SHB DTX/CNG encoder */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + floatToFixed_arr( old_syn_12k8_16k[i], old_syn_12k8_16k_fx[i], 0, L_FRAME16k ); + } + + floatToFixed_arr( shb_speech, shb_speech_fx, 0, L_FRAME16k ); + + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) + { + IF( st->cng_type == LP_CNG ) + { + IF( GE_32( st->input_Fs, L_FRAME32k * FRAMES_PER_SEC ) ) + { + /* decide if SHB SID encoding or not */ + floatToFixed_arr( st->hBWE_TD->old_speech_shb, st->hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + } + } + } +#endif + swb_CNG_enc_ivas_fx( st, shb_speech_fx, old_syn_12k8_16k_fx[n] ); +#else swb_CNG_enc( st, shb_speech, old_syn_12k8_16k[n] ); +#endif } /*-------------------------------------------------------------------* @@ -491,8 +1344,8 @@ ivas_error ivas_core_enc( floatToFixed_arr16( hCPE->hStereoICBWE->dec_2over3_mem_lp, hCPE->hStereoICBWE->dec_2over3_mem_lp_fx, scale_factor, 3 ); floatToFixed_arr16( hCPE->hStereoICBWE->memModifyFs_icbwe[0], hCPE->hStereoICBWE->memModifyFs_icbwe_fx[0], scale_factor, 60 ); floatToFixed_arr16( hCPE->hStereoICBWE->memModifyFs_icbwe[1], hCPE->hStereoICBWE->memModifyFs_icbwe_fx[1], scale_factor, 60 ); - floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[0], hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], scale_factor, 270 ); - floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[1], hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], scale_factor, 270 ); + floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[0], hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], scale_factor, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); + floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[1], hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], scale_factor, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); floatToFixed_arr16( hCPE->hStereoICBWE->mem_decim_shb_ch0, hCPE->hStereoICBWE->mem_decim_shb_ch0_fx, 0, 90 ); @@ -510,8 +1363,8 @@ ivas_error ivas_core_enc( fixedToFloat_arr( hCPE->hStereoICBWE->dec_2over3_mem_lp_fx, hCPE->hStereoICBWE->dec_2over3_mem_lp, scale_factor, 3 ); fixedToFloat_arr( hCPE->hStereoICBWE->memModifyFs_icbwe_fx[0], hCPE->hStereoICBWE->memModifyFs_icbwe[0], scale_factor, 60 ); fixedToFloat_arr( hCPE->hStereoICBWE->memModifyFs_icbwe_fx[1], hCPE->hStereoICBWE->memModifyFs_icbwe[1], scale_factor, 60 ); - fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], hCPE->hStereoICBWE->icbwe_inp_mem[0], scale_factor, 270 ); - fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], hCPE->hStereoICBWE->icbwe_inp_mem[1], scale_factor, 270 ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], hCPE->hStereoICBWE->icbwe_inp_mem[0], scale_factor, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], hCPE->hStereoICBWE->icbwe_inp_mem[1], scale_factor, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); fixedToFloat_arr( hCPE->hStereoICBWE->mem_decim_shb_ch0_fx, hCPE->hStereoICBWE->mem_decim_shb_ch0, 0, 90 ); @@ -519,22 +1372,191 @@ ivas_error ivas_core_enc( stereo_icBWE_preproc( hCPE, input_frame, new_swb_speech_buffer /*tmp buffer*/ ); #endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 nbSubFr; + Word32 shb_speech_fx32[L_FRAME16k]; + Word32 voice_factors_fx32[CPE_CHANNELS][NB_SUBFR16k]; + Word16 q_shb_speech_fx32 = Q_factor_arrL( shb_speech, L_FRAME16k ); + floatToFixed_arrL( shb_speech, shb_speech_fx32, q_shb_speech_fx32, L_FRAME16k ); + f2me_buf_16( hStereoICBWE->mixExc16k, hStereoICBWE->mixExc16k_fx, &hStereoICBWE->mixExc16k_e, L_FRAME16k ); + IF( st->flag_ACELP16k == 0 ) + { + nbSubFr = NB_SUBFR; + move16(); + } + ELSE + { + nbSubFr = NB_SUBFR16k; + move16(); + } + f2me_buf_16( hStereoICBWE->nlExc16k, hStereoICBWE->nlExc16k_fx, &hStereoICBWE->nlExc16k_e, L_FRAME16k / nbSubFr ); + q_new_swb_speech_buffer = Q_factor_arrL( new_swb_speech_buffer, input_frame ); + floatToFixed_arrL( new_swb_speech_buffer, new_swb_speech_buffer_fx, q_new_swb_speech_buffer, input_frame ); + Copy_Scale_sig_16_32( voice_factors_fx[0], voice_factors_fx32[0], NB_SUBFR16k, 16 ); // Q31 + f2me_buf_16( hCPE->hStereoICBWE->mem_shb_speech_nonref, hCPE->hStereoICBWE->mem_shb_speech_nonref_fx, &hCPE->hStereoICBWE->mem_shb_speech_nonref_e, L_LOOK_16k ); // shb_speech_ref_e + f2me_buf_16( hCPE->hStereoICBWE->mem_shb_speech_ref, hCPE->hStereoICBWE->mem_shb_speech_ref_fx, &hCPE->hStereoICBWE->mem_shb_speech_ref_e, L_LOOK_16k ); // shb_speech_ref_e + f2me_buf_16( hCPE->hStereoICBWE->shbSynthRef, hCPE->hStereoICBWE->shbSynthRef_fx, &hCPE->hStereoICBWE->shbSynthRef_e, L_LOOK_16k ); // shb_speech_ref_e + + f2me( hCPE->hStereoICBWE->icbweRefEner, &hCPE->hStereoICBWE->icbweRefEner_fx, &hCPE->hStereoICBWE->icbweRefEner_e ); + scale_factor = Q_factor_arrL( hCPE->hStereoICBWE->lpSHBRef, LPC_SHB_ORDER + 1 ) - 1; + scale_factor = s_min( scale_factor, Q_factor_arrL( hCPE->hStereoICBWE->mem_lpc_shbsynth_nonref, LPC_SHB_ORDER ) ); + floatToFixed_arr32( hCPE->hStereoICBWE->lpSHBRef, hCPE->hStereoICBWE->lpSHBRef_fx, scale_factor, LPC_SHB_ORDER + 1 ); + floatToFixed_arr32( hCPE->hStereoICBWE->mem_lpc_shbsynth_nonref, hCPE->hStereoICBWE->mem_lpc_shbsynth_nonref_fx, scale_factor, LPC_SHB_ORDER ); + hCPE->hStereoICBWE->lpSHBRef_e = 31 - scale_factor; + +#endif + stereo_icBWE_enc_ivas_fx( hCPE, shb_speech_fx32, 31 - q_shb_speech_fx32, new_swb_speech_buffer_fx, 31 - q_new_swb_speech_buffer, voice_factors_fx32[0] ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( hStereoICBWE->mem_shb_speech_ref_fx, hStereoICBWE->mem_shb_speech_ref, 15 - hStereoICBWE->mem_shb_speech_ref_e, LPC_SHB_ORDER ); + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + hStereoICBWE->prevSpecMapping = fixedToFloat( hStereoICBWE->prevSpecMapping_fx, 31 ); + IF( ( st->extl == SWB_TBE || st->extl == FB_TBE ) && st->flag_ACELP16k == 1 ) + { + fixedToFloat_arrL( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, hStereoICBWE->mem_lpc_shbsynth_nonref, 31 - hStereoICBWE->mem_lpc_shbsynth_nonref_e, LPC_SHB_ORDER ); + } + ELSE + { + me2f_buf_16( hStereoICBWE->shbSynthRef_fx, hStereoICBWE->shbSynthRef_e, hStereoICBWE->shbSynthRef, L_FRAME16k ); + } + + FOR( i = 0; i < 2; i++ ) + { + hStereoICBWE->memGsEnerMap[i] = me2f( hStereoICBWE->memGsEnerMap_fx[i], hStereoICBWE->memGsEnerMap_e ); + } + + hStereoICBWE->prevgsMapping = me2f( hStereoICBWE->prevgsMapping_fx, 0 ); + + IF( ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, WB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && EQ_16( st->flag_ACELP16k, 1 ) ) + { + hStereoICBWE->prevSpecMapping = fixedToFloat( hStereoICBWE->prevSpecMapping_fx, Q31 ); + hStereoICBWE->memShbSpecMapping = fixedToFloat( hStereoICBWE->memShbSpecMapping_fx, 31 - hStereoICBWE->memShbSpecMapping_e ); + } + ELSE + { + hStereoICBWE->memShbSpecMapping = 0; + hStereoICBWE->prevSpecMapping = 0; + } + } + ELSE + { + hStereoICBWE->prevgsMapping = me2f( hStereoICBWE->prevgsMapping_fx, hStereoICBWE->prevgsMapping_e ); + hStereoICBWE->gDes_pastFrame = me2f( hStereoICBWE->gDes_pastFrame_fx, hStereoICBWE->gDes_pastFrame_e ); + + IF( ( st->extl == SWB_TBE || st->extl == WB_TBE || st->extl == FB_TBE ) && st->flag_ACELP16k == 1 ) + { + + + me2f_buf( hStereoICBWE->memShbSpecXcorr_fx, hStereoICBWE->memShbSpecXcorr_e, hStereoICBWE->memShbSpecXcorr, 6 ); + hStereoICBWE->memShbSpecMapping = me2f( hStereoICBWE->memShbSpecMapping_fx, hStereoICBWE->memShbSpecMapping_e ); + } + + hStereoICBWE->prevRefEner = fixedToFloat( hStereoICBWE->prevRefEner_fx, 31 - hStereoICBWE->prevRefEner_e ); + hStereoICBWE->prevNonRefEner = fixedToFloat( hStereoICBWE->prevNonRefEner_fx, 31 - hStereoICBWE->prevNonRefEner_e ); + IF( ( st->extl == SWB_TBE || st->extl == FB_TBE ) && st->flag_ACELP16k == 1 ) + { + fixedToFloat_arrL( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, hStereoICBWE->mem_lpc_shbsynth_nonref, 31 - hStereoICBWE->mem_lpc_shbsynth_nonref_e, LPC_SHB_ORDER ); + } + hStereoICBWE->gDes_pastFrame = me2f( hStereoICBWE->gDes_pastFrame_fx, hStereoICBWE->gDes_pastFrame_e ); + } +#endif +#else stereo_icBWE_enc( hCPE, shb_speech, new_swb_speech_buffer, voice_factors[0] ); +#endif } /*---------------------------------------------------------------------* * Channel-aware mode - write signaling information into the bitstream *---------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + signaling_enc_rf_fx( st ); +#else signaling_enc_rf( st ); - +#endif /*---------------------------------------------------------------------* * Common updates *---------------------------------------------------------------------*/ if ( !MCT_flag ) /* for MCT do this later, otherwise there can be a problem because TCX quant happens later and might get the wrong last_core on a bit rate switch */ { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf_16( st->buf_speech_enc_pe_flt, st->buf_speech_enc_pe, &st->exp_buf_speech_enc_pe, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_speech_enc_flt, st->buf_speech_enc, &st->exp_buf_speech_enc, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_synth_flt, st->buf_synth, &st->exp_buf_synth, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + f2me_buf_16( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, &st->exp_buf_wspeech_enc, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + f2me_buf_16( st->hTcxEnc->buf_speech_ltp_flt, st->hTcxEnc->buf_speech_ltp, &st->hTcxEnc->exp_buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, 15 ); + } +#endif + + updt_enc_common_ivas_fx( st ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf_16( st->buf_speech_enc_pe, st->exp_buf_speech_enc_pe, st->buf_speech_enc_pe_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_speech_enc, st->exp_buf_speech_enc, st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_synth, st->exp_buf_synth, st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + me2f_buf_16( st->buf_wspeech_enc, st->exp_buf_wspeech_enc, st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + me2f_buf_16( st->hTcxEnc->buf_speech_ltp, st->hTcxEnc->exp_buf_speech_ltp, st->hTcxEnc->buf_speech_ltp_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) + { + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + IF( st->hTcxEnc != NULL ) + { + IF( st->element_mode != IVAS_CPE_MDCT ) + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + } + } + + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem_flt = fixedToFloat( st->hTcxEnc->tcxltp_norm_corr_mem, 31 ); + } + + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac_flt = PREEMPH_FAC_FLT; + st->gamma_flt = GAMMA1_FLT; + } + ELSE + { + st->preemph_fac_flt = PREEMPH_FAC_16k_FLT; + st->gamma_flt = GAMMA16k_FLT; + } + } + + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + } + } +#endif +#else updt_enc_common( st ); +#endif } } diff --git a/lib_enc/ivas_core_pre_proc.c b/lib_enc/ivas_core_pre_proc.c index 50123f85702d0b21526a4d4fa0a1f4e14ebf91e3..12a7d1d8dce3e27600680134320c12a23817c938 100644 --- a/lib_enc/ivas_core_pre_proc.c +++ b/lib_enc/ivas_core_pre_proc.c @@ -40,7 +40,9 @@ #include "prot.h" #include "wmc_auto.h" #include "prot_fx.h" - +#include "ivas_prot_fx.h" +#include "prot_fx_enc.h" +#include "basop_util.h" /*-------------------------------------------------------------------* * pre_proc_ivas() @@ -50,31 +52,43 @@ *--------------------------------------------------------------------*/ ivas_error pre_proc_ivas( - Encoder_State *st, /* i/o: encoder state structure */ - const int16_t last_element_mode, /* i : last element mode */ - const int32_t element_brate, /* i : element bitrate */ - const int32_t last_element_brate, /* i : last element bitrate */ - const int16_t input_frame, /* i : frame length */ - float old_inp_12k8[], /* i/o: buffer of old input signal */ - float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ - float **inp, /* o : ptr. to inp. signal in the current frame*/ - float *ener, /* o : residual energy from Levinson-Durbin */ - float A[NB_SUBFR16k * ( M + 1 )], /* i/o: A(z) unquantized for the 4 subframes */ - float Aw[NB_SUBFR16k * ( M + 1 )], /* i/o: weighted A(z) unquantized for subframes */ - float epsP[M + 1], /* i/o: LP prediction errors */ - float lsp_new[M], /* i/o: LSPs at the end of the frame */ - float lsp_mid[M], /* i/o: LSPs in the middle of the frame */ - float *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ - int16_t *Voicing_flag, /* o : voicing flag for HQ FEC */ - const float old_wsp[], /* i : weighted input signal buffer */ - const int16_t loc_harm, /* i : harmonicity flag */ - const float cor_map_sum, /* i : speech/music clasif. parameter */ - const int16_t vad_flag_dtx, /* i : HE-SAD flag with additional DTX HO */ - const float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ - const float fft_buff[2 * L_FFT], /* i : FFT buffer */ - const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ - const int16_t vad_hover_flag, /* i : VAD hangover flag */ - const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ + Encoder_State *st, /* i/o: encoder state structure */ + const int16_t last_element_mode, /* i : last element mode */ + const int32_t element_brate, /* i : element bitrate */ + const int32_t last_element_brate, /* i : last element bitrate */ + const int16_t input_frame, /* i : frame length */ + float old_inp_12k8[], /* i/o: buffer of old input signal */ + float old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + float **inp, /* o : ptr. to inp. signal in the current frame*/ + float *ener, /* o : residual energy from Levinson-Durbin */ + float A[NB_SUBFR16k * ( M + 1 )], /* i/o: A(z) unquantized for the 4 subframes */ + float Aw[NB_SUBFR16k * ( M + 1 )], /* i/o: weighted A(z) unquantized for subframes */ + float epsP[M + 1], /* i/o: LP prediction errors */ + float lsp_new[M], /* i/o: LSPs at the end of the frame */ + float lsp_mid[M], /* i/o: LSPs in the middle of the frame */ + float *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + int16_t *Voicing_flag, /* o : voicing flag for HQ FEC */ + const float old_wsp[], /* i : weighted input signal buffer */ + const int16_t loc_harm, /* i : harmonicity flag */ +#ifndef IVAS_FLOAT_FIXED + const float cor_map_sum, /* i : speech/music clasif. parameter */ +#endif + const int16_t vad_flag_dtx, /* i : HE-SAD flag with additional DTX HO */ +#ifndef IVAS_FLOAT_FIXED + /*const*/ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy buffer */ + /*const*/ float fft_buff[2 * L_FFT], /* i : FFT buffer */ +#endif + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t vad_hover_flag, /* i : VAD hangover flag */ + const int16_t flag_16k_smc /* i : flag to indicate if the OL SMC is run at 16 kHz */ +#ifdef IVAS_FLOAT_FIXED + , + Word32 enerBuffer_fx[CLDFB_NO_CHANNELS_MAX], + Word16 e_enerBuffer, + Word16 fft_buff_fx[2 * L_FFT], + Word32 cor_map_sum_fx, + Word16 exp_cor_map_sum +#endif ) { int16_t L_look, element_mode, lMemRecalc_12k8; @@ -93,6 +107,44 @@ ivas_error pre_proc_ivas( element_mode = st->element_mode; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 A_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 lsp_new_fx[M]; + Word16 lsp_mid_fx[M]; + + floatToFixed_arr16( A, A_fx, Q12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr16( Aw, Aw_fx, Q12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr16( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr16( lsp_mid, lsp_mid_fx, Q15, M ); +#endif + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS1 + Word16 old_inp_16k_fx[L_INP_MEM]; + Word16 exp_old_inp_16k = 0; + Word16 old_inp_12k8_fx[496]; + Word16 exp_old_inp_12k8 = 0; + Word16 old_wsp_fx[L_WSP]; + Word16 exp_old_wsp = 0; + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )], exp_Aw = 0; + Word16 lsp_new_fx[M], exp_lsp_new = 0; + Word16 lsp_mid_fx[M], exp_lsp_mid = 0; + Word16 epsP_fx[M + 1], exp_epsP = 0; + Word32 enerBuffer_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 fft_buff_fx[2 * L_FFT]; + Word32 cor_map_sum_fx = 0; + Word16 exp_cor_map_sum = 0; + Word16 q_fft_buff; + Word16 e_enerBuffer; + + /*input buffers*/ + f2me_buf_16( st->old_inp_16k, old_inp_16k_fx, &exp_old_inp_16k, L_INP_MEM ); + f2me_buf_16( old_inp_12k8, old_inp_12k8_fx, &exp_old_inp_12k8, 496 ); + f2me_buf_16( old_wsp, old_wsp_fx, &exp_old_wsp, L_WSP ); + f2me_buf_16( epsP, epsP_fx, &exp_epsP, M + 1 ); + f2me( cor_map_sum, &cor_map_sum_fx, &exp_cor_map_sum ); +#endif + new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ inp_12k8 = new_inp_12k8 - L_LOOK_12k8; @@ -108,11 +160,115 @@ ivas_error pre_proc_ivas( { lMemRecalc_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_NS ); } - /*----------------------------------------------------------------* * Selection of internal ACELP Fs (12.8 kHz or 16 kHz) *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_32( st->core_brate, FRAME_NO_DATA ) ) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame = st->last_L_frame; + move16(); + } + ELSE IF( EQ_32( st->core_brate, SID_2k40 ) && GE_16( st->bwidth, WB ) && st->hDtxEnc->first_CNG && ( st->hTdCngEnc != NULL && LT_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) ) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame = st->hDtxEnc->last_CNG_L_frame; + move16(); + } + ELSE IF( ( ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && GE_32( st->element_brate, IVAS_64k ) && GE_16( st->bwidth, SWB ) ) || ( EQ_16( element_mode, IVAS_SCE ) && GT_32( st->total_brate, MAX_ACELP_BRATE ) && GE_16( st->bwidth, SWB ) ) ) && NE_32( st->core_brate, SID_2k40 ) ) + { + st->L_frame = L_FRAME32k; + move16(); + } + ELSE IF( GE_16( st->bwidth, SWB ) && GT_32( st->total_brate, MAX_ACELP_BRATE_ISM ) && LE_32( st->total_brate, MAX_ACELP_BRATE ) && EQ_16( element_mode, IVAS_SCE ) && st->is_ism_format && st->tcxonly && NE_32( st->core_brate, SID_2k40 ) ) + { + st->L_frame = L_FRAME25_6k; + move16(); + } + ELSE IF( st->flag_ACELP16k ) + { + st->L_frame = L_FRAME16k; + move16(); + } + ELSE + { + st->L_frame = L_FRAME; + move16(); + } + + test(); + test(); + test(); + Word16 flag_1 = 0; + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + flag_1 = ACELP_16k40; + move16(); + } + ELSE + { + flag_1 = ACELP_9k60; + move16(); + } + IF( st->hFdCngEnc != NULL && NE_16( st->element_mode, IVAS_CPE_MDCT ) && ( ( NE_16( st->hFdCngEnc->hFdCngCom->frameSize, st->L_frame ) ) || ( NE_16( st->hFdCngEnc->hFdCngCom->CngBandwidth, st->input_bwidth ) ) ) ) + { + configureFdCngEnc_ivas_fx( st->hFdCngEnc, max( st->input_bwidth, WB ), flag_1 ); + } + + IF( st->ini_frame == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame = st->L_frame; + move16(); + } + + IF( EQ_16( st->L_frame, L_FRAME ) ) + { + st->gamma = GAMMA1; + st->preemph_fac = PREEMPH_FAC; + move16(); + move16(); + } + ELSE IF( EQ_16( st->L_frame, L_FRAME32k ) ) + { + + st->gamma = GAMMA16k; + st->preemph_fac = PREEMPH_FAC_SWB; + move16(); + move16(); + } + ELSE + { + st->gamma = GAMMA16k; + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + move16(); + } + + st->sr_core = L_mult0( st->L_frame, FRAMES_PER_SEC ); + st->encoderLookahead_enc = NS2SA_FX2( st->sr_core, ACELP_LOOK_NS ); + st->encoderPastSamples_enc = shr( ( imult1616( st->L_frame, 9 ) ), 4 ); + move32(); + move16(); + move16(); +#else if ( st->core_brate == FRAME_NO_DATA ) { /* prevent "L_frame" changes in CNG segments */ @@ -174,14 +330,92 @@ ivas_error pre_proc_ivas( st->sr_core = st->L_frame * FRAMES_PER_SEC; st->encoderLookahead_enc = NS2SA( st->sr_core, ACELP_LOOK_NS ); st->encoderPastSamples_enc = ( st->L_frame * 9 ) >> 4; - +#endif /*-----------------------------------------------------------------* * coder_type rewriting in case of switching * IC frames selection * enforce TC frames in case of switching *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + /* enforce TRANSITION frames */ + IF( !( EQ_16( st->element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 1 ) ) && NE_16( st->last_L_frame, st->L_frame ) && NE_32( st->core_brate, FRAME_NO_DATA ) && NE_32( st->core_brate, SID_2k40 ) && NE_32( st->last_core_brate, FRAME_NO_DATA ) && NE_32( st->last_core_brate, SID_2k40 ) && NE_16( st->coder_type_raw, VOICED ) ) + { + /* enforce TC frame in case of ACELP@12k8 <-> ACELP@16k core switching */ + st->coder_type = TRANSITION; + move16(); + } + ELSE IF( EQ_16( st->last_core, HQ_CORE ) && NE_16( st->coder_type_raw, VOICED ) ) + { + /* enforce TC frame in case of HQ -> ACELP core switching */ + st->coder_type = TRANSITION; + move16(); + } + ELSE IF( LE_32( st->last_core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) && !( EQ_16( element_mode, IVAS_CPE_TD ) ) ) + { + /* enforce TC frame in case of FD_CNG -> ACELP switching (past excitation not available) */ + st->coder_type = TRANSITION; + move16(); + } + /* select INACTIVE frames */ + ELSE IF( LE_32( st->total_brate, MAX_GSC_INACTIVE_BRATE ) && st->vad_flag == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* inactive frames will be coded by GSC technology */ + /* except for the VBR mode. VBR mode uses NELP for that */ + test(); + test(); + test(); + IF( !( st->Opt_SC_VBR && vad_flag_dtx ) && ( st->idchan == 0 || NE_16( element_mode, IVAS_CPE_TD ) ) ) + { + st->coder_type = INACTIVE; + move16(); + st->hGSCEnc->noise_lev = NOISE_LEVEL_SP3; + move16(); + } + } + ELSE IF( GT_32( st->total_brate, MAX_GSC_INACTIVE_BRATE ) && ( ( st->vad_flag == 0 && GE_16( st->bwidth, SWB ) && GE_16( st->max_bwidth, SWB ) ) || ( st->localVAD == 0 && ( LE_16( st->bwidth, WB ) || LE_16( st->max_bwidth, WB ) ) ) ) ) + { + /* inactive frames will be coded by AVQ technology */ + st->coder_type = INACTIVE; + move16(); + } + + /*---------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *---------------------------------------------------------------------*/ + + st->mdct_sw = MODE1; + st->mdct_sw_enable = MODE1; + move16(); + move16(); + test(); + test(); + test(); + IF( ( LE_32( st->total_brate, MIN_BRATE_GSC_NOISY_FLAG ) || LT_16( st->bwidth, SWB ) || st->flag_ACELP16k ) && st->GSC_IVAS_mode == 0 ) + { + st->GSC_noisy_speech = 0; + move16(); + } +#else /* enforce TRANSITION frames */ if ( !( st->element_mode == IVAS_CPE_TD && st->idchan == 1 ) && st->last_L_frame != st->L_frame && st->core_brate != FRAME_NO_DATA && st->core_brate != SID_2k40 && st->last_core_brate != FRAME_NO_DATA && st->last_core_brate != SID_2k40 && st->coder_type_raw != VOICED ) { @@ -226,10 +460,221 @@ ivas_error pre_proc_ivas( { st->GSC_noisy_speech = 0; } +#endif /* core selection */ +#ifndef IVAS_FLOAT_FIXED ivas_decision_matrix_enc( st, element_brate, fft_buff, enerBuffer, last_element_mode ); +#else + ivas_decision_matrix_enc_fx( st, element_brate, fft_buff_fx, enerBuffer_fx, e_enerBuffer, last_element_mode ); +#endif +#ifdef IVAS_FLOAT_FIXED + test(); + test(); + IF( EQ_16( st->L_frame, L_FRAME16k ) && ( EQ_16( st->coder_type, VOICED ) || EQ_16( st->coder_type, UNVOICED ) ) ) /* VOICED and UNVOICED are not supported in ACELP@16k */ + { + st->coder_type = GENERIC; + move16(); + } + + test(); + IF( EQ_16( st->core, TCX_20_CORE ) || EQ_16( st->core, HQ_CORE ) ) + { + st->Nb_ACELP_frames = 0; + move16(); + /* Configure TCX with the same bitrate as given when (re-)initializing TCX */ + total_brate_tmp = st->total_brate; + move32(); + st->total_brate = L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ); + move32(); + + SetModeIndex_ivas_fx( st, st->last_bits_frame_nominal * FRAMES_PER_SEC, last_element_mode, MCT_flag ); + + st->sr_core = getCoreSamplerateMode2( element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, st->is_ism_format ); + move16(); + st->total_brate = total_brate_tmp; + move32(); + + st->L_frame = extract_l( Mpy_32_32( st->sr_core, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + st->encoderLookahead_enc = NS2SA_FX2( st->sr_core, ACELP_LOOK_NS ); + st->encoderPastSamples_enc = shr( ( imult1616( st->L_frame, 9 ) ), 4 ); + move16(); + move16(); + + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + move16(); + move16(); + } + ELSE IF( EQ_32( st->sr_core, INT_FS_16k ) ) + { + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + move16(); + move16(); + } + ELSE /* st->sr_core >=25600 */ + { + st->preemph_fac = PREEMPH_FAC_SWB; + st->gamma = GAMMA16k; + move16(); + move16(); + } + + IF( st->vad_flag == 0 ) + { + st->coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_16( st->coder_type, GENERIC ) ) + { + st->coder_type = GENERIC; + move16(); + } + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + SetTCXModeInfo_ivas_fx( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + st->hTcxEnc->tfm_mem_fx = 1610612736; /*0.75f in Q31*/ + move32(); + } + ELSE IF( NE_32( element_brate, last_element_brate ) ) + { + IF( NE_32( st->core_brate, FRAME_NO_DATA ) ) + { + SetModeIndex_ivas_fx( st, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), element_mode, MCT_flag ); + } + + test(); + test(); + IF( NE_16( st->extl, -1 ) && NE_16( st->extl, IGF_BWE ) && EQ_16( st->igf, 1 ) ) + { + st->igf = 0; + move16(); + } + } + + + /*-----------------------------------------------------------------* + * Update of ACELP harmonicity counter (used in ACELP transform codebook @32kbps) + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + Word16 flag = BASOP_Util_Cmp_Mant32Exp( cor_map_sum_fx, exp_cor_map_sum, 50, 31 ); + IF( EQ_16( loc_harm, 1 ) && flag && EQ_16( st->clas, VOICED_CLAS ) && EQ_16( st->coder_type, GENERIC ) ) + { + st->last_harm_flag_acelp = add( st->last_harm_flag_acelp, 1 ); + move16(); + + IF( GT_16( st->last_harm_flag_acelp, 10 ) ) + { + st->last_harm_flag_acelp = 10; + move16(); + } + } + ELSE + { + st->last_harm_flag_acelp = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Update audio frames counter (used for UV decision) + *-----------------------------------------------------------------*/ + + IF( EQ_16( st->coder_type, AUDIO ) ) + { + st->audio_frame_cnt = add( st->audio_frame_cnt, AUDIO_COUNTER_STEP ); + move16(); + } + ELSE IF( NE_16( st->coder_type, INACTIVE ) ) + { + st->audio_frame_cnt = sub( st->audio_frame_cnt, 1 ); + move16(); + } + + IF( GT_16( st->audio_frame_cnt, AUDIO_COUNTER_MAX ) ) + { + st->audio_frame_cnt = AUDIO_COUNTER_MAX; + move16(); + } + + IF( st->audio_frame_cnt < 0 ) + { + st->audio_frame_cnt = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Set formant sharpening flag + *-----------------------------------------------------------------*/ + + st->sharpFlag = 0; + move16(); + test(); + test(); + IF( EQ_16( st->coder_type, GENERIC ) || EQ_16( st->coder_type, VOICED ) || EQ_16( st->coder_type, TRANSITION ) ) + { + test(); + IF( GE_32( element_brate, FRMT_SHP_MIN_BRATE_IVAS ) && GT_16( st->lp_noise_fx, FORMANT_SHARPENING_NOISE_THRESHOLD_FX ) ) + { + st->sharpFlag = 0; + move16(); + } + ELSE + { + st->sharpFlag = 1; + move16(); + } + } + + /* channel-aware mode - due to lack of signaling bit, sharpFlag is 1 always in RF mode */ + test(); + test(); + IF( st->rf_mode && ( EQ_16( st->coder_type, VOICED ) || EQ_16( st->coder_type, GENERIC ) ) ) + { + st->sharpFlag = 1; + move16(); + } + + /* TD stereo, secondary channel - due to lack of signaling bits, sharpFlag is always 1 */ + test(); + IF( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 1 ) ) + { + st->sharpFlag = 0; + move16(); + test(); + IF( EQ_16( st->coder_type, GENERIC ) || EQ_16( st->coder_type, VOICED ) ) + { + st->sharpFlag = 1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Set voicing flag for HQ FEC + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( st->sp_aud_decision1 == 0 && ( EQ_16( st->coder_type, VOICED ) || EQ_16( st->coder_type, GENERIC ) ) ) + { + *Voicing_flag = 1; + move16(); + } + ELSE + { + *Voicing_flag = 0; + move16(); + } +#else if ( st->L_frame == L_FRAME16k && ( st->coder_type == VOICED || st->coder_type == UNVOICED ) ) /* VOICED and UNVOICED are not supported in ACELP@16k */ { st->coder_type = GENERIC; @@ -487,6 +932,7 @@ ivas_error pre_proc_ivas( { *Voicing_flag = 0; } +#endif /*-----------------------------------------------------------------* * Compute core-coder buffers at internal sampling rate @@ -500,7 +946,21 @@ ivas_error pre_proc_ivas( if ( !flag_16k_smc ) { - error = ivas_compute_core_buffers( st, &inp_16k, old_inp_16k, new_inp_resamp16k, input_frame, last_element_mode, sr_core_tmp, ener, A, Aw, epsP, lsp_new, lsp_mid ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#endif + error = ivas_compute_core_buffers( st, &inp_16k, old_inp_16k, new_inp_resamp16k, input_frame, last_element_mode, sr_core_tmp, ener, +#ifndef IVAS_FLOAT_FIXED + A, Aw, +#else + A_fx, Aw_fx, +#endif + epsP, +#ifndef IVAS_FLOAT_FIXED + lsp_new, lsp_mid +#else + lsp_new_fx, lsp_mid_fx +#endif + ); if ( error != IVAS_ERR_OK ) { return error; @@ -556,6 +1016,31 @@ ivas_error pre_proc_ivas( } /* Update VAD hangover frame counter in active frames */ +#ifdef IVAS_FLOAT_FIXED + test(); + test(); + IF( !( EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) && st->tcxonly == 0 ) + { + test(); + test(); + test(); + IF( st->hTdCngEnc != NULL && st->Opt_DTX_ON && vad_hover_flag ) + { + st->hTdCngEnc->burst_ho_cnt = add( st->hTdCngEnc->burst_ho_cnt, 1 ); + move16(); + IF( GT_16( st->hTdCngEnc->burst_ho_cnt, HO_HIST_SIZE ) ) + { + st->hTdCngEnc->burst_ho_cnt = HO_HIST_SIZE; + move16(); + } + } + ELSE IF( st->hTdCngEnc != NULL && vad_flag_dtx ) + { + st->hTdCngEnc->burst_ho_cnt = 0; + move16(); + } + } +#else if ( !( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) && st->tcxonly == 0 ) { if ( st->hTdCngEnc != NULL && st->Opt_DTX_ON && vad_hover_flag ) @@ -571,7 +1056,14 @@ ivas_error pre_proc_ivas( st->hTdCngEnc->burst_ho_cnt = 0; } } +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( A_fx, A, Q14 - norm_s( A_fx[0] ), NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( Aw_fx, Aw, Q14 - norm_s( Aw_fx[0] ), NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); +#endif pop_wmops(); return error; @@ -585,38 +1077,113 @@ ivas_error pre_proc_ivas( *--------------------------------------------------------------------*/ ivas_error ivas_compute_core_buffers( - Encoder_State *st, /* i/o: encoder state structure */ - float **inp16k_out, /* o : ptr. to inp. signal in the current frame */ - float *old_inp_16k, /* i/o: buffer of old input signal @ 16kHz */ - float new_inp_resamp16k_out[], /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ - const int16_t input_frame, /* i : frame length */ - const int16_t last_element_mode, /* i : last element mode */ - const int32_t sr_core, /* i : core-coder sampling rate */ - float *ener, /* o : residual energy from Levinson-Durbin */ + Encoder_State *st, /* i/o: encoder state structure */ + float **inp16k_out, /* o : ptr. to inp. signal in the current frame */ + float *old_inp_16k, /* i/o: buffer of old input signal @ 16kHz */ + float new_inp_resamp16k_out[], /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + const int16_t input_frame, /* i : frame length */ + const int16_t last_element_mode, /* i : last element mode */ + const int32_t sr_core, /* i : core-coder sampling rate */ + float *ener, /* o : residual energy from Levinson-Durbin */ +#ifndef IVAS_FLOAT_FIXED float A[NB_SUBFR16k * ( M + 1 )], /* i/o: A(z) unquantized for the 4 subframes */ float Aw[NB_SUBFR16k * ( M + 1 )], /* i/o: weighted A(z) unquantized for subframes */ - float epsP[M + 1], /* i/o: LP prediction errors */ - float lsp_new[M], /* i/o: LSPs at the end of the frame */ - float lsp_mid[M] /* i/o: LSPs in the middle of the frame */ +#else + Word16 A_fx[NB_SUBFR16k * ( M + 1 )], /* i/o: A(z) unquantized for the 4 subframes */ + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )], /* i/o: weighted A(z) unquantized for subframes */ +#endif + float epsP[M + 1], /* i/o: LP prediction errors */ +#ifndef IVAS_FLOAT_FIXED + float lsp_new[M], /* i/o: LSPs at the end of the frame */ + float lsp_mid[M] /* i/o: LSPs in the middle of the frame */ +#else + Word16 lsp_new_fx[M], /* i/o: LSPs at the end of the frame */ + Word16 lsp_mid_fx[M] /* i/o: LSPs in the middle of the frame */ +#endif ) { float *inp_16k, *new_inp_16k; - float tmp, mem_decim16k_dummy[2 * L_FILT_MAX]; - const float *signal_in; +#ifndef IVAS_FLOAT_FIXED + float tmp; + float mem_decim16k_dummy[2 * L_FILT_MAX]; +#endif + /*const*/ float *signal_in; int16_t delay, element_mode; +#ifdef IVAS_FLOAT_FIXED + Word16 temp1F_icatdmResampBuf_fx[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ + Word16 mem_decim16k_dummy_fx[2 * L_FILT_MAX]; + Word32 *signal_in_32fx; + Word16 *signal_in_fx; +#else float temp1F_icatdmResampBuf[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ +#endif float new_inp_resamp16k[L_FRAME16k]; int16_t lMemRecalc, lMemRecalc_16k, L_frame_tmp, L_look; int32_t input_Fs; signal_in = st->input; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 new_inp_resamp16k_fx[L_FRAME16k], tmp_fx; + Word16 Q_tmp, mem_decim16k_size, size_modified; + Word16 old_inp_16k_fx[L_INP]; + // Word16 Q_old_inp_16k = 0; + Word16 Q_old_inp_16k = -1; + Word16 *inp_16k_fx, *new_inp_16k_fx; + Word32 epsP_fx[M + 1]; + Word16 epsP_h[M + 1] = { 0 }; + Word16 epsP_l[M + 1] = { 0 }; + Word16 Q_r[2] = { 0 }; + Word32 ener_fx = 0; + Word16 inp16k_out_buf_fx[2][L_FRAME16k]; + Word16 **inp16k_out_fx = (Word16 **) inp16k_out_buf_fx; + Word16 new_inp_resamp16k_out_fx[L_FRAME16k]; + + signal_in_32fx = st->input32_fx; + signal_in_fx = st->input_fx; + + /* + !!!! ALL BUFFERS CONSIDERED IN Q(-1) for now !!!! + */ + // st->mem_preemph_enc = float_to_fix16( st->mem_preemph_enc_flt, Q_old_inp_16k ); + // st->mem_preemph16k_fx = float_to_fix16( st->mem_preemph16k, Q_old_inp_16k ); + // st->mem_preemph16k_DFT_fx = float_to_fix16( st->mem_preemph16k_DFT, Q_old_inp_16k ); + // st->mem_wsp_enc = float_to_fix16( st->mem_wsp_enc_flt, Q_old_inp_16k ); + + st->mem_preemph_enc = (Word16) floatToFixed( st->mem_preemph_enc_flt, Q_old_inp_16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, Q_old_inp_16k ); + st->mem_preemph16k_DFT_fx = (Word16) floatToFixed( st->mem_preemph16k_DFT, Q_old_inp_16k ); + st->mem_wsp_enc = (Word16) floatToFixed( st->mem_wsp_enc_flt, Q_old_inp_16k ); + + floatToFixed_arrL( signal_in, signal_in_32fx, Q11, 960 ); + + floatToFixed_arr16( old_inp_16k, old_inp_16k_fx, Q_old_inp_16k, L_INP ); + floatToFixed_arr16( signal_in, signal_in_fx, Q_old_inp_16k, 960 ); + floatToFixed_arr16( new_inp_resamp16k, new_inp_resamp16k_fx, Q_old_inp_16k, L_FRAME16k ); + + floatToFixed_arr16( st->old_inp_16k, st->old_inp_16k_fx, Q_old_inp_16k, L_INP_MEM ); + floatToFixed_arr16( st->mem_decim16k, st->mem_decim16k_fx, Q_old_inp_16k, 2 * L_FILT_MAX ); + floatToFixed_arr16( st->inp_16k_mem_stereo_sw, st->inp_16k_mem_stereo_sw_fx, Q_old_inp_16k, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + floatToFixed_arr16( st->buf_speech_enc_flt, st->buf_speech_enc, Q_old_inp_16k, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + floatToFixed_arr16( st->buf_speech_enc_pe_flt, st->buf_speech_enc_pe, Q_old_inp_16k, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); // Should take care of st->speech_enc_pe as wel + floatToFixed_arr16( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, Q_old_inp_16k, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); // Should take care of st->wspeech_enc + // wspeech_enc + + if ( st->hBWE_FD != NULL ) + { + floatToFixed_arr16( st->hBWE_FD->old_wtda_swb, st->hBWE_FD->L_old_wtda_swb_fx, Q_old_inp_16k, L_FRAME48k ); + st->Q_old_wtda = -1; // This reset needs to be looked into + floatToFixed_arr16( st->hBWE_FD->old_input_wb, st->hBWE_FD->old_input_wb_fx, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + } +#endif +#endif input_Fs = st->input_Fs; element_mode = st->element_mode; lMemRecalc_16k = 0; lMemRecalc = 0; - if ( element_mode == IVAS_CPE_TD ) + IF( EQ_16( element_mode, IVAS_CPE_TD ) ) { lMemRecalc_16k = NS2SA( INT_FS_16k, L_MEM_RECALC_NS ); lMemRecalc = NS2SA( input_Fs, L_MEM_RECALC_NS ); @@ -630,15 +1197,26 @@ ivas_error ivas_compute_core_buffers( L_look = NS2SA( sr_core, ACELP_LOOK_NS ); /* lookahead at other sampling rate (16kHz, 25.6kHz, 32kHz) */ + new_inp_16k_fx = old_inp_16k_fx + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS new_inp_16k = old_inp_16k + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ - inp_16k = new_inp_16k - L_look; /* pointer to the current frame of input signal in 16kHz core */ +#endif + inp_16k_fx = new_inp_16k_fx - L_look; /* pointer to the current frame of input signal in 16kHz core */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + inp_16k = new_inp_16k - L_look; /* pointer to the current frame of input signal in 16kHz core */ +#endif /* shift the pointer back to take care of resampler memory update */ - if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_SCE ) + test(); + IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_SCE ) ) { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS new_inp_16k -= NS2SA( sr_core, DELAY_FIR_RESAMPL_NS ); +#endif + new_inp_16k_fx -= NS2SA( sr_core, DELAY_FIR_RESAMPL_NS ); } +#ifndef IVAS_FLOAT_FIXED if ( element_mode == IVAS_CPE_DFT ) { mvr2r( st->old_inp_16k, old_inp_16k, L_INP_MEM - STEREO_DFT_OVL_16k ); @@ -651,11 +1229,26 @@ ivas_error ivas_compute_core_buffers( { mvr2r( st->old_inp_16k, old_inp_16k, L_INP_MEM - L_FILT16k ); } +#else + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + Copy( st->old_inp_16k_fx, old_inp_16k_fx, L_INP_MEM - STEREO_DFT_OVL_16k ); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + Copy( st->old_inp_16k_fx, old_inp_16k_fx, L_INP_MEM - L_MEM_RECALC_16K - L_FILT16k ); + } + ELSE + { + Copy( st->old_inp_16k_fx, old_inp_16k_fx, L_INP_MEM - L_FILT16k ); + } +#endif /*---------------------------------------------------------------* * Change the sampling frequency to 16/25.6/32 kHz *----------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED if ( element_mode == IVAS_SCE ) { if ( input_Fs == sr_core ) @@ -767,13 +1360,15 @@ ivas_error ivas_compute_core_buffers( * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ - if ( - st->tcxonly == 0 && - !( ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) || element_mode == IVAS_CPE_MDCT ) ) + if ( st->tcxonly == 0 && !( ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) || element_mode == IVAS_CPE_MDCT ) ) { st->mem_preemph_enc_flt = new_inp_16k[L_frame_tmp - 1]; } +#ifdef IVAS_FLOAT_FIXED + Word16 exp_new_inp_16k_fx = 0; + move16(); +#endif if ( input_Fs > 8000 && sr_core == INT_FS_16k && element_mode != IVAS_CPE_MDCT ) { if ( element_mode == IVAS_CPE_DFT ) @@ -787,17 +1382,51 @@ ivas_error ivas_compute_core_buffers( { mvr2r( new_inp_16k - STEREO_DFT_OVL_16k, st->buf_speech_enc_flt + L_FRAME16k - STEREO_DFT_OVL_16k, L_FRAME16k + STEREO_DFT_OVL_16k ); } +#ifdef IVAS_FLOAT_FIXED + f2me_buf_16( new_inp_16k - STEREO_DFT_OVL_16k, new_inp_16k_fx - STEREO_DFT_OVL_16k, &exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + fixedToFloat_arr( new_inp_16k_fx - STEREO_DFT_OVL_16k, new_inp_16k - STEREO_DFT_OVL_16k, 15 - exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); +#else preemph( new_inp_16k - STEREO_DFT_OVL_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif + +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + move16(); + f2me_buf_16( new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, &exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, PREEMPH_FAC_16k, STEREO_DFT_OVL_16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); +#else preemph( new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, STEREO_DFT_OVL_16k, &tmp ); +#endif } else if ( st->element_mode == IVAS_CPE_TD ) { if ( last_element_mode == IVAS_CPE_DFT ) { +#ifdef IVAS_FLOAT_FIXED + Word16 exp_inp_16k_mem_stereo_sw = 0; + move16(); + f2me_buf_16( st->inp_16k_mem_stereo_sw, st->inp_16k_mem_stereo_sw_fx, &exp_inp_16k_mem_stereo_sw, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + st->mem_preemph16k_DFT_fx = (Word16) floatToFixed( st->mem_preemph16k_DFT, 15 - exp_inp_16k_mem_stereo_sw ); + + st->mem_preemph16k_fx = st->mem_preemph16k_DFT_fx; + move16(); + Copy( st->inp_16k_mem_stereo_sw_fx, new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + PREEMPH_FX( new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), PREEMPH_FAC_16k, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k, &st->mem_preemph16k_fx ); + + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_inp_16k_mem_stereo_sw ); + fixedToFloat_arr( new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), 15 - exp_inp_16k_mem_stereo_sw, L_MEM_RECALC_16K + STEREO_DFT_OVL_16k + L_MEM_RECALC_16K + L_FILT16k ); +#else st->mem_preemph16k = st->mem_preemph16k_DFT; mvr2r( st->inp_16k_mem_stereo_sw, new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); preemph( new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), PREEMPH_FAC_16k_FLT, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k, &st->mem_preemph16k ); +#endif } st->mem_preemph16k_DFT = old_inp_16k[L_INP_MEM - STEREO_DFT_OVL_16k + L_FRAME16k - 1]; @@ -806,43 +1435,90 @@ ivas_error ivas_compute_core_buffers( if ( last_element_mode == IVAS_CPE_MDCT ) { int16_t length_16k = NS2SA( INT_FS_16k, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + move16(); + f2me_buf_16( new_inp_16k - lMemRecalc_16k - length_16k, new_inp_16k_fx - lMemRecalc_16k - length_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + length_16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k - length_16k, PREEMPH_FAC, length_16k, &st->mem_preemph16k_fx ); + + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k - length_16k, new_inp_16k - lMemRecalc_16k - length_16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + length_16k ); +#else preemph( new_inp_16k - lMemRecalc_16k - length_16k, PREEMPH_FAC_FLT, length_16k, &st->mem_preemph16k ); +#endif } if ( st->L_frame == L_FRAME16k ) { mvr2r( new_inp_16k - lMemRecalc_16k, st->buf_speech_enc_flt + L_FRAME16k - lMemRecalc_16k - L_FILT16k, L_FRAME16k + lMemRecalc_16k + L_FILT16k ); } +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k - lMemRecalc_16k, new_inp_16k_fx - lMemRecalc_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k, new_inp_16k - lMemRecalc_16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); +#else preemph( new_inp_16k - lMemRecalc_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k - lMemRecalc_16k, new_inp_16k_fx - lMemRecalc_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k + L_FRAME16k, PREEMPH_FAC_16k, lMemRecalc_16k + L_FILT16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k + L_FRAME16k, new_inp_16k - lMemRecalc_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); +#else preemph( new_inp_16k - lMemRecalc_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, lMemRecalc_16k + L_FILT16k, &tmp ); +#endif } else if ( element_mode == IVAS_SCE ) { +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k, new_inp_16k_fx, &exp_new_inp_16k_fx, L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx, new_inp_16k, 15 - exp_new_inp_16k_fx, L_FRAME16k ); +#else preemph( new_inp_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif + +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k + L_FRAME16k, new_inp_16k_fx + L_FRAME16k, &exp_new_inp_16k_fx, L_FRAME16k + L_FILT16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx + L_FRAME16k, PREEMPH_FAC_16k, L_FILT16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx + L_FRAME16k, new_inp_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, L_FRAME16k + L_FILT16k ); +#else preemph( new_inp_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, L_FILT16k, &tmp ); +#endif } - } - else if ( input_Fs > 8000 ) /* keep memory up-to-date in case of bitrate switching */ - { - if ( element_mode == IVAS_CPE_DFT ) - { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - STEREO_DFT_OVL_16k - 1]; - } - else if ( element_mode == IVAS_CPE_TD ) - { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - lMemRecalc_16k - 1]; - } - else if ( element_mode == IVAS_CPE_MDCT ) - { - st->mem_preemph16k = 0; - } - else /* SCE */ + else if ( input_Fs > 8000 ) /* keep memory up-to-date in case of bitrate switching */ { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - 1]; + if ( element_mode == IVAS_CPE_DFT ) + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - STEREO_DFT_OVL_16k - 1]; + } + else if ( element_mode == IVAS_CPE_TD ) + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - lMemRecalc_16k - 1]; + } + else if ( element_mode == IVAS_CPE_MDCT ) + { + st->mem_preemph16k = 0; + } + else /* SCE */ + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - 1]; + } + st->mem_preemph16k_DFT = st->mem_preemph16k; } - st->mem_preemph16k_DFT = st->mem_preemph16k; } /*-----------------------------------------------------------------* @@ -878,7 +1554,6 @@ ivas_error ivas_compute_core_buffers( } analy_lp( inp_16k, L_FRAME16k, L_look, ener, A, epsP, lsp_new, lsp_mid, st->lspold_enc, st->pitch, st->voicing, INT_FS_16k, 0 ); - /*--------------------------------------------------------------* * Compute Weighted Input *---------------------------------------------------------------*/ @@ -913,6 +1588,347 @@ ivas_error ivas_compute_core_buffers( { mvr2r( new_inp_resamp16k, new_inp_resamp16k_out, L_FRAME16k ); } +#else + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + test(); + IF( EQ_32( input_Fs, sr_core ) ) + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ); + Copy( st->mem_decim16k_fx + delay, new_inp_16k_fx, delay ); + Copy( signal_in_fx, new_inp_16k_fx + delay, input_frame ); + Copy( signal_in_fx + input_frame - shl( delay, 1 ), st->mem_decim16k_fx, shl( delay, 1 ) ); + } + ELSE IF( EQ_32( input_Fs, 32000 ) || EQ_32( input_Fs, 48000 ) ) + { + size_modified = modify_Fs_ivas_fx( signal_in_fx, input_frame, input_Fs, new_inp_16k_fx, sr_core, st->mem_decim16k_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx, size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + + Copy( st->mem_decim16k_fx, mem_decim16k_dummy_fx, 2 * L_FILT_MAX ); + set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); + size_modified = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ), sr_core, mem_decim16k_dummy_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ), size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + } + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + test(); + IF( EQ_32( input_Fs, sr_core ) ) + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ); + Copy( st->mem_decim16k_fx + delay, new_inp_16k_fx - sub( lMemRecalc, add( delay, L_FILT16k ) ), delay ); + Copy( signal_in_fx - lMemRecalc, new_inp_16k_fx - add( lMemRecalc, L_FILT16k ), add( input_frame, lMemRecalc ) ); + Copy( signal_in_fx + sub( sub( input_frame, lMemRecalc ), shl( delay, 1 ) ), st->mem_decim16k_fx, shl( delay, 1 ) ); + } + ELSE IF( EQ_32( input_Fs, 32000 ) || EQ_32( input_Fs, 48000 ) ) + { + /* reconstruct past segment of input signal when switching from MDCT stereo */ + IF( EQ_16( last_element_mode, IVAS_CPE_MDCT ) /*|| st->idchan == 1*/ ) + { + Word16 length_inp = NS2SA_FX2( input_Fs, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); + Word16 length_16k = NS2SA_FX2( INT_FS_16k, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); + + Copy( signal_in_fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim16k_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + size_modified = modify_Fs_ivas_fx( signal_in_fx - lMemRecalc - length_inp, length_inp, input_Fs, new_inp_16k_fx - lMemRecalc_16k - length_16k, sr_core, st->mem_decim16k_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx - lMemRecalc_16k - length_16k, size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + } + + size_modified = modify_Fs_ivas_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_16k_fx - ( lMemRecalc * sr_core ) / st->input_Fs, sr_core, st->mem_decim16k_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx - ( lMemRecalc * sr_core ) / st->input_Fs, size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + Copy( st->mem_decim16k_fx, mem_decim16k_dummy_fx, 2 * L_FILT_MAX ); + + IF( lMemRecalc > 0 ) + { + size_modified = modify_Fs_ivas_fx( signal_in_fx - lMemRecalc + input_frame, lMemRecalc, input_Fs, new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ) - ( lMemRecalc * sr_core ) / st->input_Fs, sr_core, mem_decim16k_dummy_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ) - ( lMemRecalc * sr_core ) / st->input_Fs, size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + } + + set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); + size_modified = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ), sr_core, mem_decim16k_dummy_fx, 0, &Q_tmp, &mem_decim16k_size ); + Scale_sig( new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ), size_modified, negate( Q_tmp ) ); /* scaling back to Q_old_inp_16k */ + } + } + ELSE IF( st->idchan == 0 ) + { + /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ + Copy( signal_in_fx + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim16k_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + } + + /*------------------------------------------------* + * Update BWE memories * + *------------------------------------------------*/ + + test(); + IF( EQ_32( sr_core, INT_FS_16k ) && NE_16( element_mode, IVAS_CPE_MDCT ) ) + { + delay = NS2SA( INT_FS_16k, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + /* save input resampled at 16kHz, non-preemphasised.*/ + Copy( new_inp_16k_fx, new_inp_resamp16k_fx, L_FRAME16k ); + + IF( EQ_16( st->bwidth, WB ) ) + { + Copy_Scale_sig( new_inp_16k_fx - delay, st->hBWE_FD->old_input_wb_fx, delay, -( Q_old_inp_16k + 1 ) ); /* Scaling to Q(-1) */ + Copy( new_inp_16k_fx - STEREO_DFT_OVL_16k, st->hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - STEREO_DFT_OVL_16k + delay, STEREO_DFT_OVL_16k - delay ); /* Check Q here once. Q should be Q_old_wtda */ + } + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + /* save input resampled at 16kHz, non-preemphasised */ + Copy( new_inp_16k_fx + L_FILT16k, new_inp_resamp16k_fx, L_FRAME16k ); + + test(); + IF( EQ_16( st->bwidth, WB ) && st->hBWE_FD != NULL ) + { + Copy_Scale_sig( new_inp_16k_fx + L_FILT16k - delay, st->hBWE_FD->old_input_wb_fx, delay, -( Q_old_inp_16k + 1 ) ); /* Scaling to Q(-1) */ + Copy( new_inp_16k_fx - L_MEM_RECALC_16K, st->hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - L_MEM_RECALC_16K - L_FILT16k + delay, L_MEM_RECALC_16K + L_FILT16k - delay ); /* Check Q here once. Q should be Q_old_wtda */ + } + } + ELSE IF( element_mode == IVAS_SCE ) + { + /* save input resampled at 16kHz, non-preemphasised */ + Copy( new_inp_16k_fx + L_FILT16k, new_inp_resamp16k_fx, L_FRAME16k ); + + IF( EQ_16( st->bwidth, WB ) ) + { + Copy_Scale_sig( new_inp_16k_fx, st->hBWE_FD->old_input_wb_fx + delay - L_FILT16k, L_FILT16k, -( Q_old_inp_16k + 1 ) ); /* Scaling to Q(-1) */ + /* all buffer st->hBWE_FD->old_wtda_swb is correct and does not need to be updated */ + } + } + } + ELSE IF( GT_32( sr_core, INT_FS_16k ) ) + { + /* reset the buffer, the signal is needed for WB BWEs */ + set16_fx( new_inp_resamp16k_fx, 0, L_FRAME16k ); + } + + /*------------------------------------------------------------------* + * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + if ( st->tcxonly == 0 && !( ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 1 ) ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) ) + { + st->mem_preemph_enc = new_inp_16k_fx[L_frame_tmp - 1]; + move16(); + } + + test(); + test(); + IF( GT_32( input_Fs, 8000 ) && EQ_32( sr_core, INT_FS_16k ) && NE_16( element_mode, IVAS_CPE_MDCT ) ) + { + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + Copy( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, st->inp_16k_mem_stereo_sw_fx, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); /* update for TD/DFT stereo switching */ + + st->mem_preemph16k_fx = st->mem_preemph16k_DFT_fx; + move16(); + st->mem_preemph16k_DFT_fx = old_inp_16k_fx[L_INP_MEM - STEREO_DFT_OVL_16k + L_FRAME16k - 1]; + move16(); + + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + Copy( new_inp_16k_fx - STEREO_DFT_OVL_16k, st->buf_speech_enc + L_FRAME16k - STEREO_DFT_OVL_16k, L_FRAME16k + STEREO_DFT_OVL_16k ); + } + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + tmp_fx = st->mem_preemph16k_fx; + move16(); + + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, PREEMPH_FAC_16k, STEREO_DFT_OVL_16k, &tmp_fx ); + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + IF( EQ_16( last_element_mode, IVAS_CPE_DFT ) ) + { + st->mem_preemph16k_fx = st->mem_preemph16k_DFT_fx; + move16(); + Copy( st->inp_16k_mem_stereo_sw_fx, new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + PREEMPH_FX( new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), PREEMPH_FAC_16k, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k, &st->mem_preemph16k_fx ); + } + + st->mem_preemph16k_DFT_fx = old_inp_16k_fx[L_INP_MEM - STEREO_DFT_OVL_16k + L_FRAME16k - 1]; + move16(); + + /* preemphasise past segment of input signal when switching from MDCT stereo */ + IF( EQ_16( last_element_mode, IVAS_CPE_MDCT ) ) + { + Word16 length_16k = NS2SA( INT_FS_16k, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); + + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k - length_16k, PREEMPH_FAC, length_16k, &st->mem_preemph16k_fx ); + } + + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + Copy( new_inp_16k_fx - lMemRecalc_16k, st->buf_speech_enc + L_FRAME16k - lMemRecalc_16k - L_FILT16k, L_FRAME16k + lMemRecalc_16k + L_FILT16k ); + } + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + tmp_fx = st->mem_preemph16k_fx; + move16(); + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k + L_FRAME16k, PREEMPH_FAC_16k, lMemRecalc_16k + L_FILT16k, &tmp_fx ); + } + ELSE IF( EQ_16( element_mode, IVAS_SCE ) ) + { + PREEMPH_FX( new_inp_16k_fx, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + tmp_fx = st->mem_preemph16k_fx; + move16(); + PREEMPH_FX( new_inp_16k_fx + L_FRAME16k, PREEMPH_FAC_16k, L_FILT16k, &tmp_fx ); + } + ELSE IF( GT_32( input_Fs, 8000 ) ) /* keep memory up-to-date in case of bitrate switching */ + { + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + st->mem_preemph16k_fx = new_inp_16k_fx[L_frame_tmp - STEREO_DFT_OVL_16k - 1]; + move16(); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + st->mem_preemph16k_fx = new_inp_16k_fx[L_frame_tmp - lMemRecalc_16k - 1]; + move16(); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) + { + st->mem_preemph16k_fx = 0; + move16(); + } + ELSE /* SCE */ + { + st->mem_preemph16k_fx = new_inp_16k_fx[L_frame_tmp - 1]; + move16(); + } + st->mem_preemph16k_DFT_fx = st->mem_preemph16k_fx; + move16(); + } + } + + /*-----------------------------------------------------------------* + * LP analysis at 16kHz if ACELP@16k core was selected + * update buffers + *-----------------------------------------------------------------*/ + + test(); + IF( EQ_16( st->L_frame, L_FRAME16k ) && NE_16( element_mode, IVAS_CPE_MDCT ) ) + { + /* update signal buffers */ + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + Copy( new_inp_16k_fx - STEREO_DFT_OVL_16k, st->buf_speech_enc_pe + L_FRAME16k - STEREO_DFT_OVL_16k, L_FRAME16k + STEREO_DFT_OVL_16k ); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + Copy( new_inp_16k_fx - lMemRecalc_16k, st->buf_speech_enc_pe + L_FRAME16k - lMemRecalc_16k - L_FILT16k, L_FRAME16k + lMemRecalc_16k + L_FILT16k ); + } + ELSE + { + Copy( new_inp_resamp16k_fx, st->buf_speech_enc + L_FRAME16k, L_FRAME16k ); + Copy( new_inp_16k_fx, st->buf_speech_enc_pe + L_FRAME16k, L_FRAME16k ); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + IF( EQ_16( st->last_L_frame, L_FRAME ) ) + { + /* this is just an approximation, but it is sufficient */ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + + analy_lp_fx( inp_16k_fx, L_FRAME16k, L_look, &ener_fx, A_fx, epsP_h, epsP_l, lsp_new_fx, lsp_mid_fx, st->lspold_enc_fx, st->pitch, st->voicing_fx, INT_FS_16k, 0, Q_old_inp_16k, Q_r ); + + /*--------------------------------------------------------------* + * Compute Weighted Input + *---------------------------------------------------------------*/ + + ivas_find_wsp( L_FRAME16k, L_SUBFR, NB_SUBFR16k, A_fx, Aw_fx, st->speech_enc_pe, PREEMPH_FAC_16k, st->wspeech_enc, &st->mem_wsp_enc, st->gamma, L_LOOK_16k ); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update old input signal @16kHz buffer */ + test(); + test(); + test(); + IF( ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 1 ) ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) + { + set16_fx( st->old_inp_16k_fx, 0, L_INP_MEM ); + } + ELSE IF( GT_32( input_Fs, 8000 ) && EQ_32( sr_core, INT_FS_16k ) ) + { + Copy( &old_inp_16k_fx[L_frame_tmp], st->old_inp_16k_fx, L_INP_MEM ); + } + ELSE IF( GT_32( input_Fs, 8000 ) ) + { + lerp( st->old_inp_12k8_fx + L_INP_MEM - L_INP_MEM * 4 / 5, st->old_inp_16k_fx, L_INP_MEM, L_INP_MEM * 4 / 5 ); + } + + IF( inp16k_out != NULL ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + *inp16k_out = inp_16k; +#endif + *inp16k_out_fx = inp_16k_fx; + } + + IF( new_inp_resamp16k_out != NULL ) + { + Copy( new_inp_resamp16k_fx, new_inp_resamp16k_out_fx, L_FRAME16k ); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // No need to do fixed to float for signal_in_fx + st->mem_preemph_enc_flt = fixedToFloat_16( st->mem_preemph_enc, Q_old_inp_16k ); + st->mem_preemph16k = fixedToFloat_16( st->mem_preemph16k_fx, Q_old_inp_16k ); + st->mem_preemph16k_DFT = fixedToFloat_16( st->mem_preemph16k_DFT_fx, Q_old_inp_16k ); + st->mem_wsp_enc_flt = fixedToFloat_16( st->mem_wsp_enc, Q_old_inp_16k ); + + if ( st->L_frame == L_FRAME16k && element_mode != IVAS_CPE_MDCT ) + { + *ener = fixedToFloat( ener_fx, Q_r[0] + 1 ); + } + + fixedToFloat_arr( old_inp_16k_fx, old_inp_16k, Q_old_inp_16k, L_INP ); + fixedToFloat_arr( signal_in_fx, signal_in, Q_old_inp_16k, 960 ); + fixedToFloat_arr( new_inp_resamp16k_fx, new_inp_resamp16k, Q_old_inp_16k, L_FRAME16k ); + + if ( new_inp_resamp16k_out != NULL ) + { + fixedToFloat_arr( new_inp_resamp16k_out_fx, new_inp_resamp16k_out, Q_old_inp_16k, L_FRAME16k ); + } + + fixedToFloat_arr( st->old_inp_16k_fx, st->old_inp_16k, Q_old_inp_16k, L_INP_MEM ); + fixedToFloat_arr( st->mem_decim16k_fx, st->mem_decim16k, Q_old_inp_16k, 2 * L_FILT_MAX ); + fixedToFloat_arr( st->inp_16k_mem_stereo_sw_fx, st->inp_16k_mem_stereo_sw, Q_old_inp_16k, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + fixedToFloat_arr( st->buf_speech_enc, st->buf_speech_enc_flt, Q_old_inp_16k, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + fixedToFloat_arr( st->buf_speech_enc_pe, st->buf_speech_enc_pe_flt, Q_old_inp_16k, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); // Should take care of st->speech_enc_pe as wel + fixedToFloat_arr( st->buf_wspeech_enc, st->buf_wspeech_enc_flt, Q_old_inp_16k, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); // Should take care of st->wspeech_enc + + if ( st->hBWE_FD != NULL ) + { + fixedToFloat_arr( st->hBWE_FD->L_old_wtda_swb_fx, st->hBWE_FD->old_wtda_swb, st->Q_old_wtda, L_FRAME48k ); + fixedToFloat_arr( st->hBWE_FD->old_input_wb_fx, st->hBWE_FD->old_input_wb, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + } + + if ( st->L_frame == L_FRAME16k && element_mode != IVAS_CPE_MDCT ) + { + for ( Word16 i = 0; i < M + 1; i++ ) + { + epsP_fx[i] = L_Comp( epsP_h[i], epsP_l[i] ); + move32(); + } + + fixedToFloat_arrL( epsP_fx, epsP, Q_r[0] + 1, M + 1 ); + } +#endif +#endif return IVAS_ERR_OK; } diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index a8761182af62b8041440c58a4aaac09cff9babae..f80542a568d6d065157352882aeda80cbae5394a 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -40,11 +40,14 @@ #include "prot_fx.h" #include "prot_fx_enc.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "wmc_auto.h" #include #ifdef IVAS_FLOAT_FIXED #include "prot_fx_enc.h" +#include "ivas_prot_fx.h" +#include "prot_fx.h" #endif /*---------------------------------------------------------------* @@ -54,20 +57,12 @@ #define SCE_SMC_THR 16000 -/*-------------------------------------------------------------------* - * Local function prototypes - *--------------------------------------------------------------------*/ -#if 0 -static void change_q( Word16 *buff, Word16 size, Word16 Q ) -{ - Flag Overflow; - for ( Word16 i = 0; i < size; i++ ) - { - buff[i] = shr_o( buff[i], Q, &Overflow ); - } -} -#endif +#ifdef IVAS_FLOAT_FIXED +static void calculate_energy_buffer_ivas_fx( CPE_ENC_HANDLE hCPE, Word32 enerBuffer_dft[], const Word16 no_channels, const Word32 input_Fs, Word16 *enerBuffer_dft_e ); +#else static void calculate_energy_buffer( CPE_ENC_HANDLE hCPE, float enerBuffer_dft[], const int16_t no_channels, const int32_t input_Fs ); +#endif + #ifdef IVAS_FIXED_ENC static void calculate_energy_buffer_fx( CPE_ENC_HANDLE hCPE, Word64 enerBuffer_dft_fx[], Word16 *enerBuffer_dft_q_fx, const Word16 no_channels, const Word32 input_Fs ); #endif @@ -855,10 +850,11 @@ ivas_error pre_proc_front_ivas( ivas_error pre_proc_front_ivas_fx( SCE_ENC_HANDLE hSCE, /* i/o: SCE encoder structure */ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const int32_t element_brate, /* i : SCE/CPE element bitrate */ - const int16_t nb_bits_metadata, /* i : number of metadata bits */ - const int16_t input_frame, /* i : frame length */ - const int16_t n, /* i : channel number */ + const Word32 element_brate, /* i : SCE/CPE element bitrate */ + const Word16 nb_bits_metadata, /* i : number of metadata bits */ + const Word16 input_frame, /* i : frame length */ + const Word16 n, /* i : channel number */ + Word16 old_inp_12k8_fx[], /* o : (Q-1) buffer of old input signal */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ float *ener, /* o : residual energy from Levinson-Durbin */ @@ -868,266 +864,383 @@ ivas_error pre_proc_front_ivas_fx( float epsP[M + 1], /* o : LP prediction errors */ float lsp_new[M], /* o : LSPs at the end of the frame */ float lsp_mid[M], /* o : LSPs in the middle of the frame */ - int16_t *vad_hover_flag, /* o : VAD hangover flag */ - int16_t *attack_flag, /* o : flag signaling attack */ + Word16 *vad_hover_flag, /* o : VAD hangover flag */ + Word16 *attack_flag, /* o : flag signaling attack */ float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: real buffer */ float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: imag buffer */ float old_wsp[], /* o : weighted input signal buffer */ float pitch_fr[NB_SUBFR], /* o : fractional pitch values */ float voicing_fr[NB_SUBFR], /* o : fractional pitch gains */ - int16_t *loc_harm, /* o : harmonicity flag */ + Word16 *loc_harm, /* o : harmonicity flag */ float *cor_map_sum, /* o : speech/music clasif. parameter */ - int16_t *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ + Word16 *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* o : energy buffer */ float fft_buff[2 * L_FFT], /* o : FFT buffer */ + Word16 fft_buff_fx[2 * L_FFT], /* o : FFT buffer */ const float tdm_A_PCh[M + 1], /* i : unq. LP coeff. of primary channel */ const float tdm_lsp_new_PCh[M], /* i : unq. LSPs of primary channel */ const float currFlatness, /* i : flatness parameter */ - const int16_t tdm_ratio_idx, /* i : Current Ratio_L index */ + const Word16 tdm_ratio_idx, /* i : Current Ratio_L index */ float fr_bands_LR[][2 * NB_BANDS], /* i : energy in frequency bands */ const float Etot_LR[], /* i : total energy Left & Right channel Q8*/ float lf_E_LR[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels */ - const int16_t localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover, LR channels */ + const Word16 localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover, LR channels */ float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN */ - const int16_t flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ - const int16_t front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ - const int16_t force_front_vad, /* i : flag to force VAD decision */ - const int16_t front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ + const Word16 flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ + const Word16 front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ + const Word16 force_front_vad, /* i : flag to force VAD decision */ + const Word16 front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ - const int32_t ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const Word32 ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ ) { - float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ - float *wsp; /* weighted input signal buffer */ - float Etot; /* total energy */ - float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ - float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ - float tmpN[NB_BANDS]; /* Temporary noise update */ - float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ - float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ - float non_staX_LR; /* non-stationarity for sp/mus classifier */ - float ncharX_LR; /* noise character for sp/mus classifier */ - float sp_div_LR; /* spectral diversity feature */ - float S_map_LR[L_FFT / 2]; /* short-term correlation map */ - float corr_shiftL; /* correlation shift */ - float corr_shiftR; /* correlation shift */ - int16_t loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ - int16_t lr_vad_enabled; /* LR VAD indicator */ - float ee[2]; /* Spectral tilt */ - float corr_shift; /* correlation shift */ - float sp_div, PS[128]; /* speech/music clasif. parameters */ - int16_t L_look; /* length of look-ahead */ -#if 1 - float snr_sum_he; /* HE SAD parameters */ -#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Encoder_State *st; + Word16 old_inp_12k8_e; + if ( hSCE != NULL ) + { + st = hSCE->hCoreCoder[n]; + floatToFixed_arr( hSCE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hSCE->hCoreCoder[n]->input_fx - (Word16) ( st->input_Fs / 50 ), -1, (Word16) ( st->input_Fs / 25 ) ); + floatToFixed_arrL( hSCE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hSCE->hCoreCoder[n]->input32_fx - (Word16) ( st->input_Fs / 50 ), 11, (Word16) ( st->input_Fs / 25 ) ); + } + else + { + st = hCPE->hCoreCoder[n]; + floatToFixed_arr( hCPE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hCPE->hCoreCoder[n]->input_fx - (Word16) ( st->input_Fs / 50 ), -1, (Word16) ( st->input_Fs / 25 ) ); + floatToFixed_arrL( hCPE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hCPE->hCoreCoder[n]->input32_fx - (Word16) ( st->input_Fs / 50 ), 11, (Word16) ( st->input_Fs / 25 ) ); + } + Word16 mem_decim_e; + f2me_buf_16( st->mem_decim, st->mem_decim_fx, &mem_decim_e, 2 * L_FILT_MAX ); + IF( st->cldfbAnaEnc != NULL ) + { + floatToFixed_arrL( st->cldfbAnaEnc->cldfb_state, st->cldfbAnaEnc->cldfb_state_fx, Q11, sub( sub( st->cldfbAnaEnc->p_filter_length, st->cldfbAnaEnc->no_channels ), st->cldfbAnaEnc->zeros ) ); + } + f2me_buf_16( st->old_inp_12k8, st->old_inp_12k8_fx, &st->exp_old_inp_12k8, 240 ); + f2me_buf_16( old_inp_12k8, old_inp_12k8_fx, &old_inp_12k8_e, 496 ); + if ( old_inp_12k8_e > st->exp_old_inp_12k8 ) + { + Scale_sig( st->old_inp_12k8_fx, 240, st->exp_old_inp_12k8 - old_inp_12k8_e ); + st->exp_old_inp_12k8 = old_inp_12k8_e; + } + else + { + Scale_sig( old_inp_12k8_fx, 496, old_inp_12k8_e - st->exp_old_inp_12k8 ); + old_inp_12k8_e = st->exp_old_inp_12k8; + } + Word16 mem_preemph_DFT_e; + Word16 inp_12k8_mem_stereo_sw_e; + Word16 mem_preemph_e; + f2me_buf_16( st->inp_12k8_mem_stereo_sw, st->inp_12k8_mem_stereo_sw_fx, &inp_12k8_mem_stereo_sw_e, 4 ); + f2me_16( st->mem_preemph_DFT, &st->mem_preemph_DFT_fx, &mem_preemph_DFT_e ); + f2me_16( st->mem_preemph, &st->mem_preemph_fx, &mem_preemph_e ); + Word16 relE_fx; + Word16 old_wsp_fx[L_WSP]; + Word16 pitch_fr_fx[NB_SUBFR]; + Word16 voicing_fr_fx[NB_SUBFR]; + Word16 A_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 epsP_h[M + 1]; /* o : LP prediction errors */ + Word16 epsP_l[M + 1]; /* o : LP prediction errors */ + Word16 cor_map_sum16_fx; /* o : speech/music clasif. parameter */ + Word32 fr_bands_LR_fx[2][2 * NB_BANDS]; +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ + float *wsp; /* weighted input signal buffer */ + float Etot; /* total energy */ + float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ + float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + float tmpN[NB_BANDS]; /* Temporary noise update */ + float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ + float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ + // float non_staX_LR; /* non-stationarity for sp/mus classifier */ + // float ncharX_LR; /* noise character for sp/mus classifier */ + // float sp_div_LR; /* spectral diversity feature */ + float S_map_LR[L_FFT / 2]; /* short-term correlation map */ + float corr_shiftL; /* correlation shift */ + float corr_shiftR; /* correlation shift */ + // Word16 loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ + Word16 lr_vad_enabled; /* LR VAD indicator */ + float ee[2]; /* Spectral tilt */ + float corr_shift; /* correlation shift */ + float sp_div, PS[128]; /* speech/music clasif. parameters */ + Word16 L_look; /* length of look-ahead */ +#if 0 float mem_decim_dummy[2 * L_FILT_MAX]; /* dummy decimation filter memory */ float temp1F_icatdmResampBuf[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ - float hp_E[2]; /* Energy in HF */ - int16_t flag_spitch; - int16_t high_lpn_flag; +#endif + float hp_E[2]; /* Energy in HF */ + Word16 flag_spitch; + Word16 high_lpn_flag; float lsf_new[M]; + Word32 lsf_new_fx[M]; float band_energies[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ - int16_t localVAD_HE_SAD; +#if 0 + Word32 band_energies_fx[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ +#endif + Word16 localVAD_HE_SAD; float non_staX; + Word16 currFlatness_fx; + Word32 non_staX_fx; float stab_fac; - int16_t alw_pitch_lag_12k8[2]; - float alw_voicing[2]; - int16_t last_core_orig; - float dummy; + Word16 alw_pitch_lag_12k8[2]; + Word16 alw_voicing_fx[2]; + Word16 last_core_orig; + // float dummy; float S_map[L_FFT / 2]; - int16_t i, lMemRecalc, lMemRecalc_12k8; - int16_t smc_dec; - float ncharX, dE1X; - Encoder_State *st; - float *signal_in; - int16_t element_mode; - int32_t input_Fs, last_element_brate; - int16_t *tdm_SM_last_clas, tmpS; + // Word16 S_map_fx[L_FFT / 2]; + Word16 i, lMemRecalc, lMemRecalc_12k8; + Word16 smc_dec; + // float dE1X; + // float ncharX; + // Encoder_State *st; + // float *signal_in; + Word16 element_mode; + Word32 input_Fs, last_element_brate; + Word16 *tdm_SM_last_clas, tmpS; float *res_cod_SNR_M, tmpF[STEREO_DFT_BAND_MAX]; STEREO_CLASSIF_HANDLE hStereoClassif; - int16_t old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ - int16_t LR_localVAD; + Word16 old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ + Word16 LR_localVAD; ivas_error error; + Word32 epsP_fx[17]; /*to be removed later*/ + Word32 cor_map_sum_fx; push_wmops( "pre_proc_front" ); -#ifdef IVAS_FLOAT_FIXED Word16 *signal_in_fx; - Word16 *new_inp_12k8_fx; /* pointers to current frame and new data */ +#if 0 + Word16 *lgBin_E_fx; + Word32 PS_fx[128]; + Word32 lf_E_fx[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ +#endif + Word32 *signal32_in_fx; +#if 0 + Word16 *inp_12k8_fx; +#endif + Word16 *inp_12k8_fx, *new_inp_12k8_fx; /* pointers to current frame and new data */ CLDFB_SCALE_FACTOR cldfbScale; Word32 *enerBuffer_fx; Word16 enerBuffer_exp; /*[CLDFB_NO_CHANNELS_MAX];*/ Word16 *temp1F_icatdmResampBuf_fx; - Word16 *old_inp_12k8_fx; Word16 *old_inp_16k_fx; Word16 *mem_decim_dummy_fx; /* dummy decimation filter memory */ - Word32 Etot_fx; /* total energy */ -#if 0 - Word32 fr_bands_fx[2 * NB_BANDS]; /* energy in frequency bands */ - Word16 Q_new; - Word16 new_inp_out_size, mem_decim_size; - Word16 snr_sum_he_fx; /* HE SAD parameters */ +#if 1 + Word16 Etot_16fx; /* total energy, Q8 */ +#endif + Word32 tmpF_fx[STEREO_DFT_BAND_MAX]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + Word32 *res_cod_SNR_M_fx; +#endif + Word16 snr_sum_he_fx; /* HE SAD parameters */ + Word16 new_inp_out_size; Word16 Q_new_inp; + Word16 mem_decim_size; + // Word16 *wsp_fx; + // Word16 pitch_fr_fx[NB_SUBFR]; + // Word16 voicing_fr_fx[NB_SUBFR]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + Word16 Q_new; Word16 corr_shift_fx; - Word16 dummy_fx; - Word16 Etot_LR_fx[2]; +#endif +#if 0 Word16 Q_exp; Word32 Le_min_scaled; - Word32 fr_bands_LR_fx[2][2 * NB_BANDS]; Word16 relE_fx; +#endif + + Word16 dummy_fx; + Word16 ncharX_fx; + Word16 ncharX_LR_fx; /* noise character for sp/mus classifier */ + Word16 loc_harmLR_fx[CPE_CHANNELS]; /* harmonicity flag */ + Word16 non_staX16_fx; + Word16 non_staX_LR_fx; /* non-stationarity for sp/mus classifier */ + Word32 sp_div_fx; + Word16 sp_div16_fx; + Word16 q_sp_div; + Word16 sp_div_LR_fx; + Word16 q_sp_div_LR; + Word16 *wsp_fx; + Word32 dE1X_fx; + Word16 Etot_LR_fx[2]; + Word16 S_map_fx[L_FFT / 2]; + Word16 cor_map_sum_LR_fx[CPE_CHANNELS]; /* speech/music clasif. parameter */ + Word16 S_map_LR_fx[L_FFT / 2]; /* short-term correlation map */ + Word32 Etot_fx; /* total energy */ Word32 tmpN_fx[NB_BANDS]; /* Temporary noise update */ Word32 tmpE_fx[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ Word32 tmpN_LR_fx[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ Word32 tmpE_LR_fx[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ -#endif - - signal_in_fx = (Word16 *) malloc( 2 * 1965 * sizeof( Word16 * ) ); + Word16 corr_shiftL_fx; /* correlation shift */ + Word16 corr_shiftR_fx; /* correlation shift */ + Word16 corr_shift_fx; /* correlation shift */ + Word32 ee_fx[2]; /* Spectral tilt */ + Word32 fr_bands_fx[2 * NB_BANDS]; /* energy in frequency bands */ + Word32 lf_E_fx[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + Word32 lf_E_LR_fx[2][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + Word32 hp_E_fx[2]; /* Energy in HF */ + + enerBuffer_exp = 0; + move16(); enerBuffer_fx = (Word32 *) malloc( 60 * sizeof( Word32 * ) ); - old_inp_12k8_fx = (Word16 *) malloc( 496 * sizeof( Word16 * ) ); old_inp_16k_fx = (Word16 *) malloc( 880 * sizeof( Word16 * ) ); mem_decim_dummy_fx = (Word16 *) malloc( 90 * sizeof( Word16 * ) ); temp1F_icatdmResampBuf_fx = (Word16 *) malloc( 45 * sizeof( Word16 * ) ); - + set16_fx( fft_buff_fx, 0, 512 ); Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 realBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 imagBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word16 sf_energySum[CLDFB_NO_CHANNELS_MAX]; + Word16 max_e; -#ifndef MSAN_FIX - floatToFixed_arr( old_inp_12k8, old_inp_12k8_fx, 0, 496 ); -#endif // MSAN_FIX -#endif /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ error = IVAS_ERR_OK; + move32(); + + cldfbScale.lb_scale = 31; + cldfbScale.hb_scale = 31; + move16(); + move16(); tmpS = 0; + move16(); tdm_SM_last_clas = &tmpS; + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED set_f( tmpF, 0, STEREO_DFT_BAND_MAX ); res_cod_SNR_M = tmpF; +#endif // IVAS_FLOAT - LR_localVAD = 0; - - if ( hSCE != NULL ) - { - st = hSCE->hCoreCoder[n]; - signal_in = hSCE->hCoreCoder[n]->input; - element_mode = IVAS_SCE; - last_element_brate = hSCE->last_element_brate; - hStereoClassif = NULL; - lr_vad_enabled = 0; - } - else /* CPE */ - { - st = hCPE->hCoreCoder[n]; - signal_in = hCPE->hCoreCoder[n]->input; - element_mode = hCPE->element_mode; - last_element_brate = hCPE->last_element_brate; - hStereoClassif = hCPE->hStereoClassif; - lr_vad_enabled = 0; - if ( hCPE->hFrontVad[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) - { - lr_vad_enabled = 1; - } - - if ( lr_vad_enabled && n == 0 ) - { - /* Combine localVAD and vad_flag from LR processing */ - LR_localVAD = hCPE->hCoreCoder[0]->localVAD || hCPE->hCoreCoder[1]->localVAD; - } - - if ( hCPE->hStereoTD != NULL ) - { - tdm_SM_last_clas = &hCPE->hStereoTD->tdm_SM_last_clas[n]; - mvs2s( hCPE->hStereoTD->tdm_SM_last_clas, hCPE->hStereoTD->tdm_SM_last2_clas, CPE_CHANNELS ); - } - - if ( hCPE->hStereoDft != NULL ) - { - res_cod_SNR_M = hCPE->hStereoDft->res_cod_SNR_M; - } - } -#if 0 set32_fx( tmpF_fx, 0, STEREO_DFT_BAND_MAX ); +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING res_cod_SNR_M_fx = tmpF_fx; +#endif LR_localVAD = 0; + move16(); - IF ( hSCE != NULL ) + IF( hSCE != NULL ) { st = hSCE->hCoreCoder[n]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + signal_in = hSCE->hCoreCoder[n]->input; +#endif signal_in_fx = hSCE->hCoreCoder[n]->input_fx; + signal32_in_fx = hSCE->hCoreCoder[n]->input32_fx; element_mode = IVAS_SCE; last_element_brate = hSCE->last_element_brate; hStereoClassif = NULL; lr_vad_enabled = 0; + move16(); + move32(); + move16(); } ELSE /* CPE */ { st = hCPE->hCoreCoder[n]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + signal_in = hCPE->hCoreCoder[n]->input; +#endif signal_in_fx = hCPE->hCoreCoder[n]->input_fx; + signal32_in_fx = hCPE->hCoreCoder[n]->input32_fx; element_mode = hCPE->element_mode; last_element_brate = hCPE->last_element_brate; hStereoClassif = hCPE->hStereoClassif; lr_vad_enabled = 0; - IF ( hCPE->hFrontVad[0] != NULL && NE_16(hCPE->element_mode, IVAS_CPE_MDCT )) + move16(); + move32(); + move16(); + test(); + IF( hCPE->hFrontVad[0] != NULL && NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) { lr_vad_enabled = 1; + move16(); } - IF ( lr_vad_enabled && EQ_16(n, 0 )) + IF( lr_vad_enabled && n == 0 ) { /* Combine localVAD and vad_flag from LR processing */ + test(); LR_localVAD = hCPE->hCoreCoder[0]->localVAD || hCPE->hCoreCoder[1]->localVAD; + move16(); } - IF ( hCPE->hStereoTD != NULL ) + IF( hCPE->hStereoTD != NULL ) { tdm_SM_last_clas = &hCPE->hStereoTD->tdm_SM_last_clas[n]; Copy( hCPE->hStereoTD->tdm_SM_last_clas, hCPE->hStereoTD->tdm_SM_last2_clas, CPE_CHANNELS ); } - IF ( hCPE->hStereoDft != NULL ) + IF( hCPE->hStereoDft != NULL ) { +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + res_cod_SNR_M = hCPE->hStereoDft->res_cod_SNR_M; +#endif +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING res_cod_SNR_M_fx = hCPE->hStereoDft->res_cod_SNR_M_fx; +#endif } } + +#if 0 + lgBin_E_fx = NULL; + if ( st != NULL ) + { + lgBin_E_fx = &st->lgBin_E_fx[0]; + } #endif lMemRecalc_12k8 = 0; lMemRecalc = 0; + move16(); + move16(); + test(); IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { - lMemRecalc = NS2SA( st->input_Fs, L_MEM_RECALC_NS ); - lMemRecalc_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_NS ); + lMemRecalc = NS2SA_FX2( st->input_Fs, L_MEM_RECALC_NS ); + lMemRecalc_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_NS ); } input_Fs = st->input_Fs; + move32(); localVAD_HE_SAD = 0; + move16(); + #if 1 - snr_sum_he = 0; -#endif corr_shiftL = 0; corr_shiftR = 0; -#if 0 +#endif // DEBUG + +#if 1 snr_sum_he_fx = 0; + move16(); #endif + + corr_shiftL_fx = 0; + corr_shiftR_fx = 0; + move16(); + move16(); + IF( hSCE != NULL ) { *vad_hover_flag = 0; + move16(); } st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; st->coder_type = GENERIC; + move16(); + move16(); + move16(); IF( st->hGSCEnc != NULL ) { st->hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); } *attack_flag = 0; @@ -1137,19 +1250,25 @@ ivas_error pre_proc_front_ivas_fx( st->hSC_VBR->ppp_mode = 0; st->hSC_VBR->nelp_mode = 0; st->hSC_VBR->avoid_HQ_VBR_NB = 0; + move16(); + move16(); + move16(); + move16(); } L_look = L_LOOK_12k8; /* lookahead at 12.8kHz */ + move16(); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + // int x = L_INP_MEM - L_look; inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ -#ifdef IVAS_FLOAT_FIXED - new_inp_12k8_fx = old_inp_12k8_fx + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ -#if 0 - inp_12k8_fx = new_inp_12k8_fx - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ -#endif #endif - if ( element_mode != IVAS_CPE_DFT ) + new_inp_12k8_fx = old_inp_12k8_fx + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + inp_12k8_fx = new_inp_12k8_fx - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + if ( NE_16( element_mode, IVAS_CPE_DFT ) ) { new_inp_12k8 -= L_FILT; } @@ -1166,186 +1285,125 @@ ivas_error pre_proc_front_ivas_fx( { mvr2r( st->old_inp_12k8, old_inp_12k8, L_INP_MEM - L_FILT ); } - mvr2r( st->old_wsp, old_wsp, L_WSP_MEM ); wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ - +#endif + Copy( st->old_wsp_fx, old_wsp_fx, L_WSP_MEM ); + wsp_fx = old_wsp_fx + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ IF( NE_16( element_mode, IVAS_CPE_DFT ) ) { new_inp_12k8_fx -= L_FILT; } -#if 0 - IF(EQ_16(element_mode, IVAS_CPE_DFT)) + + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - STEREO_DFT_OVL_12k8); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - STEREO_DFT_OVL_12k8 ); } - ELSE IF(EQ_16(element_mode, IVAS_CPE_TD)) + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - lMemRecalc_12k8 - L_FILT); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - lMemRecalc_12k8 - L_FILT ); } ELSE { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - L_FILT); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - L_FILT ); } - Copy(st->old_wsp, old_wsp, L_WSP_MEM); - wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ -#endif + Copy( st->old_wsp_fx, old_wsp_fx, L_WSP_MEM ); + wsp_fx = old_wsp_fx + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ + st->rf_mode = st->Opt_RF_ON; + move16(); last_core_orig = st->last_core; + move16(); /*--------------------------------------------------------------* * energy analysis *---------------------------------------------------------------*/ - floatToFixed_arr( signal_in - (Word16) ( input_Fs / 50 ), signal_in_fx, 0, (Word16) ( input_Fs / 25 ) ); - signal_in_fx = signal_in_fx + input_Fs / 50; + test(); + test(); + test(); + test(); + test(); IF( EQ_16( element_mode, IVAS_SCE ) || ( EQ_16( element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) { - analysisCldfbEncoder_ivas_fx( st, signal_in_fx, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); - for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) - { - for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) - { - realBuffer[i][j] = (float) realBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - imagBuffer[i][j] = (float) imagBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - } - } - cldfbScale.hb_scale = cldfbScale.lb_scale; - fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + analysisCldfbEncoder_ivas_fx( st, signal32_in_fx, 11, input_frame, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); } - ELSE IF( ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 0 ) ) || ( EQ_16( st->idchan, 1 ) && st->tdm_LRTD_flag ) ) + ELSE IF( ( EQ_16( element_mode, IVAS_CPE_TD ) && st->idchan == 0 ) || ( EQ_16( st->idchan, 1 ) && st->tdm_LRTD_flag ) ) { /* cldfb analysis only for pri. channel */ - analysisCldfbEncoder_ivas_fx( st, signal_in_fx - NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ), realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); - for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) - { - for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) - { - realBuffer[i][j] = (float) realBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - imagBuffer[i][j] = (float) imagBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - } - } - cldfbScale.hb_scale = cldfbScale.lb_scale; - fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + analysisCldfbEncoder_ivas_fx( st, signal32_in_fx - NS2SA_FX2( input_Fs, L_MEM_RECALC_TBE_NS ), 11, input_frame, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); } ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - calculate_energy_buffer( hCPE, enerBuffer, st->cldfbAnaEnc->no_channels, input_Fs ); - f2me_buf( enerBuffer, enerBuffer_fx, &enerBuffer_exp, 60 ); + calculate_energy_buffer_ivas_fx( hCPE, enerBuffer_fx, st->cldfbAnaEnc->no_channels, input_Fs, &enerBuffer_exp ); } ELSE { set32_fx( enerBuffer_fx, 0, CLDFB_NO_CHANNELS_MAX ); enerBuffer_exp = 31; + move16(); } /*----------------------------------------------------------------* * Change the sampling frequency to 12.8 kHz * (if not available from downsampled DMX) *----------------------------------------------------------------*/ -#if 0 // Disabled due to high mld -- Scaling needs to be handled. - IF( element_mode == IVAS_SCE ) + Word16 scale_factor = sub( getScaleFactor16( st->input_fx - (Word16) ( st->input_Fs / 50 ), (Word16) ( st->input_Fs / 25 ) ), 1 ); + Word16 q_input = s_min( add( -1, scale_factor ), sub( 16, old_inp_12k8_e ) ); + Copy_Scale_sig32_16( st->input32_fx - (Word16) ( st->input_Fs / 50 ), st->input_fx - (Word16) ( st->input_Fs / 50 ), (Word16) ( st->input_Fs / 25 ), add( 16 - 11, q_input ) ); /*scaling down from q11 to q_input*/ + Scale_sig( st->mem_decim_fx, 90, sub( q_input, 15 - mem_decim_e ) ); /*scaling from q(15-mem_decim_e) to q_input*/ + Scale_sig( old_inp_12k8_fx, 496, sub( q_input, sub( 15, old_inp_12k8_e ) ) ); /*scaling from q(15-old_inp_12k8_e) to q_input*/ + test(); + IF( EQ_16( element_mode, IVAS_SCE ) ) { - new_inp_out_size = modify_Fs_fx( signal_in_fx, input_frame, input_Fs, new_inp_12k8_fx, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); - - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, Q_new_inp, new_inp_out_size ); // To be removed - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed - - change_q( new_inp_12k8_fx, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx, input_frame, input_Fs, new_inp_12k8_fx, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ Copy( st->mem_decim_fx, mem_decim_dummy_fx, 2 * L_FILT_MAX ); - set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); - - new_inp_out_size = modify_Fs_fx( temp1F_icatdmResampBuf_fx, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); - - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME, new_inp_12k8 + L_FRAME, Q_new_inp, new_inp_out_size ); // To be removed - change_q( new_inp_12k8_fx + L_FRAME, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA_FX2( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + L_FRAME, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { /* reconstruct past segment of the Secondary channel input signal when switching from DFT stereo */ - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) + test(); + IF( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) { - Word16 length_inp = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - new_inp_out_size = modify_Fs_fx( signal_in_fx - lMemRecalc - length_inp, length_inp, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, INT_FS_12k8, st->mem_decim_fx, 0, &Q_new_inp, &mem_decim_size ); - - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, Q_new_inp, new_inp_out_size ); // To be removed + Word16 length_inp = NS2SA_FX2( input_Fs, L_MEM_RECALC_SCH_NS ); + Word16 length_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - change_q( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx - add( lMemRecalc, length_inp ), length_inp, input_Fs, new_inp_12k8_fx - add( lMemRecalc_12k8, length_12k8 ), INT_FS_12k8, st->mem_decim_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx - add( lMemRecalc_12k8, length_12k8 ), new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } - new_inp_out_size = modify_Fs_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); Copy( st->mem_decim_fx, mem_decim_dummy_fx, 2 * L_FILT_MAX ); - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, Q_new_inp, new_inp_out_size ); // To be removed - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed + Scale_sig( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ - change_q( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_out_size, Q_new_inp ); - - IF( GT_16( lMemRecalc, 0 ) ) + IF( lMemRecalc > 0 ) { - new_inp_out_size = modify_Fs_fx( signal_in_fx + input_frame - lMemRecalc, lMemRecalc, input_Fs, new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, INT_FS_12k8, mem_decim_dummy_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, new_inp_12k8 + L_FRAME - lMemRecalc_12k8, Q_new_inp, new_inp_out_size ); // To be removed - - change_q( new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx + sub( input_frame, lMemRecalc ), lMemRecalc, input_Fs, new_inp_12k8_fx + sub( L_FRAME, lMemRecalc_12k8 ), INT_FS_12k8, mem_decim_dummy_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + sub( L_FRAME, lMemRecalc_12k8 ), new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); - new_inp_out_size = modify_Fs_fx( temp1F_icatdmResampBuf_fx, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME, new_inp_12k8 + L_FRAME, Q_new_inp, new_inp_out_size ); // To be removed - - change_q( new_inp_12k8_fx + L_FRAME, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + L_FRAME, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } ELSE /* DFT stereo */ { /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ - Copy( signal_in_fx + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); - mvr2r( signal_in + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); // To be removed + Copy( signal_in_fx + sub( input_frame, add( NS2SA_FX2( input_Fs, L_MEM_RECALC_NS ), 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ) ), st->mem_decim_fx, 2 * NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ) ); } -#else - if ( element_mode == IVAS_SCE ) - { - modify_Fs( signal_in, input_frame, input_Fs, new_inp_12k8, INT_FS_12k8, st->mem_decim, ( st->max_bwidth == NB ) ); + old_inp_12k8_e = sub( 15, q_input ); - mvr2r( st->mem_decim, mem_decim_dummy, 2 * L_FILT_MAX ); - set_f( temp1F_icatdmResampBuf, 0, L_FILT_MAX ); - modify_Fs( temp1F_icatdmResampBuf, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8 + L_FRAME, INT_FS_12k8, mem_decim_dummy, 0 ); - } - else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) - { - /* reconstruct past segment of the Secondary channel input signal when switching from DFT stereo */ - if ( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) - { - int16_t length_inp = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); - int16_t length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - modify_Fs( signal_in - lMemRecalc - length_inp, length_inp, input_Fs, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, INT_FS_12k8, st->mem_decim, 0 ); - } - - modify_Fs( signal_in - lMemRecalc, input_frame, input_Fs, new_inp_12k8 - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim, ( st->max_bwidth == NB ) ); - mvr2r( st->mem_decim, mem_decim_dummy, 2 * L_FILT_MAX ); - - if ( lMemRecalc > 0 ) - { - modify_Fs( signal_in + input_frame - lMemRecalc, lMemRecalc, input_Fs, new_inp_12k8 + L_FRAME - lMemRecalc_12k8, INT_FS_12k8, mem_decim_dummy, ( st->max_bwidth == NB ) ); - } - set_f( temp1F_icatdmResampBuf, 0, L_FILT_MAX ); - modify_Fs( temp1F_icatdmResampBuf, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8 + L_FRAME, INT_FS_12k8, mem_decim_dummy, 0 ); - } - else /* DFT stereo */ - { - /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ - mvr2r( signal_in + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); - } -#endif - /* save input resampled at 12.8kHz, non-preemhasised */ - if ( element_mode == IVAS_CPE_DFT ) - { - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8, st->buf_speech_enc_flt + L_FRAME32k - STEREO_DFT_OVL_12k8, L_FRAME + STEREO_DFT_OVL_12k8 ); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + /* save input resampled at 12.8kHz, non-preemhasised */ + if ( element_mode == IVAS_CPE_DFT ) + { + mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8, st->buf_speech_enc_flt + L_FRAME32k - STEREO_DFT_OVL_12k8, L_FRAME + STEREO_DFT_OVL_12k8 ); } else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) { @@ -1355,6 +1413,8 @@ ivas_error pre_proc_front_ivas_fx( { mvr2r( new_inp_12k8, st->buf_speech_enc_flt + L_FRAME32k, L_FRAME ); } +#endif // DEBUG + #ifndef MSAN_FIX /*To be enabled when updations related to new_inp_12k8_fx is enabled */ #if 1 IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) @@ -1377,212 +1437,116 @@ ivas_error pre_proc_front_ivas_fx( /*------------------------------------------------------------------* * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ -#if 0 // Disabled due to high mld -#if 0 // EVS-Version - Word16 headroom = 1; - IF( ( ( EQ_16( st->bwidth, NB ) ) || ( EQ_16( st->max_bwidth, NB ) ) ) && ( GT_32( st->input_Fs, 8000 ) ) ) - { - headroom = add( headroom, 1 ); - } - IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) - { - Copy( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw_fx, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - - st->mem_preemph_fx = st->mem_preemph_DFT_fx; - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; - - Preemph_scaled( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, new_inp_12k8 - STEREO_DFT_OVL_12k8, Q_new, L_FRAME ); // To be removed - dummy_fx = st->mem_preemph_fx; - Preemph_scaled( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, STEREO_DFT_OVL_12k8, st->last_coder_type, 1 ); - - st->mem_preemph = (float) st->mem_preemph_fx; - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, Q_new, STEREO_DFT_OVL_12k8 ); // To be removed - } - ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) - { - IF( EQ_16( st->idchan, 0 ) ) - { - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) - { - st->mem_preemph_fx = st->mem_preemph_DFT_fx; - Copy( st->inp_12k8_mem_stereo_sw_fx, new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); - Preemph_scaled( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, st->last_coder_type, 1 ); - - st->mem_preemph = (float) st->mem_preemph_fx; - fixedToFloat_arr( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), Q_new, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed - } - - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ - } - - /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) - { - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, length_12k8, st->last_coder_type, 1 ); - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, Q_new, length_12k8 ); // To be removed - } - - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - dummy_fx = st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, Q_new, L_FRAME ); // To be removed - - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, lMemRecalc_12k8 + L_FILT, st->last_coder_type, 1 ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, new_inp_12k8 - lMemRecalc_12k8 + L_FRAME, Q_new, lMemRecalc_12k8 + L_FILT ); // To be removed - } - ELSE /* IVAS_SCE or IVAS_CPE_MDCT */ - { - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - - Preemph_scaled( new_inp_12k8_fx, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - dummy_fx = st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, Q_new, L_FRAME ); // To be removed - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - - Preemph_scaled( new_inp_12k8_fx + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FILT, st->last_coder_type, 1 ); - st->mem_preemph = (float) st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx + 256, new_inp_12k8 + 256, Q_new, 12 ); // To be removed - } - - Q_exp = sub( Q_new, st->Q_old ); - st->prev_Q_old = st->Q_old; + max_e = old_inp_12k8_e; move16(); - st->Q_old = Q_new; + max_e = s_max( max_e, mem_preemph_e ); + max_e = s_max( max_e, mem_preemph_DFT_e ); + Scale_sig( old_inp_12k8_fx, 496, sub( old_inp_12k8_e, max_e ) ); + st->mem_preemph_DFT_fx = shr( st->mem_preemph_DFT_fx, sub( max_e, mem_preemph_DFT_e ) ); + st->mem_preemph_fx = shr( st->mem_preemph_fx, sub( max_e, mem_preemph_e ) ); + old_inp_12k8_e = mem_preemph_DFT_e = mem_preemph_e = max_e; move16(); -#else // IVAS-Version - + move16(); + move16(); + move16(); + move16(); + test(); IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - floatToFixed_arr( new_inp_12k8 - STEREO_DFT_OVL_12k8, new_inp_12k8_fx - STEREO_DFT_OVL_12k8, 0, L_FRAME + STEREO_DFT_OVL_12k8 ); // To be removed - st->mem_preemph_fx = (Word16) st->mem_preemph; - st->mem_preemph_DFT_fx = (Word16) st->mem_preemph_DFT; - Copy( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw_fx, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ -#if 1 // TOBE removed later - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; -#endif + inp_12k8_mem_stereo_sw_e = old_inp_12k8_e; + move16(); + st->mem_preemph_fx = st->mem_preemph_DFT_fx; + move16(); st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; + move16(); PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; - PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8, &dummy_fx ); + move16(); - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, new_inp_12k8 - STEREO_DFT_OVL_12k8, 0, L_FRAME + STEREO_DFT_OVL_12k8 ); // To be removed - st->mem_preemph = (float) st->mem_preemph_fx; - st->mem_preemph_DFT = (float) st->mem_preemph_DFT_fx; + PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC, STEREO_DFT_OVL_12k8, &dummy_fx ); } ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { - IF( EQ_16( st->idchan, 0 ) ) + IF( st->idchan == 0 ) { - - st->mem_preemph_fx = (Word16) st->mem_preemph; IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) { -#if 1 // TOBE removed later - - floatToFixed_arr( new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), 0, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed - st->mem_preemph_DFT_fx = (Word16) st->mem_preemph_DFT; - - mvr2r( st->inp_12k8_mem_stereo_sw, new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); -#endif st->mem_preemph_fx = st->mem_preemph_DFT_fx; + move16(); + IF( GT_16( inp_12k8_mem_stereo_sw_e, old_inp_12k8_e ) ) + { + Scale_sig( new_inp_12k8_fx - ( L_INP_MEM - L_FILT ), L_FRAME + L_INP_MEM, old_inp_12k8_e - inp_12k8_mem_stereo_sw_e ); + old_inp_12k8_e = inp_12k8_mem_stereo_sw_e; + st->mem_preemph_fx = shr( st->mem_preemph_fx, inp_12k8_mem_stereo_sw_e - mem_preemph_e ); + mem_preemph_e = inp_12k8_mem_stereo_sw_e; + move16(); + move16(); + move16(); + } + ELSE + { + Scale_sig( st->inp_12k8_mem_stereo_sw_fx, 4, inp_12k8_mem_stereo_sw_e - old_inp_12k8_e ); + inp_12k8_mem_stereo_sw_e = old_inp_12k8_e; + move16(); + } Copy( st->inp_12k8_mem_stereo_sw_fx, new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); PREEMPH_FX( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), PREEMPH_FAC, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, &st->mem_preemph_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), 0, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed } - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ -#if 1 // TOBE removed later - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ // TO be remove later -#endif + st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ + mem_preemph_DFT_e = old_inp_12k8_e; + move16(); } /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ + test(); IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) { - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - floatToFixed_arr( new_inp_12k8 - lMemRecalc_12k8 - length_12k8, new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, 0, length_12k8 ); // To be removed - + Word16 length_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); + move16(); PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, PREEMPH_FAC, length_12k8, &st->mem_preemph_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, 0, length_12k8 ); // To be removed } - floatToFixed_arr( new_inp_12k8 - lMemRecalc_12k8, new_inp_12k8_fx - lMemRecalc_12k8, 0, L_FRAME + lMemRecalc_12k8 + L_FILT ); // To be removed - PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; + move16(); PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, PREEMPH_FAC, lMemRecalc_12k8 + L_FILT, &dummy_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, 0, L_FRAME + lMemRecalc_12k8 + L_FILT ); // To be removed } ELSE /* IVAS_SCE or IVAS_CPE_MDCT */ { - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - st->mem_preemph_fx = (Word16) st->mem_preemph; - PREEMPH_FX( new_inp_12k8_fx, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; + move16(); PREEMPH_FX( new_inp_12k8_fx + L_FRAME, PREEMPH_FAC, L_FILT, &dummy_fx ); - - st->mem_preemph = (float) st->mem_preemph_fx; - dummy = (float) dummy_fx; - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, 0, L_FRAME + L_FILT ); // To be removed } -#endif -#else - if ( element_mode == IVAS_CPE_DFT ) - { - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - - st->mem_preemph = st->mem_preemph_DFT; - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; - preemph( new_inp_12k8 - STEREO_DFT_OVL_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8, &dummy ); - } - else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) - { - if ( st->idchan == 0 ) - { - if ( hCPE->last_element_mode == IVAS_CPE_DFT ) - { - st->mem_preemph = st->mem_preemph_DFT; - mvr2r( st->inp_12k8_mem_stereo_sw, new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); - preemph( new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, &st->mem_preemph ); - } +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + /*fixed to float from modify_fs block*/ + fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, q_input, 90 ); // To be removed - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ - } + /*fixed to float conversions for preemph_fx block*/ + st->mem_preemph = me2f_16( st->mem_preemph_fx, mem_preemph_e ); + st->mem_preemph_DFT = me2f_16( st->mem_preemph_DFT_fx, mem_preemph_DFT_e ); + fixedToFloat_arr( st->inp_12k8_mem_stereo_sw_fx, st->inp_12k8_mem_stereo_sw, 15 - inp_12k8_mem_stereo_sw_e, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); + fixedToFloat_arr( old_inp_12k8_fx, old_inp_12k8, 15 - old_inp_12k8_e, L_INP_MEM + L_FRAME ); // To be removed - /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ - if ( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) + /*analysisCldfbEncoder_ivas_fx*/ + for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - int16_t length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - preemph( new_inp_12k8 - lMemRecalc_12k8 - length_12k8, PREEMPH_FAC_FLT, length_12k8, &st->mem_preemph ); + realBuffer[i][j] = fixedToFloat( realBuffer_fx[i][j], 16 - cldfbScale.lb_scale ); + imagBuffer[i][j] = fixedToFloat( imagBuffer_fx[i][j], 16 - cldfbScale.lb_scale ); } - - preemph( new_inp_12k8 - lMemRecalc_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 - lMemRecalc_12k8 + L_FRAME, PREEMPH_FAC_FLT, lMemRecalc_12k8 + L_FILT, &dummy ); } - else /* IVAS_SCE or IVAS_CPE_MDCT */ + cldfbScale.hb_scale = cldfbScale.lb_scale; + fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + IF( st->cldfbAnaEnc != NULL ) { - preemph( new_inp_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 + L_FRAME, PREEMPH_FAC_FLT, L_FILT, &dummy ); + fixedToFloat_arrL( st->cldfbAnaEnc->cldfb_state_fx, st->cldfbAnaEnc->cldfb_state, Q11, sub( sub( st->cldfbAnaEnc->p_filter_length, st->cldfbAnaEnc->no_channels ), st->cldfbAnaEnc->zeros ) ); } #endif @@ -1603,115 +1567,155 @@ ivas_error pre_proc_front_ivas_fx( /*-------------------------------------------------------------------------* * Spectral analysis *--------------------------------------------------------------------------*/ +#if 1 /*Fixed implementation disabled due to wrong values*/ analy_sp( element_mode, hCPE, input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, &Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); +#else + Word16 Q_inp_dmx = Q_factor_arrL( hCPE->hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ) - 1; + floatToFixed_arrL( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], Q_inp_dmx, STEREO_DFT_N_MAX_ENC ); + Word16 Q_new; + Word16 Scale_fac[2]; + Q_new = 15 - old_inp_12k8_e; + Le_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_new, QSCALE ) ) ), 1 ), 1 ); + ivas_analy_sp_fx( element_mode, hCPE, input_Fs, inp_12k8_fx /*old_inp_12k8_e*/, Q_new, fr_bands_fx, lf_E_fx, &Etot_16fx, st->min_band, st->max_band, Le_min_scaled, Scale_fac, st->Bin_E_fx, st->Bin_E_old_fx, PS_fx, lgBin_E_fx, band_energies_fx, fft_buff_fx, Q_inp_dmx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( fr_bands_fx, fr_bands, Q_new + QSCALE + 2, 40 ); + fixedToFloat_arrL( band_energies_fx, band_energies, Q_new + QSCALE + 2, 40 ); + fixedToFloat_arrL( lf_E_fx, lf_E, Q_new + QSCALE, 148 ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, Q_new + QSCALE, 256 ); + IF( lgBin_E_fx != NULL ) + { + fixedToFloat_arr( lgBin_E_fx, st->Bin_E, Q7, 128 ); + } + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, Q_new + QSCALE, 128 ); + fixedToFloat_arrL( PS_fx, PS, Q_new + QSCALE, 128 ); + Etot = fixedToFloat( Etot_16fx, Q8 ); + fixedToFloat_arr( fft_buff_fx, fft_buff, Q_new + QSCALE + Scale_fac[0] - 14, 512 ); +#endif +#endif - if ( hStereoClassif != NULL ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*float to fix conversions for noise_est_pre_32fx*/ + Etot_fx = (Word32) ( Etot * ( 1 << 24 ) ); + st->hNoiseEst->Etot_l_lp_32fx = (Word32) ( st->hNoiseEst->Etot_l_lp * 16777216.0 ); + st->hNoiseEst->Etot_last_32fx = (Word32) ( st->hNoiseEst->Etot_last * 16777216.0 ); + st->hNoiseEst->Etot_v_h2_32fx = (Word32) ( st->hNoiseEst->Etot_v_h2 * 16777216.0 ); + st->hNoiseEst->Etot_lp_32fx = (Word32) ( st->hNoiseEst->Etot_lp * 16777216.0 ); + st->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( st->hNoiseEst->sign_dyn_lp * 16777216.0 ); + + /*float to fix conversions for wb_vad_ivas_fx*/ + Word16 Q_new = Q_factor_arr( fr_bands, 40 ) + 3; + floatToFixed_arrL( fr_bands, fr_bands_fx, Q_new + QSCALE, 40 ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, 8 ); + st->lp_speech_fx = float_to_fix16( st->lp_speech, 8 ); + floatToFixed_arrL( st->hNoiseEst->bckr, st->hNoiseEst->bckr_fx, Q_new + QSCALE, 20 ); + floatToFixed_arrL( st->hNoiseEst->enrO, st->hNoiseEst->enrO_fx, Q_new + QSCALE, 20 ); + st->flag_noisy_speech_snr_fx = (Word8) st->flag_noisy_speech_snr; + + /*float to fix for dtx_hangover_addition_fx*/ + st->hNoiseEst->Etot_lp_fx = (Word16) ( st->hNoiseEst->Etot_lp * ( 1 << 8 ) ); + + if ( st->cldfbAnaEnc ) + st->cldfbAnaEnc->scale = (Word16) ( st->cldfbAnaEnc->scale_flt * ( 1 << 8 ) ); + st->lt_mean_NB_fx = (Word16) st->lt_mean_NB * ( 1 << 11 ); + st->lt_mean_WB_fx = (Word16) st->lt_mean_WB * ( 1 << 11 ); + st->lt_mean_SWB_fx = (Word16) st->lt_mean_SWB * ( 1 << 11 ); + + Word16 Q_bands0 = 0, Q_bands1 = 0; + IF( lr_vad_enabled && st->idchan == 0 ) + { + Q_bands0 = Q_factor_arr( fr_bands_LR[0], 2 * NB_BANDS ); + Q_bands1 = Q_factor_arr( fr_bands_LR[1], 2 * NB_BANDS ); + floatToFixed_arrL( fr_bands_LR[0], fr_bands_LR_fx[0], Q_bands0 + QSCALE, 2 * NB_BANDS ); + floatToFixed_arrL( fr_bands_LR[1], fr_bands_LR_fx[1], Q_bands1 + QSCALE, 2 * NB_BANDS ); + floatToFixed_arrL( hCPE->hFrontVad[0]->hNoiseEst->bckr, hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, Q_bands0 + QSCALE, NB_BANDS ); + floatToFixed_arrL( hCPE->hFrontVad[1]->hNoiseEst->bckr, hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, Q_bands1 + QSCALE, NB_BANDS ); + Etot_LR_fx[0] = float_to_fix16( Etot_LR[0], 8 ); + Etot_LR_fx[1] = float_to_fix16( Etot_LR[1], 8 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->Etot_last, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->Etot_last, 8 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2, 8 ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( hStereoClassif != NULL ) { - if ( st->lp_speech - Etot > 25 ) + IF( GT_32( L_sub( L_shl( st->lp_speech_fx, 16 ), Etot_fx ), 25 << Q24 ) ) /*q24*/ { hStereoClassif->silence_flag = 2; + move16(); } - else + ELSE { - hStereoClassif->silence_flag = hStereoClassif->silence_flag - 1; + hStereoClassif->silence_flag = sub( hStereoClassif->silence_flag, 1 ); + move16(); } - hStereoClassif->silence_flag = max( 0, hStereoClassif->silence_flag ); + hStereoClassif->silence_flag = s_max( 0, hStereoClassif->silence_flag ); + move16(); } /*----------------------------------------------------------------* * SAD (1-signal, 0-noise) *----------------------------------------------------------------*/ - Etot_fx = (Word32) ( Etot * ( 1 << 24 ) ); - st->hNoiseEst->Etot_h_32fx = (Word32) ( st->hNoiseEst->Etot_h * 16777216.0 ); - st->hNoiseEst->Etot_l_32fx = (Word32) ( st->hNoiseEst->Etot_l * 16777216.0 ); - st->hNoiseEst->Etot_l_lp_32fx = (Word32) ( st->hNoiseEst->Etot_l_lp * 16777216.0 ); - st->hNoiseEst->Etot_last_32fx = (Word32) ( st->hNoiseEst->Etot_last * 16777216.0 ); - st->hNoiseEst->Etot_v_h2_32fx = (Word32) ( st->hNoiseEst->Etot_v_h2 * 16777216.0 ); - st->hNoiseEst->Etot_lp_32fx = (Word32) ( st->hNoiseEst->Etot_lp * 16777216.0 ); - st->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( st->hNoiseEst->sign_dyn_lp * 16777216.0 ); - noise_est_pre_32fx( Etot_fx, st->ini_frame, st->hNoiseEst, st->idchan, element_mode, hCPE != NULL ? hCPE->last_element_mode : element_mode ); - st->hNoiseEst->Etot_h = (float) ( st->hNoiseEst->Etot_h_32fx / 16777216.0 ); - st->hNoiseEst->Etot_l = (float) ( st->hNoiseEst->Etot_l_32fx / 16777216.0 ); - st->hNoiseEst->Etot_l_lp = (float) ( st->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); - st->hNoiseEst->Etot_last = (float) ( st->hNoiseEst->Etot_last_32fx / 16777216.0 ); - st->hNoiseEst->Etot_v_h2 = (float) ( st->hNoiseEst->Etot_v_h2_32fx / 16777216.0 ); - st->hNoiseEst->Etot_lp = (float) ( st->hNoiseEst->Etot_lp_32fx / 16777216.0 ); - st->hNoiseEst->sign_dyn_lp = (float) ( st->hNoiseEst->sign_dyn_lp_32fx / 16777216.0 ); - - IF( EQ_16( element_mode, IVAS_CPE_TD ) && ( ( abs( hCPE->hStereoTD->tdm_last_ratio_idx - tdm_ratio_idx ) > 5 && EQ_16( st->idchan, 1 ) ) || abs( hCPE->hStereoTD->tdm_last_inst_ratio_idx - hCPE->hStereoTD->tdm_inst_ratio_idx ) > 10 ) ) + test(); + test(); + test(); + if ( EQ_16( element_mode, IVAS_CPE_TD ) && ( ( GT_16( abs_s( sub( hCPE->hStereoTD->tdm_last_ratio_idx, tdm_ratio_idx ) ), 5 ) && EQ_16( st->idchan, 1 ) ) || GT_16( abs_s( sub( hCPE->hStereoTD->tdm_last_inst_ratio_idx, hCPE->hStereoTD->tdm_inst_ratio_idx ) ), 10 ) ) ) { st->ini_frame = 1; + move16(); } -#if 0 // Disbaled due to high MLD - Q_new = Q_factor_arr( fr_bands, 40 ); - floatToFixed_arrL( fr_bands, fr_bands_fx, Q_new + QSCALE, 40 ); - st->lp_noise_fx = (Word16) ( st->lp_noise * ( 1 << 8 ) ); - st->lp_speech_fx = (Word16) ( st->lp_speech * ( 1 << 8 ) ); - floatToFixed_arrL( st->hNoiseEst->bckr, st->hNoiseEst->bckr_fx, Q_new + QSCALE, 20 ); - floatToFixed_arrL( st->hNoiseEst->enrO, st->hNoiseEst->enrO_fx, Q_new + QSCALE, 20 ); - st->flag_noisy_speech_snr_fx = (Word8) st->flag_noisy_speech_snr; - st->hVAD->bcg_flux_fx = (Word16) st->hVAD->bcg_flux * ( 1 << 4 ); - st->hNoiseEst->Etot_v_h2_fx = (Word16) ( st->hNoiseEst->Etot_v_h2 * ( 1 << 8 ) ); - st->hNoiseEst->sign_dyn_lp_fx = (Word16) ( st->hNoiseEst->sign_dyn_lp * ( 1 << 8 ) ); - st->hVAD->snr_sum_vad_fx = (Word16) ( st->hVAD->snr_sum_vad * 32767 ); - st->hVAD->prim_act_quick_fx = (Word16) ( st->hVAD->prim_act_quick * 32767 ); - st->hVAD->prim_act_slow_fx = (Word16) ( st->hVAD->prim_act_slow * 32767 ); - st->hVAD->prim_act_fx = (Word16) ( st->hVAD->prim_act * 32767 ); - st->hVAD->prim_act_quick_he_fx = (Word16) ( st->hVAD->prim_act_quick_he * 32767 ); - st->hVAD->prim_act_slow_he_fx = (Word16) ( st->hVAD->prim_act_slow_he * 32767 ); - st->hVAD->prim_act_he_fx = (Word16) ( st->hVAD->prim_act_he * 32767 ); - + st->hNoiseEst->Etot_v_h2_fx = extract_h( st->hNoiseEst->Etot_v_h2_32fx ); /*q24 to q8*/ + st->hNoiseEst->sign_dyn_lp_fx = extract_h( st->hNoiseEst->sign_dyn_lp_32fx ); /*q24 to q8*/ st->vad_flag = wb_vad_ivas_fx( st, fr_bands_fx, &i, &i, &i, &snr_sum_he_fx, &localVAD_HE_SAD, &( st->flag_noisy_speech_snr_fx ), Q_new, NULL, NULL, -MAX_16, -MAX_16 ); //-100000f == max 16bit float + move16(); + move16(); + move16(); - st->hNoiseEst->Etot_v_h2 = (float) ( st->hNoiseEst->Etot_v_h2_fx / ( 256.0 ) ); - st->hNoiseEst->sign_dyn_lp = (float) ( st->hNoiseEst->sign_dyn_lp_fx / ( 256.0 ) ); - st->hVAD->bcg_flux = (float) ( st->hVAD->bcg_flux_fx / ( 16.0 ) ); - st->flag_noisy_speech_snr = (Word16) st->flag_noisy_speech_snr_fx; - st->hVAD->snr_sum_vad = (float) ( st->hVAD->snr_sum_vad_fx / 32767.0 ); - st->hVAD->prim_act_quick = (float) ( st->hVAD->prim_act_quick_fx / 32767.0 ); - st->hVAD->prim_act_slow = (float) ( st->hVAD->prim_act_slow_fx / 32767.0 ); - st->hVAD->prim_act = (float) ( st->hVAD->prim_act_fx / 32767.0 ); - st->hVAD->prim_act_quick_he = (float) ( st->hVAD->prim_act_quick_he_fx / 32767.0 ); - st->hVAD->prim_act_slow_he = (float) ( st->hVAD->prim_act_slow_he_fx / 32767.0 ); - st->hVAD->prim_act_he = (float) ( st->hVAD->prim_act_he_fx / 32767.0 ); -#else - st->vad_flag = wb_vad( st, fr_bands, &i, &i, &i, &snr_sum_he, &localVAD_HE_SAD, &( st->flag_noisy_speech_snr ), NULL, NULL, -1000.0f, -1000.0f ); -#endif - + test(); IF( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_flag, 1 ) ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ st->vad_flag = front_vad_flag; st->localVAD = front_vad_flag; + move16(); + move16(); } - IF( ( hCPE != NULL && !( lr_vad_enabled && EQ_16( st->idchan, 0 ) ) ) || hSCE != NULL ) + test(); + test(); + test(); + IF( ( hCPE != NULL && !( lr_vad_enabled && st->idchan == 0 ) ) || hSCE != NULL ) { - st->lp_noise_fx = (Word16) ( st->lp_noise * ( 1 << 8 ) ); - st->lp_speech_fx = (Word16) ( st->lp_speech * ( 1 << 8 ) ); - st->hVAD->prim_act_he_fx = (Word16) ( st->hVAD->prim_act_he * MAX_16 ); - st->hNoiseEst->Etot_lp_fx = (Word16) ( st->hNoiseEst->Etot_lp * ( 1 << 8 ) ); *vad_flag_dtx = dtx_hangover_addition_fx( st, st->vad_flag, sub( st->lp_speech_fx, st->lp_noise_fx ), 0, vad_hover_flag, NULL, NULL ); + move16(); } ELSE { /* This only applies to st->idchan==0 now */ /* Add down mix stereo activity to LR vad_flag_dtx */ + test(); *vad_flag_dtx = *vad_flag_dtx || st->vad_flag; + move16(); /* Determine hangover flag status based on LR localVAD and downmix localVAD */ + test(); + test(); *vad_hover_flag = *vad_flag_dtx && !( LR_localVAD || st->localVAD ); + move16(); } - IF( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_dtx_flag, 1 ) ) + test(); + if ( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_dtx_flag, 1 ) ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ *vad_flag_dtx = front_vad_dtx_flag; + move16(); } /*----------------------------------------------------------------* @@ -1723,37 +1727,31 @@ ivas_error pre_proc_front_ivas_fx( move16(); } + test(); IF( EQ_16( st->idchan, 0 ) && NE_16( element_mode, IVAS_CPE_MDCT ) ) { - st->cldfbAnaEnc->scale = (Word16) ( st->cldfbAnaEnc->scale_flt * ( 1 << 8 ) ); - floatToFixed_arr( st->input, st->input_fx, 0, 480 ); -#ifdef MSAN_FIX - st->lt_mean_NB_fx = (Word16) st->lt_mean_NB * ( 1 << 11 ); - st->lt_mean_WB_fx = (Word16) st->lt_mean_WB * ( 1 << 11 ); - st->lt_mean_SWB_fx = (Word16) st->lt_mean_SWB * ( 1 << 11 ); - st->lp_noise_fx = (Word16) st->lp_noise * ( 1 << 8 ); // have taken Q8 as above one functions uses Q8 -#endif + Scale_sig( st->input_fx, 480, negate( q_input ) ); /*scaling from q_input to q0*/ bw_detect_fx( st, st->input_fx, NULL, enerBuffer_fx, sf_energySum, ivas_format, 0 ); - st->lt_mean_NB = (float) st->lt_mean_NB_fx / ( 1 << 11 ); - st->lt_mean_WB = (float) st->lt_mean_WB_fx / ( 1 << 11 ); - st->lt_mean_SWB = (float) st->lt_mean_SWB_fx / ( 1 << 11 ); + Scale_sig( st->input_fx, 480, q_input ); /*scaling back to q_input*/ } + IF( NE_16( element_mode, IVAS_CPE_MDCT ) ) /* in MDCT stereo, set_bw_stereo() is used instead */ { -#ifndef IVAS_FLOAT_FIXED - set_bw( element_mode, element_brate, st, MODE1 ); -#else set_bw_fx( element_mode, element_brate, st, MODE1 ); -#endif } + /* set the BW of the TD secondary channel in LRTD mode same as BW of the primary channel (only at higher bitrates) */ - IF( EQ_16( st->idchan, 1 ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->tdm_LRTD_flag, 1 ) && st->bits_frame_channel >= IVAS_16k4 / FRAMES_PER_SEC ) + test(); + test(); + test(); + if ( EQ_16( st->idchan, 1 ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->tdm_LRTD_flag, 1 ) && GE_16( st->bits_frame_channel, IVAS_16k4 / FRAMES_PER_SEC ) ) { st->bwidth = hCPE->hCoreCoder[0]->bwidth; + move16(); } /*----------------------------------------------------------------* @@ -1762,42 +1760,65 @@ ivas_error pre_proc_front_ivas_fx( * Correlation correction as a function of total noise level *----------------------------------------------------------------*/ - noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); + Word32 Le_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_new, QSCALE ) ) ), 1 ), 1 ); + Etot_16fx = extract_h( Etot_fx ); /*q24 to q8*/ + noise_est_down_fx( fr_bands_fx, st->hNoiseEst->bckr_fx, tmpN_fx, tmpE_fx, st->min_band, st->max_band, &st->hNoiseEst->totalNoise_fx, Etot_16fx, &st->hNoiseEst->Etot_last_fx, &st->hNoiseEst->Etot_v_h2_fx, Q_new, Le_min_scaled ); - if ( lr_vad_enabled && st->idchan == 0 ) + test(); + IF( lr_vad_enabled && st->idchan == 0 ) { - noise_est_down( fr_bands_LR[0], hCPE->hFrontVad[0]->hNoiseEst->bckr, tmpN_LR[0], tmpE_LR[0], st->min_band, st->max_band, &hCPE->hFrontVad[0]->hNoiseEst->totalNoise, Etot_LR[0], &hCPE->hFrontVad[0]->hNoiseEst->Etot_last, &hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2 ); - noise_est_down( fr_bands_LR[1], hCPE->hFrontVad[1]->hNoiseEst->bckr, tmpN_LR[1], tmpE_LR[1], st->min_band, st->max_band, &hCPE->hFrontVad[1]->hNoiseEst->totalNoise, Etot_LR[1], &hCPE->hFrontVad[1]->hNoiseEst->Etot_last, &hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2 ); -#ifndef IVAS_FLOAT_FIXED - corr_shiftL = correlation_shift( hCPE->hFrontVad[0]->hNoiseEst->totalNoise ); - corr_shiftR = correlation_shift( hCPE->hFrontVad[1]->hNoiseEst->totalNoise ); -#else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 corr_shiftL_fx, corr_shiftR_fx; - // performing float to fix conversion of (totalNoise) - hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); - hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); -#endif + Word32 Le_min_scaled0, Le_min_scaled1; + Le_min_scaled0 = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_bands0, QSCALE ) ) ), 1 ), 1 ); + Le_min_scaled1 = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_bands1, QSCALE ) ) ), 1 ), 1 ); + noise_est_down_fx( fr_bands_LR_fx[0], hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, tmpN_LR_fx[0], tmpE_LR_fx[0], st->min_band, st->max_band, &hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx, Etot_LR_fx[0], &hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx, &hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx, Q_bands0, Le_min_scaled0 ); + noise_est_down_fx( fr_bands_LR_fx[1], hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, tmpN_LR_fx[1], tmpE_LR_fx[1], st->min_band, st->max_band, &hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx, Etot_LR_fx[1], &hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx, &hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx, Q_bands1, Le_min_scaled1 ); + corr_shiftL_fx = correlation_shift_fx( hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx ); corr_shiftR_fx = correlation_shift_fx( hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx ); + } #ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*cleanup changes for noise_est_pre_32fx*/ + st->hNoiseEst->Etot_l_lp = (float) ( st->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); + st->hNoiseEst->Etot_last = (float) ( st->hNoiseEst->Etot_last_32fx / 16777216.0 ); + st->hNoiseEst->Etot_lp = (float) ( st->hNoiseEst->Etot_lp_32fx / 16777216.0 ); + + /*cleanup changes for wb_vad_ivas_fx*/ + st->hNoiseEst->sign_dyn_lp = fixedToFloat( st->hNoiseEst->sign_dyn_lp_fx, 8 ); + st->flag_noisy_speech_snr = (Word16) st->flag_noisy_speech_snr_fx; + + st->lt_mean_NB = (float) st->lt_mean_NB_fx / ( 1 << 11 ); + st->lt_mean_WB = (float) st->lt_mean_WB_fx / ( 1 << 11 ); + st->lt_mean_SWB = (float) st->lt_mean_SWB_fx / ( 1 << 11 ); + + /*fixed to float for noise_est_down*/ + fixedToFloat_arrL( st->hNoiseEst->bckr_fx, st->hNoiseEst->bckr, Q_new + QSCALE, NB_BANDS ); + fixedToFloat_arrL( tmpN_fx, tmpN, Q_new + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_fx, tmpE, Q_new + QSCALE, 20 ); + st->hNoiseEst->Etot_v_h2 = fixedToFloat( st->hNoiseEst->Etot_v_h2_fx, 8 ); + + /*fixed to float for noise_est_down_fx concerned with fr_bands_LR*/ + IF( lr_vad_enabled && st->idchan == 0 ) + { + fixedToFloat_arrL( hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, hCPE->hFrontVad[0]->hNoiseEst->bckr, Q_bands0 + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, hCPE->hFrontVad[1]->hNoiseEst->bckr, Q_bands1 + QSCALE, NB_BANDS ); + fixedToFloat_arrL( tmpN_LR_fx[0], tmpN_LR[0], Q_bands0 + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_LR_fx[0], tmpE_LR[0], Q_bands0 + QSCALE, 20 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2 = fixedToFloat( hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx, 8 ); + fixedToFloat_arrL( tmpN_LR_fx[1], tmpN_LR[1], Q_bands1 + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_LR_fx[1], tmpE_LR[1], Q_bands1 + QSCALE, 20 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2 = fixedToFloat( hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx, 8 ); + // performing fix to float conversion of (corr_shift_fx) corr_shiftL = fix16_to_float( corr_shiftL_fx, 15 ); corr_shiftR = fix16_to_float( corr_shiftR_fx, 15 ); -#endif -#endif } +#endif *relE = Etot - st->lp_speech; #ifndef IVAS_FLOAT_FIXED corr_shift = correlation_shift( st->hNoiseEst->totalNoise ); #else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 corr_shift_fx; - // performing float to fix conversion of (totalNoise) - st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, 8 ); -#endif corr_shift_fx = correlation_shift_fx( st->hNoiseEst->totalNoise_fx ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // performing fix to float conversion of (corr_shift_fx) @@ -1810,17 +1831,132 @@ ivas_error pre_proc_front_ivas_fx( *----------------------------------------------------------------*/ if ( st->hFdCngEnc != NULL ) { +#ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->last_totalNoise_fx = float_to_fix16( st->last_totalNoise, Q8 ); + FOR( Word16 j = 0; j < TOTALNOISE_HIST_SIZE; j++ ) + { + st->totalNoise_increase_hist_fx[j] = float_to_fix16( st->totalNoise_increase_hist[j], Q8 ); + move16(); + } +#endif + resetFdCngEnc_fx( st ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 totalNoiseIncrease_fx = st->hNoiseEst->totalNoise_fx - st->last_totalNoise_fx; + st->last_totalNoise = fix16_to_float( st->last_totalNoise_fx, Q8 ); + IF( + ( totalNoiseIncrease_fx > 5 * 256 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) || + ( st->input_bwidth > st->last_input_bwidth ) || + ( st->last_core == AMR_WB_CORE ) ) + { + st->hFdCngEnc->hFdCngCom->init_old_flt = fix16_to_float( st->hFdCngEnc->hFdCngCom->init_old, Q15 ); + move16(); + } + + IF( totalNoiseIncrease_fx > 0 ) + { + IF( EQ_16( st->totalNoise_increase_len, TOTALNOISE_HIST_SIZE ) ) + { + FOR( Word16 ind = 0; i < TOTALNOISE_HIST_SIZE; ind++ ) + { + st->totalNoise_increase_hist[ind] = fix16_to_float( st->totalNoise_increase_hist_fx[ind + 1], Q8 ); + move16(); + } + } + ELSE + { + st->totalNoise_increase_hist[st->totalNoise_increase_len] = fix16_to_float( st->totalNoise_increase_hist_fx[st->totalNoise_increase_len], Q8 ); + move16(); + } + } +#endif +#else resetFdCngEnc( st ); +#endif if ( st->idchan == 0 || element_mode == IVAS_CPE_MDCT ) { if ( element_mode == IVAS_CPE_TD && lr_vad_enabled && band_energies_LR != NULL ) { - perform_noise_estimation_enc( band_energies_LR, enerBuffer, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 band_energies_LR_fx[2 * NB_BANDS] = { 0 }; /* energy in critical bands without minimum noise floor E_MIN */ + Word16 band_energies_LR_fx_exp; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 enerBuffer_fx_loc[CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word16 enerBuffer_fx_exp; + + Word16 q_band_energies_LR = Q_factor_arrL( band_energies_LR, 2 * NB_BANDS ); + band_energies_LR_fx_exp = 31 - q_band_energies_LR; + floatToFixed_arrL( band_energies_LR, band_energies_LR_fx, ( 31 - band_energies_LR_fx_exp ), 2 * NB_BANDS ); + + Word16 q_enerBuffer = Q_factor_arrL( enerBuffer, CLDFB_NO_CHANNELS_MAX ); + enerBuffer_fx_exp = 31 - q_enerBuffer; + floatToFixed_arrL( enerBuffer, enerBuffer_fx_loc, ( 31 - enerBuffer_fx_exp ), CLDFB_NO_CHANNELS_MAX ); + + Word16 normmsPeriodog = Q_factor_arrL( st->hFdCngEnc->msPeriodog, NPART ); + st->hFdCngEnc->msPeriodog_fx_exp = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_cldfb = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_fft = 31 - normmsPeriodog; + floatToFixed_arrL( st->hFdCngEnc->msPeriodog, st->hFdCngEnc->msPeriodog_fx, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + + // not needed actuall its just output + Word16 normmsNoiseEst = Q_factor_arrL( st->hFdCngEnc->msNoiseEst, NPART ); + st->hFdCngEnc->msNoiseEst_fx_exp = 31 - normmsNoiseEst; + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_fx, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv_flt, st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv, 15, NPARTCLDFB ); +#endif + perform_noise_estimation_enc_ivas_fx( band_energies_LR_fx, band_energies_LR_fx_exp, enerBuffer_fx_loc, enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_fx, st->hFdCngEnc->msNoiseEst, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); +#endif } else { - perform_noise_estimation_enc( band_energies, enerBuffer, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 band_energies_fx[2 * NB_BANDS] = { 0 }; /* energy in critical bands without minimum noise floor E_MIN */ + Word16 band_energies_fx_exp; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 enerBuffer_fx_loc[CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word16 enerBuffer_fx_exp; + + Word16 q_band_energies = Q_factor_arrL( band_energies, 2 * NB_BANDS ); + band_energies_fx_exp = 31 - q_band_energies; + floatToFixed_arrL( band_energies, band_energies_fx, ( 31 - band_energies_fx_exp ), 2 * NB_BANDS ); + + + Word16 q_enerBuffer = Q_factor_arrL( enerBuffer, CLDFB_NO_CHANNELS_MAX ); + enerBuffer_fx_exp = 31 - q_enerBuffer; + floatToFixed_arrL( enerBuffer, enerBuffer_fx_loc, ( 31 - enerBuffer_fx_exp ), CLDFB_NO_CHANNELS_MAX ); + + Word16 normmsPeriodog = Q_factor_arrL( st->hFdCngEnc->msPeriodog, NPART ); + st->hFdCngEnc->msPeriodog_fx_exp = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_cldfb = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_fft = 31 - normmsPeriodog; + floatToFixed_arrL( st->hFdCngEnc->msPeriodog, st->hFdCngEnc->msPeriodog_fx, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + + // not needed actuall its just output + Word16 normmsNoiseEst = Q_factor_arrL( st->hFdCngEnc->msNoiseEst, NPART ); + st->hFdCngEnc->msNoiseEst_fx_exp = 31 - normmsNoiseEst; + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_fx, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv_flt, st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv, 15, NPARTCLDFB ); + + Word16 normmsperiodog = Q_factor_arrL( st->hFdCngEnc->hFdCngCom->periodog_flt, PERIODOGLEN ); + st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog = 31 - normmsperiodog; + // floatToFixed_arrL( st->hFdCngEnc->hFdCngCom->periodog_flt, st->hFdCngEnc->hFdCngCom->periodog, 31 - st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog, PERIODOGLEN); + floatToFixed_arr( st->hFdCngEnc->msPeriodogBuf, st->hFdCngEnc->msPeriodogBuf_fx, 9, MSBUFLEN * NPART ); + st->hFdCngEnc->hFdCngCom->init_old = (Word16) ( st->hFdCngEnc->hFdCngCom->init_old_flt * ( 1 << 9 ) ); + st->hFdCngEnc->hFdCngCom->scalingFactor = (Word16) ( st->hFdCngEnc->hFdCngCom->scalingFactor * ( 1 << 30 ) ); +#endif + + perform_noise_estimation_enc_ivas_fx( band_energies_fx, band_energies_fx_exp, enerBuffer_fx_loc, enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_fx, st->hFdCngEnc->msNoiseEst, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + fixedToFloat_arr( st->hFdCngEnc->msPeriodogBuf_fx, st->hFdCngEnc->msPeriodogBuf, 9, MSBUFLEN * NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + // fixedToFloat_arrL(st->hFdCngEnc->hFdCngCom->periodog, st->hFdCngEnc->hFdCngCom->periodog_flt, 31 - st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog, PERIODOGLEN); +#endif } } } @@ -1847,79 +1983,559 @@ ivas_error pre_proc_front_ivas_fx( hCPE->hStereoDft->expectedNumUpdates += st->hDtxEnc->max_SID; } - /*----------------------------------------------------------------* - * Adjust FD-CNG Noise Estimator - *----------------------------------------------------------------*/ + /*----------------------------------------------------------------* + * Adjust FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + + if ( st->hFdCngEnc != NULL && ( st->ini_frame == 0 || last_element_brate != element_brate || st->last_bwidth != st->bwidth ) ) + { + int32_t total_brate; + + total_brate = ( element_mode == IVAS_SCE ) ? st->total_brate : st->bits_frame_nominal * FRAMES_PER_SEC; + configureFdCngEnc( st->hFdCngEnc, max( st->input_bwidth, WB ), total_brate ); + configureFdCngEnc_ivas_fx( st->hFdCngEnc, max( st->input_bwidth, WB ), total_brate ); + if ( hCPE != NULL ) + { + st->hFdCngEnc->hFdCngCom->CngBitrate = hCPE->element_brate - 1; + } + } + + if ( st->hFdCngEnc != NULL && st->Opt_DTX_ON ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hFdCngEnc->msPeriodog_fx_exp = 31 - Q_factor_arrL( st->hFdCngEnc->msPeriodog, NPART ); + st->hFdCngEnc->msPeriodog_fx_exp_fft = st->hFdCngEnc->msPeriodog_fx_exp_cldfb = st->hFdCngEnc->msPeriodog_fx_exp; + st->hFdCngEnc->energy_ho_fx_exp = 31 - Q_factor_arrL( st->hFdCngEnc->energy_ho, NPART ); + st->hFdCngEnc->msNoiseEst_fx_exp = 31 - Q_factor_arrL( st->hFdCngEnc->msNoiseEst, NPART ); + st->hFdCngEnc->msNoiseEst_old_fx_exp = 31 - Q_factor_arrL( st->hFdCngEnc->msNoiseEst_old, NPART ); + floatToFixed_arrL( st->hFdCngEnc->msPeriodog, st->hFdCngEnc->msPeriodog_fx, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + floatToFixed_arrL( st->hFdCngEnc->energy_ho, st->hFdCngEnc->energy_ho_fx, 31 - st->hFdCngEnc->energy_ho_fx_exp, NPART ); + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_fx, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst_old, st->hFdCngEnc->msNoiseEst_old_fx, 31 - st->hFdCngEnc->msNoiseEst_old_fx_exp, NPART ); +#endif + + AdjustFirstSID_fx( st->hFdCngEnc->hFdCngCom->npart, st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog_fx_exp, st->hFdCngEnc->energy_ho_fx, + &st->hFdCngEnc->energy_ho_fx_exp, st->hFdCngEnc->msNoiseEst_fx, &st->hFdCngEnc->msNoiseEst_fx_exp, st->hFdCngEnc->msNoiseEst_old_fx, + &st->hFdCngEnc->msNoiseEst_old_fx_exp, &( st->hFdCngEnc->hFdCngCom->active_frame_counter ), st ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + fixedToFloat_arrL( st->hFdCngEnc->energy_ho_fx, st->hFdCngEnc->energy_ho, 31 - st->hFdCngEnc->energy_ho_fx_exp, NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_fx, st->hFdCngEnc->msNoiseEst, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_old_fx, st->hFdCngEnc->msNoiseEst_old, 31 - st->hFdCngEnc->msNoiseEst_old_fx_exp, NPART ); +#endif + } + + /*----------------------------------------------------------------* + * LP analysis + *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 *old_inp_12k8_loc_fx = (Word16 *) malloc( L_INP_12k8 * sizeof( Word16 * ) ); + Word16 *inp_12k8_loc_fx, *new_inp_12k8_loc_fx; /* pointers to current frame and new data */ + new_inp_12k8_loc_fx = old_inp_12k8_loc_fx + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + inp_12k8_loc_fx = new_inp_12k8_loc_fx - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ + Word16 lsp_new_loc_fx[M]; + Word16 lsp_mid_loc_fx[M]; + Word16 lsf_new_16_loc_fx[M]; + Word16 stab_fac_fx; + Word16 Q_new_loc; + Word16 Q_r[2] = { 0 }; + Word16 A_loc_fx[NB_SUBFR16k * ( M + 1 )] = { 0 }; + Word16 epsP_l_loc[M + 1]; + Word16 epsP_h_loc[M + 1]; + Word32 ener_fx; + Q_new_loc = Q_factor_arrL( old_inp_12k8, L_INP_12k8 ); + Q_new_loc = 0; /* Dynamic Q_new used above causes overflow issues */ + for ( int k = 0; k < L_INP_12k8; k++ ) + { + if ( fabs( old_inp_12k8[k] ) > 32768.0f ) + { + Q_new_loc = -1; + break; + } + } + for ( int idx = 0; idx < L_INP_12k8; idx++ ) + { + old_inp_12k8_loc_fx[idx] = (Word16) ( old_inp_12k8[idx] * ( 1 << Q_new_loc ) ); + } + for ( int idx = 0; idx < M; idx++ ) + { + lsp_new_loc_fx[idx] = (Word16) ( lsp_new[idx] * 32767 ); + st->lsp_old1_fx[idx] = (Word16) ( st->lsp_old1[idx] * 32767 ); + st->lsf_old1_fx[idx] = (Word16) ( st->lsf_old1[idx] * 2.56 ); + } + for ( int idx = 0; idx < 3; idx++ ) + { + st->voicing_fx[idx] = (Word16) ( st->voicing[idx] * 32767 ); + } +#endif + + alw_pitch_lag_12k8[0] = st->old_pitch_la; + move16(); + alw_pitch_lag_12k8[1] = st->old_pitch_la; + move16(); + alw_voicing_fx[0] = st->voicing_fx[2]; + move16(); + alw_voicing_fx[1] = st->voicing_fx[2]; + move16(); + + i = 0; + move16(); + + test(); + test(); + if ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 1 ) && EQ_16( hCPE->hStereoTD->tdm_low_rate_mode, 1 ) ) + { + i = 1; + move16(); + } + + analy_lp_fx( inp_12k8_loc_fx, L_FRAME, L_look, &ener_fx, A_loc_fx, epsP_h_loc, epsP_l_loc, lsp_new_loc_fx, lsp_mid_loc_fx, st->lsp_old1_fx, alw_pitch_lag_12k8, alw_voicing_fx, + INT_FS_12k8, i, Q_new_loc, Q_r ); + + lsp2lsf_fx( lsp_new_loc_fx, lsf_new_16_loc_fx, M, INT_FS_12k8 ); + + stab_fac_fx = lsf_stab_fx( lsf_new_16_loc_fx, st->lsf_old1_fx, 0, L_FRAME ); + + Copy( lsf_new_16_loc_fx, st->lsf_old1_fx, M ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + float power_2 = powf( 2.0, (float) ( Q_r[0] + 1 ) ); + float check_float; + for ( int idx = 0; idx < M + 1; idx++ ) + { + Word32 check = L_Comp( epsP_h_loc[idx], epsP_l_loc[idx] ); + check_float = (float) check / power_2; + epsP[idx] = check_float; + } + check_float = (float) ener_fx / power_2; + *ener = check_float; + + for ( int idx = 0; idx < M; idx++ ) + { + + lsp_new[idx] = (float) lsp_new_loc_fx[idx] / 32767.0f; + lsp_mid[idx] = (float) lsp_mid_loc_fx[idx] / 32767.0f; + st->lsp_old1[idx] = (float) ( (float) st->lsp_old1_fx[idx] / 32767.0f ); + st->lsf_old1[idx] = (float) ( (float) st->lsf_old1_fx[idx] / 2.56f ); + lsf_new[idx] = (float) ( (float) lsf_new_16_loc_fx[idx] / 2.56f ); + } + for ( int idx = 0; idx < NB_SUBFR16k * ( M + 1 ); idx++ ) + { + A[idx] = (float) ( (float) A_loc_fx[idx] / 16384.0f ); + } + + stab_fac = (float) ( (float) stab_fac_fx / 32767.0f ); +#endif + if ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) + { + /*----------------------------------------------------------------* + * Comparison of the LP coefficents to determine if it is possible + * to reuse the primary channel LP coefficients in the secondary channel + *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + Word32 isp_PCh_fx[M]; + Word32 isp_SCh_fx[M]; + Word16 A_SCh_fx[M + 1]; + Word16 A_PCh_fx[M + 1]; + Word32 speech_buff[L_FRAME + M]; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_speech = Q_factor_arrL( inp_12k8 - M, L_FRAME + M ); + Word16 gb1 = find_guarded_bits_fx( M ); + floatToFixed_arr32( inp_12k8 - M, speech_buff, Q_speech - gb1, L_FRAME + M ); + for ( i = 0; i < M + 1; i++ ) + { + A_PCh_fx[i] = (Word16) ( tdm_A_PCh[i] * ONE_IN_Q12 ); + A_SCh_fx[i] = (Word16) ( A[i] * ONE_IN_Q12 ); + } + + for ( i = 0; i < M; i++ ) + { + isp_PCh_fx[i] = (Word32) ( tdm_lsp_new_PCh[i] * MAX_32 ); + isp_SCh_fx[i] = (Word32) ( lsp_new[i] * MAX_32 ); + } +#endif + hCPE->hStereoTD->tdm_lp_reuse_flag = tdm_lp_comparison_fx( hCPE->hStereoTD, hCPE->hStereoClassif, st, &speech_buff[0], A_PCh_fx, A_SCh_fx, M, isp_PCh_fx, isp_SCh_fx, L_FRAME, element_brate - nb_bits_metadata * FRAMES_PER_SEC, Q_speech ); +#else + hCPE->hStereoTD->tdm_lp_reuse_flag = tdm_lp_comparison( hCPE->hStereoTD, hCPE->hStereoClassif, st, inp_12k8, tdm_A_PCh, A, M, tdm_lsp_new_PCh, lsp_new, L_FRAME, element_brate - nb_bits_metadata * FRAMES_PER_SEC ); + +#endif + } + + /*----------------------------------------------------------------* + * Compute weighted input (for OL pitch analysis) + * OL pitch analysis + * stable high pitch detection + * 1/4 pitch precision improvement + *----------------------------------------------------------------*/ + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )] = { 0 }; + Word16 buf[15000] = { 0 }; + Word16 *inp_12k8_fx1 = &buf[M]; // this is done because find_wsp accesses inp from -16 index + Word16 wsp_fx1[L_FRAME + L_LOOK_12k8] = { 0 }; + + floatToFixed_arr16( A, A_fx, Q12, NB_SUBFR16k * ( M + 1 ) ); + + Word16 e1, e2, q_inp_12k8; + f2me_buf_16( inp_12k8 - M, inp_12k8_fx1, &e1, 368 + M ); + f2me_buf_16( &st->mem_wsp, &st->mem_wsp_fx, &e2, 1 ); + q_inp_12k8 = sub( 15, s_max( e1, e2 ) ); + for ( i = -M; i < 368; i++ ) + { /* starting index from -16 */ + inp_12k8_fx1[i] = (Word16) floatToFixed( inp_12k8[i], q_inp_12k8 ); + } + st->mem_wsp_fx = (Word16) floatToFixed( st->mem_wsp, q_inp_12k8 ); +#endif + + ivas_find_wsp( L_FRAME, L_SUBFR, NB_SUBFR, A_fx, Aw_fx, inp_12k8_fx1, TILT_FAC_FX, wsp_fx1, &st->mem_wsp_fx, GAMMA1, L_LOOK_12k8 ); + + IF( EQ_16( st->vad_flag, 0 ) ) + { + /* reset the OL pitch tracker memories during inactive frames */ + pitch_ol_init_fx( &st->old_thres_fx, &st->old_pitch, &st->delta_pit, &st->old_corr_fx ); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < ( NB_SUBFR16k - 1 ); i++ ) + { + FOR( int j = 0; j < M + 1; j++ ) + { + Aw[i * ( M + 1 ) + j] = (float) Aw_fx[i * ( M + 1 ) + j] / Aw_fx[i * ( M + 1 )]; + } + } + FOR( i = 0; i < L_FRAME + L_LOOK_12k8; i++ ) + { + wsp[i] = fixedToFloat( wsp_fx1[i], q_inp_12k8 ); + } + st->mem_wsp = fixedToFloat( st->mem_wsp_fx, q_inp_12k8 ); + + IF( EQ_16( st->vad_flag, 0 ) ) + { + st->old_thres = (float) ( st->old_thres_fx ); // no Q-factor used here since it's initialised to 0. + st->old_corr = (float) ( st->old_corr_fx ); // no Q-factor used here since it's initialised to 0. + } +#endif + +#else + find_wsp( L_FRAME, L_SUBFR, NB_SUBFR, A, Aw, inp_12k8, TILT_FAC, wsp, &st->mem_wsp, GAMMA1_FLT, L_look ); + + if ( st->vad_flag == 0 ) + { + /* reset the OL pitch tracker memories during inactive frames */ + pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); + } +#endif + + old_pitch1 = st->pitch[1]; + + +#ifdef IVAS_FLOAT_FIXED + Word16 exp_wsp = 0, Q_wsp = 0; + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( st->old_wsp, st->old_wsp_fx, Q_factor_arr( st->old_wsp, L_WSP_MEM ), L_WSP_MEM ); + Copy( st->old_wsp_fx, old_wsp_fx, L_WSP_MEM ); + wsp_fx = old_wsp_fx + L_WSP_MEM; + st->old_thres_fx = (Word16) floatToFixed( st->old_thres, Q15 ); + st->old_corr_fx = (Word16) floatToFixed( st->old_corr, Q15 ); + floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); + corr_shift_fx = (Word16) floatToFixed( corr_shift, Q15 ); + f2me_buf_16( wsp, wsp_fx, &exp_wsp, L_WSP - L_WSP_MEM ); + Q_wsp = sub( 15, exp_wsp ); + + floatToFixed_arr( wsp, wsp_fx, Q_wsp, L_WSP - L_WSP_MEM ); + floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q_wsp, 115 ); + floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q_wsp, 3 ); + relE_fx = (Word16) floatToFixed( *relE, Q8 ); +#endif + + pitch_ol_ivas_fx( st->pitch, st->voicing_fx, &st->old_pitch, &st->old_corr_fx, corr_shift_fx, &st->old_thres_fx, + &st->delta_pit, st->old_wsp2_fx, wsp_fx, st->mem_decim2_fx, relE_fx, st->clas, st->input_bwidth, st->Opt_SC_VBR ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->old_thres = fixedToFloat( st->old_thres_fx, Q15 ); + st->old_corr = fixedToFloat( st->old_corr_fx, Q15 ); + fixedToFloat_arr( st->voicing_fx, st->voicing, Q15, 3 ); + corr_shift = fixedToFloat( corr_shift_fx, Q15 ); + fixedToFloat_arr( st->old_wsp2_fx, st->old_wsp2, Q_wsp, 115 ); + fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q_wsp, 3 ); + *relE = fixedToFloat( relE_fx, Q8 ); +#endif + +#else + pitch_ol( st->pitch, st->voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, *relE, L_look, st->clas, st->input_bwidth, st->Opt_SC_VBR ); +#endif + /* Updates for adaptive lag window memory */ + st->old_pitch_la = st->pitch[2]; + +#ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 q_wsp = Q_factor_arr( old_wsp, L_WSP ) - 3; + floatToFixed_arr16( old_wsp, old_wsp_fx, q_wsp, L_WSP ); + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + st->voicing_sm_fx = float_to_fix16( st->voicing_sm, Q15 ); + st->voicing0_sm_fx = float_to_fix16( st->voicing0_sm, Q15 ); + st->LF_EnergyRatio_sm_fx = float_to_fix16( st->LF_EnergyRatio_sm, Q7 ); + st->diff_sm_fx = float_to_fix( st->diff_sm, Q7 ); + st->energy_sm_fx = float_to_fix( st->energy_sm, Q7 ); + + floatToFixed_arr16( st->Bin_E, st->lgBin_E_fx, Q7, L_FFT / 2 ); // Function StableHighPitchDetect_fx excepts st->lgBin_E_fx to be in Q7 + + corr_shift_fx = float_to_fix16( corr_shift, Q15 ); + corr_shiftL_fx = float_to_fix16( corr_shiftL, Q15 ); + corr_shiftR_fx = float_to_fix16( corr_shiftR, Q15 ); + + if ( (Word32) st->bckr_tilt_lt_flt == 32768 ) + { + st->bckr_tilt_lt = MAX_32; // Q16 + } + else + { + st->bckr_tilt_lt = float_to_fix( st->bckr_tilt_lt_flt, Q16 ); + } + + Word16 q_fr_bands = Q30; + q_fr_bands = min( q_fr_bands, Q_factor_arrL( tmpN, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( tmpE, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( fr_bands, 2 * NB_BANDS ) - 4 /* needs 4 gaurd bits for summation */ ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( st->hNoiseEst->bckr, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( st->hNoiseEst->fr_bands1, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( st->hNoiseEst->fr_bands2, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( st->hNoiseEst->ave_enr, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( st->hNoiseEst->ave_enr2, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( lf_E, 2 * VOIC_BINS ) + 2 ); + + if ( lr_vad_enabled && st->idchan == 0 ) + { + for ( int j = 0; j < 2; j++ ) + { + q_fr_bands = min( q_fr_bands, Q_factor_arrL( lf_E_LR[j], 2 * VOIC_BINS ) + 2 ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( tmpN_LR[j], NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( tmpE_LR[j], NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( fr_bands_LR[j], 2 * NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( hCPE->hFrontVad[j]->hNoiseEst->bckr, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( hCPE->hFrontVad[j]->hNoiseEst->fr_bands1, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( hCPE->hFrontVad[j]->hNoiseEst->fr_bands2, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( hCPE->hFrontVad[j]->hNoiseEst->ave_enr, NB_BANDS ) ); + q_fr_bands = min( q_fr_bands, Q_factor_arrL( hCPE->hFrontVad[j]->hNoiseEst->ave_enr2, NB_BANDS ) ); + } + + for ( int j = 0; j < 2; j++ ) + { + floatToFixed_arr32( fr_bands_LR[j], fr_bands_LR_fx[j], q_fr_bands, 2 * NB_BANDS ); + floatToFixed_arr32( hCPE->hFrontVad[j]->hNoiseEst->bckr, hCPE->hFrontVad[j]->hNoiseEst->bckr_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( hCPE->hFrontVad[j]->hNoiseEst->fr_bands1, hCPE->hFrontVad[j]->hNoiseEst->fr_bands1_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( hCPE->hFrontVad[j]->hNoiseEst->fr_bands2, hCPE->hFrontVad[j]->hNoiseEst->fr_bands2_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( hCPE->hFrontVad[j]->hNoiseEst->ave_enr, hCPE->hFrontVad[j]->hNoiseEst->ave_enr_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( hCPE->hFrontVad[j]->hNoiseEst->ave_enr2, hCPE->hFrontVad[j]->hNoiseEst->ave_enr2_fx, q_fr_bands, NB_BANDS ); + for ( int k = 0; k < NB_BANDS; k++ ) + { + hCPE->hFrontVad[j]->hNoiseEst->fr_bands1_fx[k] = max( 1, hCPE->hFrontVad[j]->hNoiseEst->fr_bands1_fx[k] ); + hCPE->hFrontVad[j]->hNoiseEst->fr_bands2_fx[k] = max( 1, hCPE->hFrontVad[j]->hNoiseEst->fr_bands2_fx[k] ); + } + floatToFixed_arr32( tmpN_LR[j], tmpN_LR_fx[j], q_fr_bands, NB_BANDS ); + floatToFixed_arr32( tmpE_LR[j], tmpE_LR_fx[j], q_fr_bands, NB_BANDS ); + floatToFixed_arr32( lf_E_LR[j], lf_E_LR_fx[j], q_fr_bands - 2, 2 * VOIC_BINS ); + } + } + floatToFixed_arr32( tmpN, tmpN_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( tmpE, tmpE_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( lf_E, lf_E_fx, q_fr_bands - 2, 2 * VOIC_BINS ); + floatToFixed_arr32( st->hNoiseEst->bckr, st->hNoiseEst->bckr_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( st->hNoiseEst->fr_bands1, st->hNoiseEst->fr_bands1_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( st->hNoiseEst->fr_bands2, st->hNoiseEst->fr_bands2_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( st->hNoiseEst->ave_enr, st->hNoiseEst->ave_enr_fx, q_fr_bands, NB_BANDS ); + floatToFixed_arr32( st->hNoiseEst->ave_enr2, st->hNoiseEst->ave_enr2_fx, q_fr_bands, NB_BANDS ); + + for ( int k = 0; k < NB_BANDS; k++ ) + { + st->hNoiseEst->fr_bands1_fx[k] = max( 1, st->hNoiseEst->fr_bands1_fx[k] ); + st->hNoiseEst->fr_bands2_fx[k] = max( 1, st->hNoiseEst->fr_bands2_fx[k] ); + } + + floatToFixed_arr32( fr_bands, fr_bands_fx, q_fr_bands, 2 * NB_BANDS ); + + q_inp_12k8 = Q_factor_arr( old_inp_12k8, L_INP_12k8 ); // inp_12k8_fx + floatToFixed_arr16( old_inp_12k8, old_inp_12k8_fx, q_inp_12k8, L_INP_12k8 ); + + Word16 Etot16_fx = float_to_fix16( Etot, Q8 ); + relE_fx = float_to_fix16( *relE, Q8 ); + + Word16 Q_epsp = Q_factor_arrL( epsP, M + 1 ); + floatToFixed_arr32( epsP, epsP_fx, Q_epsp, M + 1 ); + FOR( Word16 j = 0; j <= M; j++ ) + { + L_Extract( epsP_fx[j], &epsP_h[j], &epsP_l[j] ); + } + + + floatToFixed_arr16( st->hSpMusClas->past_log_enr, st->hSpMusClas->past_log_enr_fx, Q8, NB_BANDS_SPMUS ); + + st->hNoiseEst->Etot_lp_fx = float_to_fix16( st->hNoiseEst->Etot_lp, Q8 ); + st->hNoiseEst->Etot_v_h2_fx = float_to_fix16( st->hNoiseEst->Etot_v_h2, Q8 ); + st->hNoiseEst->Etot_l_lp_fx = float_to_fix16( st->hNoiseEst->Etot_l_lp, Q8 ); + st->hNoiseEst->sign_dyn_lp_fx = float_to_fix16( st->hNoiseEst->sign_dyn_lp, Q8 ); + + if ( lr_vad_enabled && st->idchan == 0 ) + { + for ( int j = 0; j < 2; j++ ) + { + hCPE->hFrontVad[j]->hNoiseEst->Etot_lp_fx = float_to_fix16( hCPE->hFrontVad[j]->hNoiseEst->Etot_lp, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->Etot_v_h2_fx = float_to_fix16( hCPE->hFrontVad[j]->hNoiseEst->Etot_v_h2, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->Etot_l_lp_fx = float_to_fix16( hCPE->hFrontVad[j]->hNoiseEst->Etot_l_lp, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->sign_dyn_lp_fx = float_to_fix16( hCPE->hFrontVad[j]->hNoiseEst->sign_dyn_lp, Q8 ); + Etot_LR_fx[j] = float_to_fix16( Etot_LR[j], Q8 ); + } + } + + if ( st->hSC_VBR != NULL ) + { + st->hSC_VBR->vadnoise_fx = float_to_fix16( st->hSC_VBR->vadnoise, Q8 ); + } + st->lp_noise_fx = float_to_fix16( st->lp_noise, Q8 ); + st->hNoiseEst->Etot_last_fx = float_to_fix16( st->hNoiseEst->Etot_last, Q8 ); + + floatToFixed_arr32( st->old_enr_ssf, st->old_enr_ssf_fx, 0, 2 * NB_SSF ); + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + /* Detection of very short stable pitch period */ + StableHighPitchDetect_ivas_fx( &flag_spitch, st->pitch, st->voicing_fx, wsp_fx, st->localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, &st->LF_EnergyRatio_sm_fx, &st->predecision_flag, &st->diff_sm_fx, &st->energy_sm_fx, q_wsp, st->lgBin_E_fx ); + + /* 1/4 pitch precision improvement */ + IF( LE_32( element_brate, IVAS_32k ) ) + { + /* 1/4 pitch precision improvement */ + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[0], &pitch_fr_fx[0], &voicing_fr_fx[0], 0, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[0], &pitch_fr_fx[1], &voicing_fr_fx[1], L_SUBFR, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[1], &pitch_fr_fx[2], &voicing_fr_fx[2], 2 * L_SUBFR, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[1], &pitch_fr_fx[3], &voicing_fr_fx[3], 3 * L_SUBFR, wsp_fx, 7 ); + } + ELSE + { + pitch_fr_fx[0] = shl( st->pitch[0], 6 ); // Q6 + move16(); + pitch_fr_fx[1] = shl( st->pitch[0], 6 ); // Q6 + move16(); + pitch_fr_fx[2] = shl( st->pitch[1], 6 ); // Q6 + move16(); + pitch_fr_fx[3] = shl( st->pitch[1], 6 ); // Q6 + move16(); + + voicing_fr_fx[0] = st->voicing_fx[0]; // Q15 + move16(); + voicing_fr_fx[1] = st->voicing_fx[0]; // Q15 + move16(); + voicing_fr_fx[2] = st->voicing_fx[1]; // Q15 + move16(); + voicing_fr_fx[3] = st->voicing_fx[1]; // Q15 + move16(); + } + + /*------------------------------------------------------------------* + * Update estimated noise energy and voicing cut-off frequency + *-----------------------------------------------------------------*/ - if ( st->hFdCngEnc != NULL && ( st->ini_frame == 0 || last_element_brate != element_brate || st->last_bwidth != st->bwidth ) ) + noise_est_ivas_fx( st, old_pitch1, tmpN_fx, epsP_h, epsP_l, Etot16_fx, relE_fx, corr_shift_fx, tmpE_fx, fr_bands_fx, &cor_map_sum16_fx, &ncharX_fx, &sp_div16_fx, &q_sp_div, + &non_staX16_fx, loc_harm, lf_E_fx, &st->hNoiseEst->harm_cor_cnt, st->hNoiseEst->Etot_l_lp_fx, st->hNoiseEst->Etot_v_h2_fx, &st->hNoiseEst->bg_cnt, st->lgBin_E_fx, sub( q_fr_bands, QSCALE ), L_shl( E_MIN_IVAS_FX, sub( q_fr_bands, Q19 ) ), &dummy_fx, S_map_fx, hStereoClassif, NULL, st->ini_frame ); + + test(); + IF( lr_vad_enabled && st->idchan == 0 ) { - int32_t total_brate; + /* Run noise_est for Left and Right channel */ + *loc_harmLR_fx = *loc_harm; + noise_est_ivas_fx( st, old_pitch1, tmpN_LR_fx[0], epsP_h, epsP_l, Etot_LR_fx[0], sub( Etot_LR_fx[0], hCPE->hFrontVad[0]->lp_speech_fx ), corr_shiftL_fx, tmpE_LR_fx[0], fr_bands_LR_fx[0], &cor_map_sum_LR_fx[0], &ncharX_LR_fx, &sp_div_LR_fx, &q_sp_div_LR, + &non_staX_LR_fx, loc_harmLR_fx, lf_E_LR_fx[0], &hCPE->hFrontVad[0]->hNoiseEst->harm_cor_cnt, hCPE->hFrontVad[0]->hNoiseEst->Etot_l_lp_fx, hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx, &hCPE->hFrontVad[0]->hNoiseEst->bg_cnt, st->lgBin_E_fx, sub( q_fr_bands, QSCALE ), L_shl( E_MIN_IVAS_FX, sub( q_fr_bands, Q19 ) ), &dummy_fx, S_map_LR_fx, NULL, hCPE->hFrontVad[0], hCPE->hFrontVad[0]->ini_frame ); - total_brate = ( element_mode == IVAS_SCE ) ? st->total_brate : st->bits_frame_nominal * FRAMES_PER_SEC; - configureFdCngEnc( st->hFdCngEnc, max( st->input_bwidth, WB ), total_brate ); - if ( hCPE != NULL ) - { - st->hFdCngEnc->hFdCngCom->CngBitrate = hCPE->element_brate - 1; - } + /* Note: the index [0] in the last argument is intended, the ini_frame counter is only maintained in the zero-th channel's VAD handle */ + noise_est_ivas_fx( st, old_pitch1, tmpN_LR_fx[1], epsP_h, epsP_l, Etot_LR_fx[1], sub( Etot_LR_fx[1], hCPE->hFrontVad[1]->lp_speech_fx ), corr_shiftR_fx, tmpE_LR_fx[1], fr_bands_LR_fx[1], &cor_map_sum_LR_fx[1], &ncharX_LR_fx, &sp_div_LR_fx, &q_sp_div_LR, + &non_staX_LR_fx, loc_harmLR_fx, lf_E_LR_fx[1], &hCPE->hFrontVad[1]->hNoiseEst->harm_cor_cnt, hCPE->hFrontVad[1]->hNoiseEst->Etot_l_lp_fx, hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx, &hCPE->hFrontVad[1]->hNoiseEst->bg_cnt, st->lgBin_E_fx, sub( q_fr_bands, QSCALE ), L_shl( E_MIN_IVAS_FX, sub( q_fr_bands, Q19 ) ), &dummy_fx, S_map_LR_fx, NULL, hCPE->hFrontVad[1], hCPE->hFrontVad[0]->ini_frame ); } - if ( st->hFdCngEnc != NULL && st->Opt_DTX_ON ) + /*------------------------------------------------------------------* + * Update parameters used in the VAD and DTX + *-----------------------------------------------------------------*/ + vad_param_updt_fx( st, old_pitch1, corr_shift_fx, corr_shift_fx, A_fx, NULL, 1 ); + + IF( lr_vad_enabled && st->idchan == 0 ) { - AdjustFirstSID( st ); + vad_param_updt_fx( st, old_pitch1, corr_shiftL_fx, corr_shiftR_fx, A_fx, &hCPE->hFrontVad[0], CPE_CHANNELS ); } + /*-----------------------------------------------------------------* + * Find spectral tilt + * UC and VC frame selection + *-----------------------------------------------------------------*/ + find_tilt_ivas_fx( fr_bands_fx, st->hNoiseEst->bckr_fx, ee_fx, st->pitch, st->voicing_fx, lf_E_fx, corr_shift_fx, st->input_bwidth, st->max_band, hp_E_fx, MODE1, q_fr_bands, &( st->bckr_tilt_lt ), st->Opt_SC_VBR ); - /*----------------------------------------------------------------* - * LP analysis - *----------------------------------------------------------------*/ + st->coder_type = find_uv_ivas_fx( st, pitch_fr_fx, voicing_fr_fx, inp_12k8_fx, ee_fx, &dE1X_fx, corr_shift_fx, relE_fx, Etot16_fx, hp_E_fx, &flag_spitch, last_core_orig, hStereoClassif, q_inp_12k8, q_fr_bands ); - alw_pitch_lag_12k8[0] = st->old_pitch_la; - alw_pitch_lag_12k8[1] = st->old_pitch_la; - alw_voicing[0] = st->voicing[2]; - alw_voicing[1] = st->voicing[2]; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - i = 0; - if ( element_mode == IVAS_CPE_TD && st->idchan == 1 && hCPE->hStereoTD->tdm_low_rate_mode == 1 ) - { - i = 1; - } + st->diff_sm = fixedToFloat_32( st->diff_sm_fx, Q7 ); + st->energy_sm = fixedToFloat_32( st->energy_sm_fx, Q7 ); - analy_lp( inp_12k8, L_FRAME, L_look, ener, A, epsP, lsp_new, lsp_mid, st->lsp_old1, alw_pitch_lag_12k8, alw_voicing, INT_FS_12k8, i ); + st->voicing_sm = fixedToFloat_16( st->voicing_sm_fx, Q15 ); + st->voicing0_sm = fixedToFloat_16( st->voicing0_sm_fx, Q15 ); + st->LF_EnergyRatio_sm = fixedToFloat_16( st->LF_EnergyRatio_sm_fx, Q7 ); - lsp2lsf( lsp_new, lsf_new, M, INT_FS_12k8 ); - stab_fac = lsf_stab( lsf_new, st->lsf_old1, 0, L_FRAME ); - mvr2r( lsf_new, st->lsf_old1, M ); + fixedToFloat_arr( pitch_fr_fx, pitch_fr, Q6, NB_SUBFR ); + fixedToFloat_arr( voicing_fr_fx, voicing_fr, Q15, NB_SUBFR ); - if ( element_mode == IVAS_CPE_TD && st->idchan == 1 ) - { - /*----------------------------------------------------------------* - * Comparison of the LP coefficents to determine if it is possible - * to reuse the primary channel LP coefficients in the secondary channel - *----------------------------------------------------------------*/ + fixedToFloat_arrL32( ee_fx, ee, Q6, 2 ); + fixedToFloat_arrL32( hp_E_fx, hp_E, q_fr_bands, 2 ); + st->bckr_tilt_lt_flt = fixedToFloat_32( st->bckr_tilt_lt, Q16 ); - hCPE->hStereoTD->tdm_lp_reuse_flag = tdm_lp_comparison( hCPE->hStereoTD, hCPE->hStereoClassif, st, inp_12k8, tdm_A_PCh, A, M, tdm_lsp_new_PCh, lsp_new, L_FRAME, element_brate - nb_bits_metadata * FRAMES_PER_SEC ); - } + fixedToFloat_arrL32( st->old_enr_ssf_fx, st->old_enr_ssf, 0, 2 * NB_SSF ); - /*----------------------------------------------------------------* - * Compute weighted input (for OL pitch analysis) - * OL pitch analysis - * stable high pitch detection - * 1/4 pitch precision improvement - *----------------------------------------------------------------*/ + non_staX = fixedToFloat_16( non_staX16_fx, Q8 ); + sp_div = fixedToFloat_16( sp_div16_fx, q_sp_div ); + *cor_map_sum = fixedToFloat_16( cor_map_sum16_fx, Q8 ); - find_wsp( L_FRAME, L_SUBFR, NB_SUBFR, A, Aw, inp_12k8, TILT_FAC, wsp, &st->mem_wsp, GAMMA1_FLT, L_look ); + fixedToFloat_arr( S_map_fx, S_map, Q7, L_FFT / 2 ); + fixedToFloat_arr( st->lgBin_E_fx, st->Bin_E, Q7, L_FFT / 2 ); - if ( st->vad_flag == 0 ) + if ( lr_vad_enabled && st->idchan == 0 ) { - /* reset the OL pitch tracker memories during inactive frames */ - pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); + fixedToFloat_arr( cor_map_sum_LR_fx, cor_map_sum_LR, Q8, 2 ); + fixedToFloat_arr( S_map_LR_fx, S_map_LR, Q7, L_FFT / 2 ); + for ( int j = 0; j < 2; j++ ) + { + fixedToFloat_arrL32( hCPE->hFrontVad[j]->hNoiseEst->bckr_fx, hCPE->hFrontVad[j]->hNoiseEst->bckr, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( hCPE->hFrontVad[j]->hNoiseEst->fr_bands1_fx, hCPE->hFrontVad[j]->hNoiseEst->fr_bands1, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( hCPE->hFrontVad[j]->hNoiseEst->fr_bands2_fx, hCPE->hFrontVad[j]->hNoiseEst->fr_bands2, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( hCPE->hFrontVad[j]->hNoiseEst->ave_enr_fx, hCPE->hFrontVad[j]->hNoiseEst->ave_enr, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( hCPE->hFrontVad[j]->hNoiseEst->ave_enr2_fx, hCPE->hFrontVad[j]->hNoiseEst->ave_enr2, q_fr_bands, NB_BANDS ); + } } + fixedToFloat_arrL32( st->hNoiseEst->bckr_fx, st->hNoiseEst->bckr, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( st->hNoiseEst->fr_bands1_fx, st->hNoiseEst->fr_bands1, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( st->hNoiseEst->fr_bands2_fx, st->hNoiseEst->fr_bands2, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( st->hNoiseEst->ave_enr_fx, st->hNoiseEst->ave_enr, q_fr_bands, NB_BANDS ); + fixedToFloat_arrL32( st->hNoiseEst->ave_enr2_fx, st->hNoiseEst->ave_enr2, q_fr_bands, NB_BANDS ); - old_pitch1 = st->pitch[1]; + fixedToFloat_arr( st->hSpMusClas->past_log_enr_fx, st->hSpMusClas->past_log_enr, Q8, NB_BANDS_SPMUS ); - pitch_ol( st->pitch, st->voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, *relE, L_look, st->clas, st->input_bwidth, st->Opt_SC_VBR ); + st->hNoiseEst->Etot_lp = fixedToFloat_16( st->hNoiseEst->Etot_lp_fx, Q8 ); + st->hNoiseEst->Etot_v_h2 = fixedToFloat_16( st->hNoiseEst->Etot_v_h2_fx, Q8 ); + st->hNoiseEst->Etot_l_lp = fixedToFloat_16( st->hNoiseEst->Etot_l_lp_fx, Q8 ); + st->hNoiseEst->sign_dyn_lp = fixedToFloat_16( st->hNoiseEst->sign_dyn_lp_fx, Q8 ); + if ( lr_vad_enabled && st->idchan == 0 ) + { + for ( int j = 0; j < 2; j++ ) + { + hCPE->hFrontVad[j]->hNoiseEst->Etot_lp = fixedToFloat_16( hCPE->hFrontVad[j]->hNoiseEst->Etot_lp_fx, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->Etot_v_h2 = fixedToFloat_16( hCPE->hFrontVad[j]->hNoiseEst->Etot_v_h2_fx, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->Etot_l_lp = fixedToFloat_16( hCPE->hFrontVad[j]->hNoiseEst->Etot_l_lp_fx, Q8 ); + hCPE->hFrontVad[j]->hNoiseEst->sign_dyn_lp = fixedToFloat_16( hCPE->hFrontVad[j]->hNoiseEst->sign_dyn_lp_fx, Q8 ); + } + } - /* Updates for adaptive lag window memory */ - st->old_pitch_la = st->pitch[2]; +#endif +#else /* Detection of very short stable pitch period */ StableHighPitchDetect( &flag_spitch, st->pitch, st->voicing, st->Bin_E, wsp, st->localVAD, &st->voicing_sm, &st->voicing0_sm, &st->LF_EnergyRatio_sm, &st->predecision_flag, &st->diff_sm, &st->energy_sm ); @@ -1983,6 +2599,7 @@ ivas_error pre_proc_front_ivas_fx( find_tilt( fr_bands, st->hNoiseEst->bckr, ee, st->pitch, st->voicing, lf_E, corr_shift, st->input_bwidth, st->max_band, hp_E, MODE1, &( st->bckr_tilt_lt_flt ), st->Opt_SC_VBR ); st->coder_type = find_uv( st, pitch_fr, voicing_fr, inp_12k8, ee, &dE1X, corr_shift, *relE, Etot, hp_E, &flag_spitch, last_core_orig, hStereoClassif ); +#endif // IVAS_FLOAT_FIXED /*-----------------------------------------------------------------* * channel aware mode configuration * @@ -1996,7 +2613,27 @@ ivas_error pre_proc_front_ivas_fx( * TC frame selection *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 oi12k8_fx[L_INP_12k8]; + floatToFixed_arr( old_inp_12k8, oi12k8_fx, 0, L_INP_12k8 ); // Q_fac doesn't matter as it is only being used for sign + Word16 *ni12k8_fx = oi12k8_fx + L_INP_MEM; + inp_12k8_fx = ni12k8_fx - L_look; + floatToFixed_arrL( ee, ee_fx, Q6, 2 ); + relE_fx = float_to_fix16( *relE, Q8 ); + floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); + st->prev_fmerit = float_to_fix16( st->prev_fmerit_flt, Q15 ); +#endif + st->clas = signal_clas_fx( st, inp_12k8_fx, ee_fx, relE_fx, L_look, tdm_SM_last_clas ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->voicing_fx, st->voicing, Q15, 3 ); + st->prev_fmerit_flt = fix16_to_float( st->prev_fmerit, Q15 ); + st->fmerit_dt_flt = fix16_to_float( st->fmerit_dt, Q15 ); +#endif +#else st->clas = signal_clas( st, inp_12k8, ee, *relE, L_look, tdm_SM_last_clas ); +#endif #ifndef IVAS_FLOAT_FIXED select_TC( MODE1, st->tc_cnt, &st->coder_type, st->localVAD ); #else @@ -2010,17 +2647,87 @@ ivas_error pre_proc_front_ivas_fx( /*-----------------------------------------------------------------* * Collect stereo classifier features *-----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 cor_map_sum_e; + f2me( *cor_map_sum, &cor_map_sum_fx, &cor_map_sum_e ); +#endif if ( hStereoClassif != NULL ) { +#if 1 +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 non_staX_e, sp_div_e, epsP_e, max_e_Etot; + floatToFixed_arr32( lsf_new, lsf_new_fx, Q15, M ); + f2me_buf_16( st->voicing, st->voicing_fx, &st->voicing_e, 3 ); + f2me( non_staX, &non_staX_fx, &non_staX_e ); + f2me_buf( epsP, epsP_fx, &epsP_e, 17 ); + f2me( sp_div, &sp_div_fx, &sp_div_e ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + max_e_Etot = max( hStereoClassif->e_Etot_buf_fx, max( hStereoClassif->Etot_up_e, hStereoClassif->Etot_dn_e ) ); + scale_sig32( hStereoClassif->Etot_buf_fx, 3, hStereoClassif->e_Etot_buf_fx - max_e_Etot ); + hStereoClassif->Etot_up_fx = L_shr( hStereoClassif->Etot_up_fx, max_e_Etot - hStereoClassif->Etot_up_e ); + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, max_e_Etot - hStereoClassif->Etot_dn_e ); + hStereoClassif->Etot_up_e = hStereoClassif->Etot_dn_e = hStereoClassif->e_Etot_buf_fx = max_e_Etot; + stereo_classifier_features_ivas_fx( hStereoClassif, st->idchan, element_mode, localVAD_HE_SAD, lsf_new_fx, epsP_fx, + st->pitch, st->voicing_fx, cor_map_sum_fx, non_staX_fx, sp_div_fx, + st->clas, epsP_e, st->voicing_e, cor_map_sum_e, non_staX_e, sp_div_e ); + +#else stereo_classifier_features( hStereoClassif, st->idchan, element_mode, localVAD_HE_SAD, lsf_new, epsP, st->pitch, st->voicing, *cor_map_sum, non_staX, sp_div, st->clas ); +#endif // IVAS_FLOAT_FIXED } /*----------------------------------------------------------------* * 1st stage speech/music classification (GMM model) *----------------------------------------------------------------*/ +#if 0 smc_dec = ivas_smc_gmm( st, hStereoClassif, localVAD_HE_SAD, Etot, lsp_new, *cor_map_sum, epsP, PS, non_staX, *relE, &high_lpn_flag, flag_spitch ); +#else + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; +#if 1 + Word16 lsp_new_fx[M]; + Word32 PS_fx[128]; + Word16 Q_esp; + Word16 non_sta_fx = float_to_fix16( non_staX, Q6 ); + Word16 Etot_fx_0 = float_to_fix16( Etot, Q8 ); + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + hSpMusClas->wdlp_0_95_sp_32fx = float_to_fix( hSpMusClas->wdlp_0_95_sp, Q24 ); + hSpMusClas->wdlp_xtalk_fx = floatToFixed( hSpMusClas->wdlp_xtalk, Q19 ); + hSpMusClas->wrise_fx = float_to_fix16( hSpMusClas->wrise, 9 ); + relE_fx = float_to_fix16( *relE, 8 ); + floatToFixed_arr16( st->voicing, st->voicing_fx, 15, 3 ); + Word16 Qfact_PS = Q_factor_arrL( PS, 128 ); + floatToFixed_arr32( PS, PS_fx, Qfact_PS, 128 ); + Word16 e_esp; + f2me_buf( epsP, epsP_fx, &e_esp, M + 1 ); + Q_esp = sub( 31, e_esp ); + Word16 Qfact_PS_past = Q_factor_arrL( hSpMusClas->past_PS, 67 ); + floatToFixed_arr32( hSpMusClas->past_PS, hSpMusClas->past_PS_fx, Qfact_PS_past, 67 ); + hSpMusClas->dlp_var_LT_fx = float_to_fix( hSpMusClas->dlp_var_LT, Q19 ); + hSpMusClas->dlp_mean_LT_fx = float_to_fix( hSpMusClas->dlp_mean_LT, Q19 ); + hSpMusClas->dlp_mean_ST_fx = float_to_fix( hSpMusClas->dlp_mean_ST, Q19 ); + floatToFixed_arr32( hSpMusClas->past_dlp_mean_ST, hSpMusClas->past_dlp_mean_ST_fx, Q19, 7 ); + floatToFixed_arr32( hSpMusClas->prev_FV, hSpMusClas->prev_FV_fx, Q20, 15 ); + floatToFixed_arr32( hSpMusClas->FV_st, hSpMusClas->FV_st_fx, Q20, 15 ); +#endif + smc_dec = ivas_smc_gmm_fx( st, hStereoClassif, localVAD_HE_SAD, Etot_fx_0, lsp_new_fx, extract_l( L_shr( cor_map_sum_fx, sub( 23, cor_map_sum_e ) ) ) /*q8*/, epsP_fx, PS_fx, non_sta_fx, relE_fx, &high_lpn_flag, flag_spitch, Qfact_PS, Q_esp, Qfact_PS_past ); +#if 1 + fixedToFloat_arr( hSpMusClas->past_dlp_fx, hSpMusClas->past_dlp, Q9, HANG_LEN - 1 ); + hSpMusClas->lpm = fixedToFloat( hSpMusClas->lpm_fx, Q7 ); // Q7 + hSpMusClas->lps = fixedToFloat( hSpMusClas->lps_fx, Q7 ); // Q7 + hSpMusClas->wdrop = fixedToFloat( hSpMusClas->wdrop_fx, Q9 ); // Q8 + hSpMusClas->wrise = fixedToFloat( hSpMusClas->wrise_fx, Q9 ); // Q8 + hSpMusClas->wdlp_0_95_sp = fixedToFloat( hSpMusClas->wdlp_0_95_sp_32fx, Q24 ); + hSpMusClas->dlp_mean_LT = fixedToFloat_32( hSpMusClas->dlp_mean_LT_fx, Q19 ); + hSpMusClas->wdlp_xtalk = fixedToFloat( hSpMusClas->wdlp_xtalk_fx, Q19 ); + hSpMusClas->dlp_var_LT = fixedToFloat_32( hSpMusClas->dlp_var_LT_fx, Q19 ); + fixedToFloat_arrL32( hSpMusClas->past_PS_fx, hSpMusClas->past_PS, Qfact_PS_past, 67 ); + fixedToFloat_arrL32( hSpMusClas->FV_st_fx, hSpMusClas->FV_st, Q20, 15 ); + fixedToFloat_arrL32( hSpMusClas->prev_FV_fx, hSpMusClas->prev_FV, Q20, 15 ); + fixedToFloat_arrL32( hSpMusClas->past_dlp_mean_ST_fx, hSpMusClas->past_dlp_mean_ST, Q19, 7 ); + hSpMusClas->dlp_mean_ST = fixedToFloat( hSpMusClas->dlp_mean_ST_fx, Q19 ); +#endif +#endif /*----------------------------------------------------------------* @@ -2032,13 +2739,11 @@ ivas_error pre_proc_front_ivas_fx( long_enr( st, Etot, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); #else #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 Etot16_fx; // conv params from float to fix Etot_fx = float_to_fix( Etot, 8 ); Etot16_fx = extract_l( Etot_fx ); st->lp_speech_fx = float_to_fix16( st->lp_speech, 8 ); st->lp_noise_fx = float_to_fix16( st->lp_noise, 8 ); - st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, 8 ); st->hNoiseEst->Etot_last_fx = float_to_fix16( st->hNoiseEst->Etot_last, 8 ); #endif ivas_long_enr_fx( st, Etot16_fx, localVAD_HE_SAD, high_lpn_flag, NULL, 1, NULL, NULL ); @@ -2058,23 +2763,11 @@ ivas_error pre_proc_front_ivas_fx( #else #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // conv params from float to fix - Word16 Etot_LR_fx[2]; Etot_LR_fx[0] = float_to_fix16( Etot_LR[0], 8 ); Etot_LR_fx[1] = float_to_fix16( Etot_LR[1], 8 ); - hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); - hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); - hCPE->hFrontVad[0]->lp_speech_fx = float_to_fix16( hCPE->hFrontVad[0]->lp_speech, 8 ); - hCPE->hFrontVad[1]->lp_speech_fx = float_to_fix16( hCPE->hFrontVad[1]->lp_speech, 8 ); - hCPE->hFrontVad[0]->lp_noise_fx = float_to_fix16( hCPE->hFrontVad[0]->lp_noise, 8 ); - hCPE->hFrontVad[1]->lp_noise_fx = float_to_fix16( hCPE->hFrontVad[1]->lp_noise, 8 ); #endif ivas_long_enr_fx( st, -1, localVAD_HE_SAD, high_lpn_flag, hCPE->hFrontVad, CPE_CHANNELS, localVAD_HE_SAD_LR, Etot_LR_fx ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // conv params from fix to float - hCPE->hFrontVad[0]->lp_speech = fix16_to_float( hCPE->hFrontVad[0]->lp_speech_fx, 8 ); - hCPE->hFrontVad[1]->lp_speech = fix16_to_float( hCPE->hFrontVad[1]->lp_speech_fx, 8 ); - hCPE->hFrontVad[0]->lp_noise = fix16_to_float( hCPE->hFrontVad[0]->lp_noise_fx, 8 ); - hCPE->hFrontVad[1]->lp_noise = fix16_to_float( hCPE->hFrontVad[1]->lp_noise_fx, 8 ); hCPE->hFrontVad[0]->hNoiseEst->Etot_last = fix16_to_float( hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx, 8 ); hCPE->hFrontVad[1]->hNoiseEst->Etot_last = fix16_to_float( hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx, 8 ); @@ -2109,36 +2802,257 @@ ivas_error pre_proc_front_ivas_fx( { if ( ivas_format == SBA_FORMAT && st->core_brate != FRAME_NO_DATA && st->last_core_brate == FRAME_NO_DATA && st->sba_br_sw_while_no_data ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( ( NE_32( imult1616( st->last_bits_frame_nominal, FRAMES_PER_SEC ), st->total_brate ) ) || + ( NE_16( st->last_bwidth, st->bwidth ) ) || + ( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->element_mode, EVS_MONO ) ) || + ( ( NE_16( st->last_core, TCX_20_CORE ) && NE_16( st->last_core, TCX_10_CORE ) ) && GT_16( st->element_mode, EVS_MONO ) ) || + ( NE_16( st->rf_mode_last, st->rf_mode ) ) || + ( GT_16( st->element_mode, EVS_MONO ) && st->ini_frame == 0 ) ) + { + Word16 bSwitchFromAmrwbIO = 0, switchWB = 0, fscale; + Word32 sr_core; + move16(); + move16(); + + IF( EQ_16( st->last_core, AMR_WB_CORE ) ) + { + bSwitchFromAmrwbIO = 1; + move16(); + } + sr_core = getCoreSamplerateMode2( st->element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, st->is_ism_format ); + fscale = sr2fscale_fx( sr_core ); + IF( EQ_32( fscale, st->fscale ) && !bSwitchFromAmrwbIO && !switchWB ) + { + st->hTcxCfg->bandwidth_flt = getTcxBandwidth_flt( st->bwidth ); + } + IF( st->envWeighted && !st->enableTcxLpc ) + { + /* Unweight the envelope */ + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + st->gamma = (Word16) floatToFixed( st->gamma_flt, Q14 ); + } + } +#endif + + SetModeIndex_ivas_fx( st, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), element_mode, MCT_flag ); + + st->sba_br_sw_while_no_data = 0; + move16(); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( st->envWeighted && !st->enableTcxLpc ) + { + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + fixedToFloat_arr( st->lsf_old_fx, st->lsf_old, Q15, M ); + } +#endif +#else SetModeIndex( st, st->bits_frame_nominal * FRAMES_PER_SEC, element_mode, MCT_flag ); + st->sba_br_sw_while_no_data = 0; +#endif // IVAS_FLOAT_FIXED } else if ( ivas_format == SBA_FORMAT && st->core_brate == FRAME_NO_DATA && element_brate != last_element_brate ) { st->sba_br_sw_while_no_data = 1; } +/* these are for ivas_acelp_tcx20_switching_fx */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 lsp_mid_fx_1[M]; + Word32 res_cod_SNR_M_fx[STEREO_DFT_BAND_MAX]; + Word16 res_cod_SNR_M_fx_e[STEREO_DFT_BAND_MAX]; + Word16 tcx_mdct_window_fx[L_LOOK_16k]; + // Word16 stab_fac_fx; + float tmp = currFlatness * ONE_IN_Q7; + Word16 wsp_fx_temp[L_WSP]; + Word16 *wsp_fx_l; + non_staX16_fx = float_to_fix16( non_staX, Q8 ); + // currFlatness_fx = float_to_fix16_thrld( currFlatness, Q7 ); + if ( tmp > MAX_16 ) + { + currFlatness_fx = MAX_16; + } + else if ( tmp < MIN_16 ) + { + currFlatness_fx = MIN_16; + } + else + currFlatness_fx = (Word16) tmp; + stab_fac_fx = float_to_fix16( stab_fac, Q15 ); + if ( flag_16k_smc ) + floatToFixed_arr16( st->hTcxCfg->tcx_mdct_window_flt, tcx_mdct_window_fx, Q15, L_LOOK_16k ); + else + floatToFixed_arr16( st->hTcxCfg->tcx_mdct_window_flt, tcx_mdct_window_fx, Q15, L_LOOK_12k8 ); + floatToFixed_arr( pitch_fr, pitch_fr_fx, Q6, NB_SUBFR ); + floatToFixed_arr( voicing_fr, voicing_fr_fx, Q15, NB_SUBFR ); + floatToFixed_arrL( st->hTcxEnc->spectrum_long, st->hTcxEnc->spectrum_long_fx, Q15, N_MAX ); +#endif if ( flag_16k_smc ) { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 lsp_mid_fx[M]; + + floatToFixed_arr16( Aw, Aw_fx, Q12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr16( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr16( lsp_mid, lsp_mid_fx, Q15, M ); +#endif + /* Compute core-coder buffers at internal sampling rate */ - error = ivas_compute_core_buffers( st, NULL, old_inp_16k, NULL, input_frame, IVAS_SCE /*last_element_mode*/, INT_FS_16k /*sr_core_tmp*/, ener, A, Aw, epsP, lsp_new, lsp_mid ); + error = ivas_compute_core_buffers( st, NULL, old_inp_16k, NULL, input_frame, IVAS_SCE /*last_element_mode*/, INT_FS_16k /*sr_core_tmp*/, ener, +#ifndef IVAS_FLOAT_FIXED + A, Aw, +#else + A_fx, Aw_fx, +#endif + epsP, +#ifndef IVAS_FLOAT_FIXED + lsp_new, lsp_mid +#else + lsp_new_fx, lsp_mid_fx +#endif + ); if ( error != IVAS_ERR_OK ) { return error; } - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( Aw_fx, Aw, Q12, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); +#endif +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_speech_enc; + floatToFixed_arr16( lsp_mid, lsp_mid_fx_1, Q15, M ); + q_speech_enc = s_min( Q_factor_arr( st->speech_enc_flt - 560, 2 * 560 ), Q_factor_arr( st->wspeech_enc_flt - 560, 2 * 560 ) ); + floatToFixed_arr( st->speech_enc_flt - 560, st->speech_enc - 560, q_speech_enc, 2 * 560 ); + floatToFixed_arr( st->wspeech_enc_flt - 560, st->wspeech_enc - 560, q_speech_enc, 2 * 560 ); +#endif + smc_dec = ivas_acelp_tcx20_switching_fx( st, st->speech_enc, q_speech_enc, st->wspeech_enc, non_staX16_fx, pitch_fr_fx, voicing_fr_fx, currFlatness_fx, lsp_mid_fx_1, stab_fac_fx, res_cod_SNR_M_fx, res_cod_SNR_M_fx_e, tcx_mdct_window_fx, flag_16k_smc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < 7; i++ ) + { + res_cod_SNR_M[i] = me2f( res_cod_SNR_M_fx[i], res_cod_SNR_M_fx_e[i] ); + } + st->prevTempFlatness = fix16_to_float( st->prevTempFlatness_fx, Q7 ); +#endif +#else smc_dec = ivas_acelp_tcx20_switching( st, st->speech_enc_flt, st->wspeech_enc_flt, non_staX, pitch_fr, voicing_fr, currFlatness, lsp_mid, stab_fac, res_cod_SNR_M, flag_16k_smc ); +#endif } else { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#define ATT_SEG_LEN ( L_FRAME / ATT_NSEG ) + // Q_new = s_min(Q_factor_arr( inp_12k8, ATT_NSEG * ATT_SEG_LEN ), Q_factor_arr( st->Bin_E, 256 )) - 1; + Q_new = 0; /* Dynamic Q_new used above causes overflow issues */ + for ( int k = 0; k < ATT_NSEG * ATT_SEG_LEN; k++ ) + { + if ( fabs( inp_12k8[k] ) > 32768.0f ) + { + Q_new = -1; + break; + } + } + floatToFixed_arr16( lsp_mid, lsp_mid_fx_1, Q15, M ); + floatToFixed_arr( inp_12k8, inp_12k8_fx, Q_new, ATT_NSEG * ATT_SEG_LEN ); + floatToFixed_arr( wsp - L_WSP_MEM, wsp_fx_temp, Q_new, L_WSP_MEM ); + wsp_fx_l = wsp_fx_temp + L_WSP_MEM; + floatToFixed_arr( wsp, wsp_fx_l, Q_new, L_WSP - L_WSP_MEM ); +#endif + smc_dec = ivas_acelp_tcx20_switching_fx( st, inp_12k8_fx, Q_new, wsp_fx_l, non_staX16_fx, pitch_fr_fx, voicing_fr_fx, currFlatness_fx, lsp_mid_fx_1, stab_fac_fx, res_cod_SNR_M_fx, res_cod_SNR_M_fx_e, tcx_mdct_window_fx, flag_16k_smc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->prevTempFlatness = fix16_to_float( st->prevTempFlatness_fx, Q7 ); + // st->prevTempFlatness = currFlatness; + for ( i = 0; i < 7; i++ ) + { + res_cod_SNR_M[i] = me2f( res_cod_SNR_M_fx[i], res_cod_SNR_M_fx_e[i] ); + } +#endif +#else smc_dec = ivas_acelp_tcx20_switching( st, inp_12k8, wsp, non_staX, pitch_fr, voicing_fr, currFlatness, lsp_mid, stab_fac, res_cod_SNR_M, flag_16k_smc ); +#endif } } /* Switch to ACELP for non-harmonic transient signals */ else if ( ( ( element_mode >= IVAS_CPE_DFT && element_brate <= IVAS_16k4 ) || ( element_mode == IVAS_SCE && element_brate < SCE_SMC_THR ) ) && ( loc_harm[0] != 1 ) && smc_dec == MUSIC ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + Word16 q1 = Q_factor_arr( st->hTranDet->subblockEnergies.subblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY ); + Word16 q2 = Q_factor_arr( st->hTranDet->subblockEnergies.accSubblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + + st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg = float_to_fix16( st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt, Q15 ); + floatToFixed_arrL( st->hTranDet->subblockEnergies.subblockNrg_flt, st->hTranDet->subblockEnergies.subblockNrg, q1, NSUBBLOCKS + MAX_TD_DELAY ); + floatToFixed_arrL( st->hTranDet->subblockEnergies.accSubblockNrg_flt, st->hTranDet->subblockEnergies.accSubblockNrg, q2, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + st->hTranDet->subblockEnergies.subblockNrg_e = 31 - q1; + st->hTranDet->subblockEnergies.accSubblockNrg_e = 31 - q2; + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + Word16 q1 = Q_factor_arr( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY ); + Word16 q2 = Q_factor_arr( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + + hCPE->hCoreCoder[i]->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg = float_to_fix16( hCPE->hCoreCoder[i]->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt, Q15 ); + floatToFixed_arrL( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg_flt, hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg, q1, NSUBBLOCKS + MAX_TD_DELAY ); + floatToFixed_arrL( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg_flt, hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg, q2, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg_e = 31 - q1; + hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg_e = 31 - q2; + } + } + +#endif + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + if ( transient_analysis_ivas_fx( st->hTranDet, st->hNoiseEst->cor_map_fx, Q15, st->hNoiseEst->multi_harm_limit_fx, Q9 ) ) + { + smc_dec = SPEECH; + move16(); + } + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + test(); + if ( smc_dec != SPEECH && transient_analysis_ivas_fx( hCPE->hCoreCoder[i]->hTranDet, st->hNoiseEst->cor_map_fx, Q15, st->hNoiseEst->multi_harm_limit_fx, Q9 ) ) + { + smc_dec = SPEECH; /* overwrite initial music decision, initial SPEECH_MUSIC never changed */ + move16(); + } + } + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + fixedToFloat_arrL( st->hTranDet->subblockEnergies.subblockNrg, st->hTranDet->subblockEnergies.subblockNrg_flt, ( 31 - st->hTranDet->subblockEnergies.subblockNrg_e ), NSUBBLOCKS + MAX_TD_DELAY ); + fixedToFloat_arrL( st->hTranDet->subblockEnergies.accSubblockNrg, st->hTranDet->subblockEnergies.accSubblockNrg_flt, ( 31 - st->hTranDet->subblockEnergies.accSubblockNrg_e ), NSUBBLOCKS + MAX_TD_DELAY + 1 ); + st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt = fix16_to_float( st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg, Q15 ); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + fixedToFloat_arrL( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg, hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg_flt, ( 31 - hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.subblockNrg_e ), NSUBBLOCKS + MAX_TD_DELAY ); + fixedToFloat_arrL( hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg, hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg_flt, ( 31 - hCPE->hCoreCoder[i]->hTranDet->subblockEnergies.accSubblockNrg_e ), NSUBBLOCKS + MAX_TD_DELAY + 1 ); + hCPE->hCoreCoder[i]->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt = fix16_to_float( hCPE->hCoreCoder[i]->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg, Q15 ); + } + } +#endif +#else if ( element_mode == IVAS_SCE ) { if ( transient_analysis( st->hTranDet, st->hNoiseEst->cor_map, st->hNoiseEst->multi_harm_limit ) ) + { smc_dec = SPEECH; } @@ -2153,10 +3067,54 @@ ivas_error pre_proc_front_ivas_fx( } } } +#endif + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#define ATT_SEG_LEN ( L_FRAME / ATT_NSEG ) + relE_fx = float_to_fix16( *relE, Q8 ); + Etot16_fx = float_to_fix16( Etot, Q8 ); + // Q_new = s_min(Q_factor_arr( inp_12k8, ATT_NSEG * ATT_SEG_LEN ), Q_factor_arr( st->Bin_E, 256 )) - 1; + Q_new = 0; /* Dynamic Q_new used above causes overflow issues */ + for ( int k = 0; k < ATT_NSEG * ATT_SEG_LEN; k++ ) + { + if ( fabs( inp_12k8[k] ) > 32768.0f ) + { + Q_new = -1; + break; + } } + floatToFixed_arr( inp_12k8, inp_12k8_fx, Q_new, ATT_NSEG * ATT_SEG_LEN ); + floatToFixed_arrL( st->Bin_E, st->Bin_E_fx, Q_new + Q_SCALE - 2, TOD_NSPEC ); + floatToFixed_arrL( st->hSpMusClas->tod_lt_Bin_E, st->hSpMusClas->tod_lt_Bin_E_fx, Q_new + Q_SCALE - 2, TOD_NSPEC ); + floatToFixed_arr( S_map, S_map_fx, Q7, L_FFT / 2 ); + floatToFixed_arr( st->hSpMusClas->gsc_lt_diff_etot, st->hSpMusClas->gsc_lt_diff_etot_fx, Q8, MAX_LT ); + st->hSpMusClas->gsc_mem_etot_fx = float_to_fix16( st->hSpMusClas->gsc_mem_etot, Q8 ); + floatToFixed_arr( st->hSpMusClas->gsc_thres, st->hSpMusClas->gsc_thres_fx, Q11, 4 ); + st->old_corr_fx = float_to_fix16( st->old_corr, Q15 ); + floatToFixed_arrL( st->hSpMusClas->finc_prev, st->hSpMusClas->finc_prev_fx, 2 * Q_new, ATT_NSEG ); + st->hSpMusClas->lt_finc_fx = floatToFixed( st->hSpMusClas->lt_finc, 2 * Q_new ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, Q8 ); + st->hSpMusClas->wdlp_0_95_sp_fx = float_to_fix16( st->hSpMusClas->wdlp_0_95_sp, Q8 ); + st->hSpMusClas->mold_corr_fx = float_to_fix16( st->hSpMusClas->mold_corr, Q15 ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + /* 2nd stage speech/music classification (ACELP/GSC/TCX core selection) */ + ivas_smc_mode_selection_fx( st, element_brate, smc_dec, relE_fx, Etot16_fx, attack_flag, inp_12k8_fx, Q_new, S_map_fx, flag_spitch ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->hSpMusClas->gsc_lt_diff_etot_fx, st->hSpMusClas->gsc_lt_diff_etot, Q8, MAX_LT ); + st->hSpMusClas->gsc_mem_etot = fix16_to_float( st->hSpMusClas->gsc_mem_etot_fx, Q8 ); + fixedToFloat_arrL( st->hSpMusClas->finc_prev_fx, st->hSpMusClas->finc_prev, 2 * Q_new, ATT_NSEG ); + st->hSpMusClas->lt_finc = fixedToFloat( st->hSpMusClas->lt_finc_fx, 2 * Q_new ); + fixedToFloat_arrL( st->hSpMusClas->tod_lt_Bin_E_fx, st->hSpMusClas->tod_lt_Bin_E, Q_new + Q_SCALE - 2, TOD_NSPEC ); + st->hSpMusClas->mold_corr = fix16_to_float( st->hSpMusClas->mold_corr_fx, Q15 ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else /* 2nd stage speech/music classification (ACELP/GSC/TCX core selection) */ ivas_smc_mode_selection( st, element_brate, smc_dec, *relE, Etot, attack_flag, inp_12k8, S_map, flag_spitch ); +#endif // IVAS_FLOAT_FIXED } /*----------------------------------------------------------------* @@ -2175,10 +3133,13 @@ ivas_error pre_proc_front_ivas_fx( mvr2r( &old_inp_12k8[L_FRAME], st->old_inp_12k8, L_INP_MEM ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 tmp = norm_s( A_fx[0] ); + fixedToFloat_arr( A_fx, A, Q14 - tmp, NB_SUBFR16k * ( M + 1 ) ); +#endif + #ifdef IVAS_FLOAT_FIXED - free( signal_in_fx - ( input_Fs / 50 ) ); free( enerBuffer_fx ); - free( old_inp_12k8_fx ); free( old_inp_16k_fx ); free( mem_decim_dummy_fx ); free( temp1F_icatdmResampBuf_fx ); @@ -2256,24 +3217,25 @@ static void calculate_energy_buffer_fx( * * calculate DFT-based energies *--------------------------------------------------------------------*/ - -static void calculate_energy_buffer( - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - float enerBuffer_dft[], /* o : energy buffer */ - const int16_t no_channels, /* i : no. of used CLDFB channels */ - const int32_t input_Fs /* i : input sampling rate */ -) -{ #ifdef IVAS_FLOAT_FIXED - float *pDFT_DMX; // to be removed +static void calculate_energy_buffer_ivas_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word32 enerBuffer_dft_fx[], /* o : energy buffer() */ + const Word16 no_channels, /* i : no. of used CLDFB channels */ + const Word32 input_Fs, /* i : input sampling rate */ + Word16 *enerBuffer_dft_e ) +{ Word16 i, j; - Word64 enerBuffer_dft_fx[CLDFB_NO_CHANNELS_MAX]; // to be removed Word64 nrg_DMX_fx[CLDFB_NO_CHANNELS_MAX]; Word64 *p_nrg_DMX_fx; - Word32 *pDFT_DMX_fx; + Word32 *pDFT_DMX_fx; /*q_DFT_DMX_fx*/ Word32 chan_width_bins_fx; Word16 band_res_dft_fx, chan_width_f_fx, start, stop; + Word16 norm_nrg_DMX_fx; + Word64 max_abs_nrg_DMX_fx; + Flag overflow = 0; + max_abs_nrg_DMX_fx = 0; Word16 temp_q1 = norm_l( input_Fs ) - 1; Word16 temp_q2 = norm_s( hCPE->hStereoDft->NFFT ); @@ -2281,55 +3243,53 @@ static void calculate_energy_buffer( /* chan_width_f = 24000.f / CLDFB_NO_CHANNELS_MAX; */ chan_width_f_fx = 24000 / CLDFB_NO_CHANNELS_MAX; chan_width_bins_fx = L_shl( (Word32) div_s( chan_width_f_fx, band_res_dft_fx ), ( sub( temp_q1, temp_q2 ) ) ); // Q16 + set64_fx( nrg_DMX_fx, 0, CLDFB_NO_CHANNELS_MAX ); - pDFT_DMX = hCPE->hStereoDft->DFT[0]; // to be removed start = 1; - pDFT_DMX_fx = hCPE->hStereoDft->DFT_fx[0]; + pDFT_DMX_fx = hCPE->hStereoDft->DFT_fx[0]; /*q_DFT_DMX_fx = 31-hCPE->hStereoDft->DFT_fx_e[0]*/ p_nrg_DMX_fx = nrg_DMX_fx; - pDFT_DMX_fx[0] = (Word32) ( pDFT_DMX[0] * ONE_IN_Q11 ); - - FOR( i = 0; i < no_channels; i++ ) - { - stop = (Word16) ( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ) >> 1 ); - nrg_DMX_fx[i] = 0; - FOR( j = start; j < stop; j++ ) - { - pDFT_DMX_fx[2 * j] = (Word32) ( pDFT_DMX[2 * j] * ONE_IN_Q11 ); - pDFT_DMX_fx[2 * j + 1] = (Word32) ( pDFT_DMX[2 * j + 1] * ONE_IN_Q11 ); - } - start = stop; - } - start = 1; - - *p_nrg_DMX_fx = Mpy_32_32( pDFT_DMX_fx[0], pDFT_DMX_fx[0] ); + *p_nrg_DMX_fx = Mpy_32_32( pDFT_DMX_fx[0], pDFT_DMX_fx[0] ); /*2 * q_DFT_DMX_fx -31 */ FOR( i = 0; i < no_channels; i++ ) { - stop = (Word16) ( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ) >> 1 ); + stop = extract_l( L_shr( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ), 1 ) ); FOR( j = start; j < stop; j++ ) { - *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j], pDFT_DMX_fx[2 * j] ) ); + *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j], pDFT_DMX_fx[2 * j] ) ); /*2 * q_DFT_DMX_fx -31 */ *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j + 1], pDFT_DMX_fx[2 * j + 1] ) ); - // Q(-9) = Q11 + Q11 - Q31 + // 2 * DFT_fx_e } + if ( GT_64( W_abs( *p_nrg_DMX_fx ), max_abs_nrg_DMX_fx ) ) + max_abs_nrg_DMX_fx = W_abs( *p_nrg_DMX_fx ); start = stop; + move16(); p_nrg_DMX_fx++; } + norm_nrg_DMX_fx = W_norm( max_abs_nrg_DMX_fx ); FOR( i = 0; i < no_channels; i++ ) /* Consider only used channels, dependent on Fs */ { - enerBuffer_dft_fx[i] = nrg_DMX_fx[i] / 3; - enerBuffer_dft[i] = (float) enerBuffer_dft_fx[i] * ( 1 << 9 ); // Q(-9) adjustment, to be removed + enerBuffer_dft_fx[i] = W_extract_h( W_shl_o( nrg_DMX_fx[i], norm_nrg_DMX_fx, &overflow ) ) / 3; /*q_enerBuffer_dft_fx=2 * q_DFT_DMX_fx -31+ norm_nrg_DMX_fx -32*/ } + *enerBuffer_dft_e = sub( add( 32, shl( hCPE->hStereoDft->DFT_fx_e[0], 1 ) ), norm_nrg_DMX_fx ); /*31-q_enerBuffer_dft_fx*/ /* Set remaining entries of enerBuffer to zero */ FOR( ; i < CLDFB_NO_CHANNELS_MAX; i++ ) { - enerBuffer_dft[i] = 0.f; + enerBuffer_dft_fx[i] = 0; } + return; +} #else +static void calculate_energy_buffer( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + float enerBuffer_dft[], /* o : energy buffer */ + const int16_t no_channels, /* i : no. of used CLDFB channels */ + const int32_t input_Fs /* i : input sampling rate */ +) +{ int16_t i, j; float *pDFT_DMX, *p_nrg_DMX; float nrg_DMX[CLDFB_NO_CHANNELS_MAX]; @@ -2368,6 +3328,6 @@ static void calculate_energy_buffer( { enerBuffer_dft[i] = 0.f; } -#endif return; } +#endif diff --git a/lib_enc/ivas_corecoder_enc_reconfig.c b/lib_enc/ivas_corecoder_enc_reconfig.c index 1f7defcbc8472534cae9870220cb141b56a3f8c1..bb0125e113549e58994edf965d2feaaeb5542abd 100644 --- a/lib_enc/ivas_corecoder_enc_reconfig.c +++ b/lib_enc/ivas_corecoder_enc_reconfig.c @@ -34,15 +34,17 @@ #include "options.h" #include "ivas_cnst.h" #include "prot.h" +#include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot.h" #include "wmc_auto.h" - +#include "ivas_prot_fx.h" /*-------------------------------------------------------------------* * ivas_corecoder_enc_reconfig() * * Allocate, initialize, and configure SCE/CPE/MCT handles in case of bitrate switching *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_corecoder_enc_reconfig( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ const int16_t nSCE_old, /* i : number of SCEs in previous frame */ @@ -211,7 +213,7 @@ ivas_error ivas_corecoder_enc_reconfig( mvr2r( st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, input_buff[sce_id], len_inp_memory ); } - destroy_sce_enc( st_ivas->hSCE[sce_id], ( EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) && !st_ivas->hEncoderConfig->stereo_dmx_evs ) ); + destroy_sce_enc( st_ivas->hSCE[sce_id], EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) ); st_ivas->hSCE[sce_id] = NULL; } @@ -415,7 +417,7 @@ ivas_error ivas_corecoder_enc_reconfig( st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); - if ( ( error = IGF_Reconfig( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) + IF( ( error = IGF_Reconfig_fx( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) { return error; } @@ -481,14 +483,532 @@ ivas_error ivas_corecoder_enc_reconfig( st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; } -#ifndef IVAS_FLOAT_FIXED initMdctStereoEncData( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct, hEncoderConfig->ivas_format, st_ivas->hCPE[st_ivas->nCPE - 1]->element_mode, st_ivas->hCPE[st_ivas->nCPE - 1]->element_brate, hEncoderConfig->max_bwidth, 0, NULL, 1 ); + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->isSBAStereoMode = ( ( hEncoderConfig->ivas_format == SBA_FORMAT || hEncoderConfig->ivas_format == SBA_ISM_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); + } + } + + return error; +} #else +/* Some float operations are still pending */ +ivas_error ivas_corecoder_enc_reconfig_fx( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const Word16 nSCE_old, /* i : number of SCEs in previous frame */ + const Word16 nCPE_old, /* i : number of CPEs in previous frame */ + const Word16 nchan_transport_old, /* i : number of TCs in previous frame */ + const Word32 brate_SCE, /* i : bitrate to be set for the SCEs */ + const Word32 brate_CPE, /* i : bitrate to be set for the CPEs */ + const MC_MODE last_mc_mode /* i : switching between MC modes: last mode */ +) +{ + Word16 n, sce_id, cpe_id; + Word16 len_inp_memory, n_CoreCoder_existing, nSCE_existing, nCPE_existing; + float input_buff[MCT_MAX_BLOCKS][L_FRAME48k + NS2SA( 48000, IVAS_FB_ENC_DELAY_NS )]; + BSTR_ENC_HANDLE hBstr; + Word16 i, nb_bits; + Indice temp_ind_list[MAX_NUM_IND_TEMP_LIST]; + Word16 nb_bits_tot; + Word16 nchan_transport_real, nchan_transport_old_real; + ENCODER_CONFIG_HANDLE hEncoderConfig; + ivas_error error; + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + hEncoderConfig = st_ivas->hEncoderConfig; + error = IVAS_ERR_OK; + + len_inp_memory = idiv1616U( extract_l( L_shr( hEncoderConfig->input_Fs, 1 ) ), FRAMES_PER_SEC / 2 ); + IF( EQ_16( hEncoderConfig->ivas_format, SBA_FORMAT ) ) + { + len_inp_memory = add( len_inp_memory, NS2SA( hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ) ); + } + + nchan_transport_old_real = nchan_transport_old; + move16(); + nchan_transport_real = st_ivas->nchan_transport; + move16(); + + if ( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + nchan_transport_real = add( nchan_transport_real, st_ivas->hEncoderConfig->nchan_ism ); + } + + /*-----------------------------------------------------------------* + * Switching between SCE(s)/CPE(s)/MCT + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( EQ_16( nchan_transport_real, nchan_transport_old_real ) && EQ_16( st_ivas->nSCE, nSCE_old ) && EQ_16( st_ivas->nCPE, nCPE_old ) ) /* in McMASA, nchan_transport may be the same, but nSCE/nCPE differs */ + { + FOR( sce_id = 0; sce_id < st_ivas->nSCE; sce_id++ ) + { + copy_encoder_config_fx( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + move32(); + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + move32(); + } + + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + move32(); + + /* prepare bitstream buffers */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + copy_encoder_config_fx( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); + + Word16 tmp = 1; + move16(); + IF( GT_16( st_ivas->nCPE, 1 ) ) + { + tmp = 0; + move16(); + } + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = L_shr( st_ivas->hCPE[cpe_id]->element_brate, tmp ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + // st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + move32(); + } + } + + IF( GT_16( st_ivas->nCPE, 1 ) ) + { + IF( ( error = mct_enc_reconfigure( st_ivas, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + ELSE + { + + /* in SCE+CPE McMASA nchan_transport is still 2, fix the numbers */ + test(); + IF( EQ_16( hEncoderConfig->ivas_format, MC_FORMAT ) && EQ_16( last_mc_mode, MC_MODE_MCMASA ) ) + { + nchan_transport_old_real = add( nSCE_old, i_mult( CPE_CHANNELS, nCPE_old ) ); + } + + test(); + IF( EQ_16( hEncoderConfig->ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + nchan_transport_real = add( st_ivas->nSCE, i_mult( CPE_CHANNELS, st_ivas->nCPE ) ); + } + + /* something in transport changes */ + hBstr = NULL; + + /* get the index list pointers */ + IF( nSCE_old ) + { + hBstr = st_ivas->hSCE[0]->hCoreCoder[0]->hBstr; + } + ELSE IF( nCPE_old ) + { + hBstr = st_ivas->hCPE[0]->hCoreCoder[0]->hBstr; + } + + /* save bitstream information */ + nb_bits_tot = hBstr->nb_bits_tot; + move16(); + i = 0; + move16(); + nb_bits = 0; + move16(); + + test(); + WHILE( LT_16( nb_bits, nb_bits_tot ) && LT_16( i, MAX_NUM_IND_TEMP_LIST ) ) + { + IF( hBstr->ind_list[i].nb_bits > 0 ) + { + temp_ind_list[i].id = hBstr->ind_list[i].id; + move16(); + temp_ind_list[i].value = hBstr->ind_list[i].value; + move16(); + temp_ind_list[i].nb_bits = hBstr->ind_list[i].nb_bits; + move16(); + hBstr->ind_list[i].nb_bits = -1; + move16(); + } + + hBstr->nb_bits_tot = 0; + move16(); + hBstr->nb_ind_tot = 0; + move16(); + + nb_bits = add( nb_bits, temp_ind_list[i].nb_bits ); + i = add( i, 1 ); + test(); + } + + FOR( ; i < MAX_NUM_IND_TEMP_LIST; i++ ) + { + /* reset nb_bits of all other indices to -1 */ + temp_ind_list[i].nb_bits = -1; + move16(); + } + + test(); + test(); + IF( EQ_16( hEncoderConfig->ivas_format, MC_FORMAT ) && EQ_16( last_mc_mode, MC_MODE_MCMASA ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + /* within McMASA we can modify the transport signals when switching */ + /* copy earlier dmx buffers */ + IF( nSCE_old > 0 ) + { + set_zero( input_buff[0], len_inp_memory ); + mvr2r( st_ivas->hSCE[0]->hCoreCoder[0]->input_buff, input_buff[0], len_inp_memory ); + } + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + set_zero( input_buff[n + 1], len_inp_memory ); + IF( nCPE_old > 0 ) + { + mvr2r( st_ivas->hCPE[0]->hCoreCoder[n]->input_buff, input_buff[n + 1], len_inp_memory ); + } + } + + ivas_mcmasa_dmx_modify( len_inp_memory, input_buff, nSCE_old + CPE_CHANNELS * nCPE_old, st_ivas->nSCE + CPE_CHANNELS * st_ivas->nCPE ); + + n_CoreCoder_existing = 0; + move16(); + } + ELSE + { + n_CoreCoder_existing = s_min( nchan_transport_real, nchan_transport_old_real ); + } + + /* destroy superfluous core-coder elements */ + FOR( sce_id = st_ivas->nSCE; sce_id < nSCE_old; sce_id++ ) + { + /* save input audio buffers */ + IF( GT_16( n_CoreCoder_existing, sce_id ) ) + { + mvr2r( st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, input_buff[sce_id], len_inp_memory ); + } + + destroy_sce_enc( st_ivas->hSCE[sce_id], ( EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) && !st_ivas->hEncoderConfig->stereo_dmx_evs ) ); + st_ivas->hSCE[sce_id] = NULL; + } + + FOR( cpe_id = st_ivas->nCPE; cpe_id < nCPE_old; cpe_id++ ) + { + /* save input audio buffers */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + IF( n_CoreCoder_existing > cpe_id * CPE_CHANNELS + n ) + { + mvr2r( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->input_buff, input_buff[( cpe_id - st_ivas->nCPE ) * CPE_CHANNELS + n], len_inp_memory ); + } + } + + destroy_cpe_enc( st_ivas->hCPE[cpe_id] ); + st_ivas->hCPE[cpe_id] = NULL; + } + + test(); + IF( LE_16( st_ivas->nCPE, 1 ) && st_ivas->hMCT != NULL ) + { + ivas_mct_enc_close( &( st_ivas->hMCT ) ); + } + + /* special case, if we have MCT now and had a single CPE before, remove the MDCT Stereo handles */ + IF( GT_16( st_ivas->nCPE, 1 ) && EQ_16( nCPE_old, 1 ) ) + { + free( st_ivas->hCPE[0]->hStereoMdct ); + st_ivas->hCPE[0]->hStereoMdct = NULL; + } + + /* create missing core coder elements and set element bitrates for already existing ones */ + IF( st_ivas->nSCE > 0 ) + { + nSCE_existing = s_min( nSCE_old, st_ivas->nSCE ); + + FOR( sce_id = 0; sce_id < nSCE_existing; sce_id++ ) + { + copy_encoder_config_fx( st_ivas, st_ivas->hSCE[sce_id]->hCoreCoder[0], 0 ); + st_ivas->hSCE[sce_id]->element_brate = brate_SCE; + move32(); + st_ivas->hSCE[sce_id]->hCoreCoder[0]->total_brate = st_ivas->hSCE[sce_id]->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + move32(); + + ivas_destroy_MD_bstr_enc( &( st_ivas->hSCE[sce_id]->hMetaData ) ); + } + + FOR( sce_id = nSCE_existing; sce_id < st_ivas->nSCE; sce_id++ ) + { + IF( ( error = create_sce_enc_fx( st_ivas, sce_id, brate_SCE ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* propagate input audio buffers */ + test(); + IF( GT_16( n_CoreCoder_existing, sce_id ) && NE_16( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) + { + mvr2r( input_buff[sce_id], st_ivas->hSCE[sce_id]->hCoreCoder[0]->input_buff, len_inp_memory ); + } + + test(); + /* only reset indices if it is not the first index list, this already contains the IVAS format bits */ + IF( sce_id > 0 || EQ_16( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) + { + reset_indices_enc( st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr, st_ivas->hSCE[sce_id]->hCoreCoder[0]->hBstr->nb_ind_tot ); + } + } + + IF( st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData == NULL ) + { + IF( ( error = ivas_initialize_MD_bstr_enc( &( st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData ), st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + IF( st_ivas->nCPE > 0 ) + { + nCPE_existing = s_min( nCPE_old, st_ivas->nCPE ); + + FOR( cpe_id = 0; cpe_id < nCPE_existing; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = brate_CPE; + move32(); + + /* allocate buffer of indices */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + copy_encoder_config_fx( st_ivas, st_ivas->hCPE[cpe_id]->hCoreCoder[n], 0 ); + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->total_brate = st_ivas->hCPE[cpe_id]->element_brate / ( st_ivas->nCPE > 1 ? 1 : CPE_CHANNELS ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + move32(); + + test(); + test(); + test(); + test(); + IF( ( add( i_mult( cpe_id, CPE_CHANNELS ), n ) > 0 ) || + ( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) && st_ivas->nSCE > 0 ) || + ( EQ_16( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) && st_ivas->nSCE > 0 ) ) + { + reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_ind_tot ); + } + } + } + + FOR( cpe_id = nCPE_existing; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + test(); + IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) && st_ivas->hMcMasa->separateChannelEnabled ) + { + st_ivas->hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + move16(); + } + + IF( ( error = create_cpe_enc_fx( st_ivas, cpe_id, brate_CPE ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* propagate input audio buffers */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + IF( GT_16( n_CoreCoder_existing, add( i_mult( cpe_id, CPE_CHANNELS ), n ) ) ) + { + mvr2r( input_buff[n], st_ivas->hCPE[cpe_id]->hCoreCoder[n]->input_buff, len_inp_memory ); + } + } + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + /* only reset indices if it is not the first index list, this already contains the IVAS format bits */ + test(); + test(); + IF( add( i_mult( cpe_id, CPE_CHANNELS ), n ) > 0 || ( st_ivas->mc_mode == MC_MODE_MCMASA && st_ivas->nSCE > 0 ) ) + { + reset_indices_enc( st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr, st_ivas->hCPE[cpe_id]->hCoreCoder[n]->hBstr->nb_ind_tot ); + } + + IF( hEncoderConfig->Opt_DTX_ON ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->cng_sba_flag = 1; + move16(); + } + } + } + } + + /* restore bitstream - IVAS format bits should be written in the first core channel of the first SCE/CPE */ + i = 0; + move16(); + nb_bits = 0; + move16(); + IF( st_ivas->nSCE > 0 ) + { + test(); + WHILE( LT_16( nb_bits, nb_bits_tot ) && LT_16( i, MAX_NUM_IND_TEMP_LIST ) ) + { + IF( temp_ind_list[i].nb_bits > 0 ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->ind_list[i].id = temp_ind_list[i].id; + move16(); + st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->ind_list[i].value = temp_ind_list[i].value; + move16(); + st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->ind_list[i].nb_bits = temp_ind_list[i].nb_bits; + move16(); + } + + nb_bits = add( nb_bits, temp_ind_list[i].nb_bits ); + i = add( i, 1 ); + test(); + } + st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->nb_ind_tot = i; + move16(); + st_ivas->hSCE[0]->hCoreCoder[0]->hBstr->nb_bits_tot = nb_bits_tot; + move16(); + } + ELSE IF( st_ivas->nCPE > 0 ) + { + WHILE( LT_16( nb_bits, nb_bits_tot ) && LT_16( i, MAX_NUM_IND_TEMP_LIST ) ) + { + IF( temp_ind_list[i].nb_bits > 0 ) + { + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->ind_list[i].id = temp_ind_list[i].id; + move16(); + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->ind_list[i].value = temp_ind_list[i].value; + move16(); + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->ind_list[i].nb_bits = temp_ind_list[i].nb_bits; + move16(); + } + + nb_bits = add( nb_bits, temp_ind_list[i].nb_bits ); + i = add( i, 1 ); + } + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->nb_ind_tot = i; + move16(); + st_ivas->hCPE[0]->hCoreCoder[0]->hBstr->nb_bits_tot = nb_bits_tot; + move16(); + } + + + IF( EQ_16( last_mc_mode, MC_MODE_MCMASA ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + /* restore modified transport signal */ + IF( st_ivas->nSCE ) + { + mvr2r( input_buff[0], st_ivas->hSCE[0]->hCoreCoder[0]->input_buff, len_inp_memory ); + } + + IF( st_ivas->nCPE ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + mvr2r( input_buff[n + 1], st_ivas->hCPE[0]->hCoreCoder[n]->input_buff, len_inp_memory ); + } + } + } + + test(); + test(); + IF( GT_16( st_ivas->nCPE, 1 ) && LE_16( nCPE_old, 1 ) ) + { + IF( EQ_16( nCPE_old, 1 ) ) + { + /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handles for MCT */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + move32(); + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = extract_l( Mpy_32_32( st_ivas->hCPE[0]->element_brate, 42949673 ) /* 1/50 in Q31*/ ); + move16(); + st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent_fx( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); + move16(); + + IF( ( error = IGF_Reconfig( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + IF( ( error = create_mct_enc( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE IF( st_ivas->hMCT != NULL && GT_16( st_ivas->nCPE, 1 ) ) + { + IF( ( error = mct_enc_reconfigure( st_ivas, st_ivas->nchan_transport != nchan_transport_old ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* alllocate buffer for metadata indices */ + IF( st_ivas->nCPE > 0 ) + { + IF( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData == NULL ) + { + IF( ( error = ivas_initialize_MD_bstr_enc( &( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData ), st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + reset_indices_enc( st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData, st_ivas->hCPE[st_ivas->nCPE - 1]->hMetaData->nb_ind_tot ); + + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE - 1; cpe_id++ ) + { + ivas_destroy_MD_bstr_enc( &( st_ivas->hCPE[cpe_id]->hMetaData ) ); + } + } + + /* special case, if we have a single CPE and had MCT before we need to init the MDCT stereo handles here */ + test(); + IF( EQ_16( st_ivas->nCPE, 1 ) && GT_16( nCPE_old, 1 ) ) + { + IF( ( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } + + /* set correct nominal bitrates and igf config already here, needed for the correct init of the MDCT Stereo handle */ + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[0]->hCoreCoder[n]->total_brate = st_ivas->hCPE[0]->element_brate; + move32(); + st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal = extract_l( Mpy_32_32( st_ivas->hCPE[0]->element_brate, 42949673 ) ) /* 1/50 in Q31*/; // ( st_ivas->hCPE[0]->element_brate / FRAMES_PER_SEC ); + st_ivas->hCPE[0]->hCoreCoder[n]->igf = getIgfPresent( st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, + L_mult0( st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal, FRAMES_PER_SEC ), + st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, + st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); + move16(); + + IF( ( error = IGF_Reconfig( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* reset mct_chan_mode */ + st_ivas->hCPE[0]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + move16(); + } + initMdctStereoEncData_fx( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct, hEncoderConfig->ivas_format, st_ivas->hCPE[st_ivas->nCPE - 1]->element_mode, st_ivas->hCPE[st_ivas->nCPE - 1]->element_brate, hEncoderConfig->max_bwidth, 0, NULL, 1 ); -#endif - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->isSBAStereoMode = ( ( hEncoderConfig->ivas_format == SBA_FORMAT || hEncoderConfig->ivas_format == SBA_ISM_FORMAT ) && ( st_ivas->nchan_transport == 2 ) ); + + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->isSBAStereoMode = extract_l( ( EQ_16( hEncoderConfig->ivas_format, SBA_FORMAT ) || EQ_16( hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) ) && EQ_16( st_ivas->nchan_transport, 2 ) ); + move16(); } } return error; } +#endif diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 5167fe3f3bffcab1708f19f9ca08ccbed435c34c..91aaf3cc1b6c33e3db195032a434e3c9070516b7 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -48,15 +48,18 @@ #include "ivas_prot_fx.h" #include "prot_fx.h" #include "ivas_rom_enc.h" +#include "prot_fx_enc.h" #endif /*--------------------------------------------------------------------------* * Local function prototypes *--------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static void stereo_mode_combined_format_enc_fx( const Encoder_Struct *st_ivas, CPE_ENC_HANDLE hCPE ); +#else static void stereo_mode_combined_format_enc( const Encoder_Struct *st_ivas, CPE_ENC_HANDLE hCPE ); - +#endif /*-------------------------------------------------------------------* * ivas_cpe_enc() @@ -80,17 +83,25 @@ ivas_error ivas_cpe_enc( float old_inp_12k8[CPE_CHANNELS][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ float old_inp_16k[CPE_CHANNELS][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ #else - float old_inp_12k8[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ - float old_inp_16k[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ + float old_inp_12k8[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + float old_inp_16k[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ #endif #ifdef IVAS_FLOAT_FIXED - Word32 old_inp_12k8_fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ - Word32 old_inp_16k_fx[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ + Word32 old_inp_12k8_fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + Word16 old_inp_12k8_16fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + Word32 old_inp_16k_fx[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ + Word16 fft_buff_fx[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ + Word16 fft_exp; +#endif + float ener[CPE_CHANNELS]; /* residual energy from Levinson-Durbin */ + float relE[CPE_CHANNELS]; /* frame relative energy */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion + float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* A(z) unquantized for subframes */ + float Aw[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* weighted A(z) unquantized for subframes */ +#else + float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ + float Aw[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ #endif - float ener[CPE_CHANNELS]; /* residual energy from Levinson-Durbin */ - float relE[CPE_CHANNELS]; /* frame relative energy */ - float A[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ - float Aw[CPE_CHANNELS][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ float epsP[CPE_CHANNELS][M + 1]; /* LP prediction errors */ float lsp_new[CPE_CHANNELS][M]; /* LSPs at the end of the frame */ float lsp_mid[CPE_CHANNELS][M]; /* ISPs in the middle of the frame */ @@ -101,23 +112,31 @@ ivas_error ivas_cpe_enc( float old_wsp[CPE_CHANNELS][L_WSP]; /* old weighted input signal */ float pitch_fr[CPE_CHANNELS][NB_SUBFR]; /* fractional pitch values */ float voicing_fr[CPE_CHANNELS][NB_SUBFR]; /* fractional pitch gains */ + Word16 pitch_fr_fx[CPE_CHANNELS][NB_SUBFR]; /* Q6, fractional pitch values */ + Word16 voicing_fr_fx[CPE_CHANNELS][NB_SUBFR]; /* Q15, fractional pitch gains */ int16_t loc_harm[CPE_CHANNELS]; /* harmonicity flag */ float cor_map_sum[CPE_CHANNELS]; /* speech/music clasif. parameter */ int16_t vad_flag_dtx[CPE_CHANNELS]; /* HE-SAD flag with additional DTX HO */ float enerBuffer[CPE_CHANNELS][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ - float currFlatness[CPE_CHANNELS]; /* flatness parameter */ - float fft_buff[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ - int16_t tdm_ratio_idx, tdm_ratio_idx_SM; /* temp. TD stereo parameters */ - int16_t tdm_SM_or_LRTD_Pri; /* temp. TD stereo parameters */ - float tdm_last_ratio; /* temp. TD stereo parameters */ - int16_t nb_bits; /* number of DFT stereo side bits */ - float fr_bands[CPE_CHANNELS][2 * NB_BANDS]; /* energy in frequency bands */ - float Etot_LR[CPE_CHANNELS]; /* total energy */ - float lf_E[CPE_CHANNELS][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ - int16_t localVAD_HE_SAD[CPE_CHANNELS]; /* HE-SAD flag without hangover, LR channels */ - float band_energies_LR[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ + float currFlatness[CPE_CHANNELS] = { 0 }; /* flatness parameter */ +#ifdef IVAS_FLOAT_FIXED + Word16 currFlatness_fx[CPE_CHANNELS]; /* flatness parameter Q7 */ +#endif + float fft_buff[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ + int16_t tdm_ratio_idx, tdm_ratio_idx_SM; /* temp. TD stereo parameters */ + int16_t tdm_SM_or_LRTD_Pri; /* temp. TD stereo parameters */ +#ifndef IVAS_FLOAT_FIXED + float tdm_last_ratio; /* temp. TD stereo parameters */ +#endif + int16_t nb_bits; /* number of DFT stereo side bits */ + float fr_bands[CPE_CHANNELS][2 * NB_BANDS]; /* energy in frequency bands */ + float Etot_LR[CPE_CHANNELS]; /* total energy */ + float lf_E[CPE_CHANNELS][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + int16_t localVAD_HE_SAD[CPE_CHANNELS]; /* HE-SAD flag without hangover, LR channels */ + float band_energies_LR[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ float orig_input[CPE_CHANNELS][L_FRAME48k]; float Etot_last[CPE_CHANNELS]; + Word16 Etot_last_fx[CPE_CHANNELS]; int32_t tmp, input_Fs; int16_t max_bwidth, ivas_format; ENCODER_CONFIG_HANDLE hEncoderConfig; @@ -147,8 +166,12 @@ ivas_error ivas_cpe_enc( tdm_SM_or_LRTD_Pri = 0; tdm_ratio_idx = -1; tdm_ratio_idx_SM = -1; - tdm_last_ratio = 0; + // tdm_last_ratio = 0; + set16_fx( pitch_fr_fx[0], 0, NB_SUBFR ); + set16_fx( pitch_fr_fx[1], 0, NB_SUBFR ); + set16_fx( voicing_fr_fx[0], 0, NB_SUBFR ); + set16_fx( voicing_fr_fx[1], 0, NB_SUBFR ); /*------------------------------------------------------------------* * CPE initialization - core coder @@ -187,16 +210,133 @@ ivas_error ivas_cpe_enc( if ( sts[0]->ini_frame > 0 && st_ivas->hMCT == NULL ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hCPE->hCoreCoder[0]->hSpMusClas->past_dlp_fx[0] = float_to_fix16( hCPE->hCoreCoder[0]->hSpMusClas->past_dlp[0], Q9 ); + hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk_fx = floatToFixed( hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk, Q19 ); +#endif + + hCPE->element_mode = select_stereo_mode( hCPE, ivas_format ); +#else hCPE->element_mode = select_stereo_mode( hCPE, ivas_format ); +#endif } - +#ifdef IVAS_FLOAT_FIXED + stereo_mode_combined_format_enc_fx( st_ivas, hCPE ); +#else stereo_mode_combined_format_enc( st_ivas, hCPE ); +#endif +#ifdef IVAS_FLOAT_FIXED + Word16 Q_inp = 0; + move16(); + Word16 Q_buffer[2]; + Word32 band_energies_LR_fx[2 * NB_BANDS]; + Word16 Etot_LR_fx[CPE_CHANNELS]; + Word32 lf_E_fx[CPE_CHANNELS][2 * VOIC_BINS]; + Word32 fr_bands_fx[CPE_CHANNELS][2 * NB_BANDS]; + Word16 band_ener_guardbits = find_guarded_bits_fx( 2 * NB_BANDS ); + Word16 Q_add = 2; + move16(); + Word16 front_create_flag = 0; + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + sts[n]->lp_speech_fx = (Word16) floatToFixed( sts[n]->lp_speech, Q8 ); + sts[n]->lp_noise_fx = (Word16) floatToFixed( sts[n]->lp_noise, Q8 ); + sts[n]->flag_noisy_speech_snr_fx = (Word8) sts[n]->flag_noisy_speech_snr; + Q_buffer[n] = 15; + move16(); + } + if ( sts[0]->hFdCngEnc != NULL ) + { + sts[0]->last_totalNoise_fx = (Word16) float_to_fix16( sts[0]->last_totalNoise, Q8 ); + for ( int i = 0; i < TOTALNOISE_HIST_SIZE - 1; i++ ) + { + sts[0]->totalNoise_increase_hist_fx[n] = (Word16) float_to_fix16( sts[0]->totalNoise_increase_hist[n], Q8 ); + } + } + if ( hCPE->hFrontVad[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) + { + Word16 Qband = -1; + move16(); + Word16 Q_new_old = add( sub( Q_inp, Qband ), Q_add ); - 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 ) + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + + floatToFixed_arr( hCPE->hFrontVad[n]->mem_decim, hCPE->hFrontVad[n]->mem_decim_fx, Q_inp, 90 ); + hCPE->hFrontVad[n]->mem_preemph_fx = (Word16) floatToFixed( hCPE->hFrontVad[n]->mem_preemph, Q_inp - 1 ); + Q_buffer[n] = Q_factor_arr( hCPE->hFrontVad[n]->buffer_12k8 + L_FFT, L_FFT / 2 ); + floatToFixed_arr( hCPE->hFrontVad[n]->buffer_12k8, hCPE->hFrontVad[n]->buffer_12k8_fx, Q_buffer[n], 384 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_l_lp_32fx = (Word32) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_l_lp * 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_last_32fx = (Word32) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_last * 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2_32fx = (Word32) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2 * 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_lp_32fx = (Word32) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_lp * 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( hCPE->hFrontVad[n]->hNoiseEst->sign_dyn_lp * 16777216.0 ); + floatToFixed_arrL( hCPE->hFrontVad[n]->hNoiseEst->bckr, hCPE->hFrontVad[n]->hNoiseEst->bckr_fx, Q_new_old + QSCALE, 20 ); + floatToFixed_arrL( hCPE->hFrontVad[n]->hNoiseEst->enrO, hCPE->hFrontVad[n]->hNoiseEst->enrO_fx, Q_new_old + QSCALE, 20 ); + } + floatToFixed_arrL( &band_energies_LR[0], &band_energies_LR_fx[0], Q_new_old + QSCALE + 2, 40 ); + } +#endif + + if ( ( error = front_vad_fx( hCPE, NULL, hEncoderConfig, &hCPE->hFrontVad[0], st_ivas->hMCT != NULL, input_frame, vad_flag_dtx, fr_bands_fx, Etot_LR_fx, lf_E_fx, localVAD_HE_SAD, vad_hover_flag, band_energies_LR_fx, NULL, NULL, Q_inp, Q_buffer, Q_add, &front_create_flag ) ) != IVAS_ERR_OK ) { return error; } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( sts[0]->hFdCngEnc != NULL ) + { + sts[0]->last_totalNoise = fix16_to_float( sts[0]->last_totalNoise_fx, Q8 ); + for ( int i = 0; i < TOTALNOISE_HIST_SIZE - 1; i++ ) + { + sts[0]->totalNoise_increase_hist[n] = fix16_to_float( sts[0]->totalNoise_increase_hist_fx[n], Q8 ); + } + sts[0]->hFdCngEnc->hFdCngCom->init_old_flt = ( sts[0]->hFdCngEnc->hFdCngCom->init_old == 32767 ) ? FLT_MAX : sts[0]->hFdCngEnc->hFdCngCom->init_old_flt; + } + if ( hCPE->hFrontVad[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) + { + Word16 Qband = -1; + move16(); + Word16 Q_new_old = add( sub( Q_inp, Qband ), Q_add ); + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + fixedToFloat_arr( hCPE->hFrontVad[n]->mem_decim_fx, hCPE->hFrontVad[n]->mem_decim, Q_inp, 90 ); + hCPE->hFrontVad[n]->mem_preemph = fixedToFloat( hCPE->hFrontVad[n]->mem_preemph_fx, Q_inp + Qband ); + fixedToFloat_arr( hCPE->hFrontVad[n]->buffer_12k8_fx, hCPE->hFrontVad[n]->buffer_12k8, Q_buffer[n], 384 ); + fixedToFloat_arrL( fr_bands_fx[n], fr_bands[n], Q_buffer[n] + QSCALE + 2, 40 ); + fixedToFloat_arrL( lf_E_fx[n], lf_E[n], Q_buffer[n] + QSCALE, 148 ); + + Etot_LR[n] = fixedToFloat( Etot_LR_fx[n], Q8 ); + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->bckr_fx, hCPE->hFrontVad[n]->hNoiseEst->bckr, Q_new_old + QSCALE, 20 ); + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->enrO_fx, hCPE->hFrontVad[n]->hNoiseEst->enrO, Q_new_old + QSCALE, 20 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_l_lp = (float) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_last = (float) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_last_32fx / 16777216.0 ); + // hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2 = (float) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2_32fx / 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_lp = (float) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_lp_32fx / 16777216.0 ); + hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2 = (float) ( hCPE->hFrontVad[n]->hNoiseEst->Etot_v_h2_fx / ( 256.0 ) ); + hCPE->hFrontVad[n]->hNoiseEst->sign_dyn_lp = (float) ( hCPE->hFrontVad[n]->hNoiseEst->sign_dyn_lp_fx / ( 256.0 ) ); + if ( front_create_flag ) + { + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->fr_bands1_fx, hCPE->hFrontVad[n]->hNoiseEst->fr_bands1, Q17, NB_BANDS ); + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->fr_bands2_fx, hCPE->hFrontVad[n]->hNoiseEst->fr_bands2, Q17, NB_BANDS ); + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->ave_enr_fx, hCPE->hFrontVad[n]->hNoiseEst->ave_enr, Q8, NB_BANDS ); + fixedToFloat_arrL( hCPE->hFrontVad[n]->hNoiseEst->ave_enr2_fx, hCPE->hFrontVad[n]->hNoiseEst->ave_enr2, Q8, NB_BANDS ); + } + } + // fixedToFloat_arrL( band_energies_fx, band_energies, Q_new + QSCALE + 2, 40 ); + fixedToFloat_arrL( &band_energies_LR_fx[0], &band_energies_LR[0], Q_buffer[1] + QSCALE + 2 - band_ener_guardbits, 40 ); + } +#endif +#else + + 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; + } +#endif sts[0]->element_mode = hCPE->element_mode; sts[1]->element_mode = hCPE->element_mode; @@ -211,28 +351,76 @@ ivas_error ivas_cpe_enc( /*----------------------------------------------------------------* * dynamically allocate data structures depending on the actual stereo mode *----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + if ( ( error = stereo_memory_enc_fx( hCPE, input_Fs, max_bwidth, ivas_format, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = stereo_memory_enc( hCPE, input_Fs, max_bwidth, &tdm_last_ratio, ivas_format, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) { return error; } +#endif /*----------------------------------------------------------------* * Set TD stereo parameters *----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + Q_inp = min( Q_inp, Q_factor_arrL( sts[1]->input, input_frame ) ); + floatToFixed_arrL32( sts[1]->input, sts[1]->input32_fx, Q_inp, input_frame ); + if ( ( error = stereo_set_tdm_fx( hCPE, input_frame, Q_inp ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = stereo_set_tdm( hCPE, input_frame ) ) != IVAS_ERR_OK ) { return error; } +#endif /*----------------------------------------------------------------* * Resets/updates in case of stereo switching *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( sts[0]->old_input_signal, sts[0]->old_input_signal_fx, 0, input_frame ); + Word16 q_inp = Q15; + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + q_inp = min( q_inp, Q_factor_arr( sts[n]->input_buff, 1965 ) ); + } + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + floatToFixed_arr( sts[n]->input_buff, sts[n]->input_buff_fx, q_inp, 1965 ); + } +#endif - stereo_switching_enc( hCPE, sts[0]->old_input_signal, input_frame ); + stereo_switching_enc_fx( hCPE, sts[0]->old_input_signal_fx, input_frame, q_inp ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + if ( hCPE->element_mode > IVAS_CPE_DFT && hCPE->input_mem[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + fixedToFloat_arr( hCPE->input_mem_fx[n], hCPE->input_mem[n], q_inp, STEREO_DFT_OVL_MAX * input_frame / L_FRAME48k ); + } + } + + if ( hCPE->element_mode == IVAS_CPE_DFT ) + { + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + fixedToFloat_arr( sts[n]->input_buff_fx, sts[n]->input_buff, q_inp, 1965 ); + } + } +#endif +#else + stereo_switching_enc( hCPE, sts[0]->old_input_signal, input_frame ); +#endif /*----------------------------------------------------------------* * Temporal inter-channel alignment, stereo adjustment *----------------------------------------------------------------*/ @@ -267,15 +455,89 @@ ivas_error ivas_cpe_enc( if ( !( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC ) ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + sts[n]->hTranDet->subblockEnergies.firState1 = (Word16) floatToFixed( sts[n]->hTranDet->subblockEnergies.firState1_flt, -1 ); + sts[n]->hTranDet->subblockEnergies.firState2 = (Word16) floatToFixed( sts[n]->hTranDet->subblockEnergies.firState2_flt, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + sts[n]->hTranDet->subblockEnergies.accSubblockNrg[i] = floatToFixed( sts[n]->hTranDet->subblockEnergies.accSubblockNrg_flt[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + sts[n]->hTranDet->subblockEnergies.subblockNrg[i] = floatToFixed( sts[n]->hTranDet->subblockEnergies.subblockNrg_flt[i], 7 ); + sts[n]->hTranDet->subblockEnergies.subblockNrgChange[i] = (Word16) floatToFixed( sts[n]->hTranDet->subblockEnergies.subblockNrgChange_flt[i], 7 ); + } + + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + sts[n]->hTranDet->delayBuffer.buffer[i] = (Word16) floatToFixed( sts[n]->hTranDet->delayBuffer.buffer_flt[i], -1 ); + } + + sts[n]->hTranDet->transientDetector.attackRatioThreshold = (Word16) floatToFixed( sts[n]->hTranDet->transientDetector.attackRatioThreshold_flt, 11 ); + + floatToFixed_arr16( sts[n]->input, sts[n]->input_fx, -1, input_frame ); + + sts[n]->hTranDet->subblockEnergies.facAccSubblockNrg = float_to_fix16( sts[n]->hTranDet->subblockEnergies.facAccSubblockNrg_flt, 15 ); + +#endif + + RunTransientDetection_ivas_fx( sts[n]->input_fx, input_frame, sts[n]->hTranDet ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + sts[n]->hTranDet->subblockEnergies.firState1_flt = fixedToFloat( (Word32) sts[n]->hTranDet->subblockEnergies.firState1, -1 ); + sts[n]->hTranDet->subblockEnergies.firState2_flt = fixedToFloat( (Word32) sts[n]->hTranDet->subblockEnergies.firState2, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + sts[n]->hTranDet->subblockEnergies.subblockNrg_flt[i] = fixedToFloat( sts[n]->hTranDet->subblockEnergies.subblockNrg[i], 7 ); + sts[n]->hTranDet->subblockEnergies.subblockNrgChange_flt[i] = fixedToFloat( (Word32) sts[n]->hTranDet->subblockEnergies.subblockNrgChange[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + sts[n]->hTranDet->subblockEnergies.accSubblockNrg_flt[i] = fixedToFloat( sts[n]->hTranDet->subblockEnergies.accSubblockNrg[i], 7 ); + } + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + sts[n]->hTranDet->delayBuffer.buffer_flt[i] = fixedToFloat( (Word32) sts[n]->hTranDet->delayBuffer.buffer[i], -1 ); + } +#endif +#else RunTransientDetection( sts[n]->input, input_frame, sts[n]->hTranDet ); +#endif } +#ifndef IVAS_FLOAT_FIXED currFlatness[n] = GetTCXAvgTemporalFlatnessMeasure( sts[n]->hTranDet, NSUBBLOCKS, 0 ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( sts[n]->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, sts[n]->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, NSUBBLOCKS + MAX_TD_DELAY ); +#endif + currFlatness_fx[n] = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( sts[n]->hTranDet, NSUBBLOCKS, 0 ); + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + currFlatness[n] = fix16_to_float( currFlatness_fx[n], Q7 ); +#endif +#endif } /* Synchonize detection for downmix-based stereo */ if ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_TD ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + currFlatness_fx[0] = float_to_fix16( currFlatness[0], Q7 ); + currFlatness_fx[1] = float_to_fix16( currFlatness[1], Q7 ); +#endif + set_transient_stereo_fx( hCPE, currFlatness_fx ); +#else set_transient_stereo( hCPE, currFlatness ); +#endif } /*----------------------------------------------------------------* @@ -431,42 +693,11 @@ ivas_error ivas_cpe_enc( 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 ); #endif // MSAN_FIX } - 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->gipd, hCPE->hStereoDft->gipd_fx, Q13, STEREO_DFT_ENC_DFT_NB ); - /* flt2fix end */ - - - /*flt2fix: dft_td_itd*/ - f2me_buf( hCPE->hStereoDft->xspec_smooth, hCPE->hStereoDft->xspec_smooth_fx, &hCPE->hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); - f2me_buf( hCPE->hStereoDft->Spd_L_smooth, hCPE->hStereoDft->Spd_L_smooth_fx, &hCPE->hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); - f2me_buf( hCPE->hStereoDft->Spd_R_smooth, hCPE->hStereoDft->Spd_R_smooth_fx, &hCPE->hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); floatToFixed_arrL( hCPE->hStereoDft->hItd->itd, hCPE->hStereoDft->hItd->itd_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 ); - f2me( hCPE->hStereoDft->hItd->currFlatness, &hCPE->hStereoDft->hItd->currFlatness_fx, &hCPE->hStereoDft->hItd->currFlatness_fx_e ); - #ifndef MSAN_FIX hCPE->hStereoClassif->xtalk_score_fx = floatToFixed( hCPE->hStereoClassif->xtalk_score, 31 ); #endif // !MSAN_FIX - 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 ); - - /*flt2fix: dft_compute_prm*/ - floatToFixed_arrL( hCPE->hStereoDft->sidSideGain, hCPE->hStereoDft->sidSideGain_fx, Q31, STEREO_DFT_ERB4_BANDS ); - hCPE->hStereoDft->sid_gipd_fx = floatToFixed( hCPE->hStereoDft->sid_gipd, Q13 ); - hCPE->hStereoClassif->relE_0_1_fx = floatToFixed( hCPE->hStereoClassif->relE_0_1, 31 ); - floatToFixed_arrL( hCPE->hStereoClassif->unclr_relE_0_1_LT, hCPE->hStereoClassif->unclr_relE_0_1_LT_fx, 31, UNCLR_RC_ORDER ); - hCPE->hStereoClassif->unclr_wscore_fx = floatToFixed( hCPE->hStereoClassif->unclr_wscore, 31 ); - - for ( i = 0; i < 2; i++ ) - { - f2me( hCPE->hStereoDft->nrg_L[i], &hCPE->hStereoDft->nrg_L_fx[i], &hCPE->hStereoDft->nrg_L_fx_e[i] ); - f2me( hCPE->hStereoDft->nrg_R[i], &hCPE->hStereoDft->nrg_R_fx[i], &hCPE->hStereoDft->nrg_R_fx_e[i] ); - f2me( hCPE->hStereoDft->nrg_DMX[i], &hCPE->hStereoDft->nrg_DMX_fx[i], &hCPE->hStereoDft->nrg_DMX_fx_e[i] ); - } for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) { f2me( hCPE->hStereoDft->res_cod_NRG_M[i], &hCPE->hStereoDft->res_cod_NRG_M_fx[i], &hCPE->hStereoDft->res_cod_NRG_M_fx_e[i] ); @@ -482,23 +713,30 @@ ivas_error ivas_cpe_enc( { floatToFixed_arr( sts[1]->old_inp_12k8, sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); } - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); + /*flt2fix end*/ #endif #ifdef IVAS_FLOAT_FIXED + Word16 temp = getScaleFactor32( hCPE->hStereoDft->Spd_L_smooth_fx, STEREO_DFT_N_32k_ENC / 2 ); + scale_sig32( hCPE->hStereoDft->Spd_L_smooth_fx, STEREO_DFT_N_32k_ENC / 2, temp ); + hCPE->hStereoDft->Spd_L_smooth_fx_e = sub( hCPE->hStereoDft->Spd_L_smooth_fx_e, temp ); + + temp = getScaleFactor32( hCPE->hStereoDft->Spd_R_smooth_fx, STEREO_DFT_N_32k_ENC / 2 ); + scale_sig32( hCPE->hStereoDft->Spd_R_smooth_fx, STEREO_DFT_N_32k_ENC / 2, temp ); + hCPE->hStereoDft->Spd_R_smooth_fx_e = sub( hCPE->hStereoDft->Spd_R_smooth_fx_e, temp ); + stereo_dft_hybrid_ITD_flag( hCPE->hStereoDft->hConfig, input_Fs, hCPE->hStereoDft->hItd->hybrid_itd_max ); /* Time Domain ITD compensation using extrapolation */ stereo_td_itd_fx( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd_fx, hCPE->hStereoDft->q_input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); - stereo_dft_enc_analyze_fx( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT_fx, hCPE->input_mem_fx, hCPE->q_input_mem ); + stereo_dft_enc_analyze_fx( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT_fx, hCPE->hStereoDft->DFT_fx_e, hCPE->input_mem_fx, hCPE->q_input_mem ); #else /* Time Domain ITD compensation using extrapolation */ stereo_td_itd( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem ); @@ -517,13 +755,64 @@ ivas_error ivas_cpe_enc( } else if ( hCPE->element_mode == IVAS_CPE_TD ) { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr16( sts[0]->input, sts[0]->input_fx, 0, input_frame ); + floatToFixed_arr16( sts[1]->input, sts[1]->input_fx, 0, input_frame ); + + 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 ); + + sts[0]->ee_old_fx = floatToFixed( sts[0]->ee_old, Q6 ); + sts[1]->ee_old_fx = floatToFixed( sts[1]->ee_old, Q6 ); + + IF( hCPE->hStereoTD->tdm_last_SM_flag ) + { + floatToFixed_arr16( sts[0]->input, sts[0]->input_fx, 0, input_frame ); + floatToFixed_arr16( sts[1]->input, sts[1]->input_fx, 0, input_frame ); + 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 /* Determine the energy ratio between the 2 channels */ - tdm_ratio_idx = stereo_tdm_ener_analysis( + tdm_ratio_idx = stereo_tdm_ener_analysis_fx( ivas_format, hCPE, input_frame, &tdm_SM_or_LRTD_Pri, &tdm_ratio_idx_SM ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ); +#endif /* Compute the downmix signal based on the ratio index */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 input_fx[2][L_FRAME48k]; + floatToFixed_arr16( sts[1]->input, input_fx[0], 0, input_frame ); + floatToFixed_arr16( sts[0]->input, input_fx[1], 0, input_frame ); +#endif + Word16 tdm_SM_flag; + IF( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) + { + tdm_SM_flag = tdm_SM_or_LRTD_Pri; + move16(); + } + ELSE + { + tdm_SM_flag = 0; + move16(); + } + stereo_tdm_downmix_ivas_fx( hCPE->hStereoTD, input_fx[0], input_fx[1], input_frame, tdm_ratio_idx, tdm_SM_flag, tdm_ratio_idx_SM ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( input_fx[0], sts[0]->input, 0, input_frame ); + fixedToFloat_arr( input_fx[1], sts[1]->input, 0, input_frame ); +#endif +#else stereo_tdm_downmix( hCPE->hStereoTD, sts[0]->input, sts[1]->input, input_frame, tdm_ratio_idx, ( ( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) ? tdm_SM_or_LRTD_Pri : 0 ), tdm_ratio_idx_SM ); +#endif /* signal the bitrate for BW selection in the SCh */ sts[0]->bits_frame_channel = 0; @@ -539,7 +828,41 @@ ivas_error ivas_cpe_enc( } else if ( hCPE->element_mode == IVAS_CPE_MDCT ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + FOR( int16_t i = 0; i < CPE_CHANNELS; i++ ) + { + sts[i]->q_inp = Q_factor_arr( sts[i]->old_input_signal, 1965 ); // check length + hCPE->q_input_mem[i] = Q_factor_arr( &hCPE->input_mem[i][0], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + floatToFixed_arr( sts[i]->old_input_signal, sts[i]->old_input_signal_fx, sts[i]->q_inp, 1965 ); + floatToFixed_arr( &hCPE->input_mem[i][0], &hCPE->input_mem_fx[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + } + floatToFixed_arrL( hCPE->hStereoMdct->hItd->itd, hCPE->hStereoMdct->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoMdct->hItd->deltaItd, hCPE->hStereoMdct->hItd->deltaItd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, 15, 3 ); + if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + floatToFixed_arr( sts[1]->old_inp_12k8, sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); + } + } +#endif + stereo_td_itd_mdct_stereo_fx( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + fixedToFloat_arrL( hCPE->hStereoMdct->hItd->itd_fx, hCPE->hStereoMdct->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); + FOR( int16_t i = 0; i < CPE_CHANNELS; i++ ) + { + 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_arr( sts[i]->old_input_signal_fx, sts[i]->old_input_signal, sts[i]->q_inp, 1965 ); + } + } +#endif +#else stereo_td_itd_mdct_stereo( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); +#endif } /*----------------------------------------------------------------* @@ -596,54 +919,16 @@ ivas_error ivas_cpe_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word16 i; - /* 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->gipd_fx, hCPE->hStereoDft->gipd, Q13, STEREO_DFT_ENC_DFT_NB ); FOR( 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 ) ); me2f_buf( hCPE->hStereoDft->DFT_fx[i], hCPE->hStereoDft->DFT_fx_e[i], hCPE->hStereoDft->DFT[i], STEREO_DFT_N_MAX_ENC ); -#ifdef MSAN_FIX - IF( hCPE->hStereoDft->hItd->td_itd[STEREO_DFT_OFFSET] != 0 && EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) - { - fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], hCPE->hStereoDft->dft_ovl ); - } -#else - 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 ); -#endif // MSAN_FIX } - /* fix2flt end */ - - - /*fix2flt: dft_td_itd*/ - me2f_buf( hCPE->hStereoDft->xspec_smooth_fx, hCPE->hStereoDft->xspec_smooth_fx_e, hCPE->hStereoDft->xspec_smooth, STEREO_DFT_N_32k_ENC ); - me2f_buf( hCPE->hStereoDft->Spd_L_smooth_fx, hCPE->hStereoDft->Spd_L_smooth_fx_e, hCPE->hStereoDft->Spd_L_smooth, STEREO_DFT_N_32k_ENC / 2 ); - me2f_buf( hCPE->hStereoDft->Spd_R_smooth_fx, hCPE->hStereoDft->Spd_R_smooth_fx_e, hCPE->hStereoDft->Spd_R_smooth, STEREO_DFT_N_32k_ENC / 2 ); fixedToFloat_arrL( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoDft->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); - fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, 15, SSC_MAX_NFEA ); - fixedToFloat_arrL( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, 15, SSC_MAX_NFEA ); - hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); - hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); - hCPE->hStereoClassif->xtalk_score = fixedToFloat( hCPE->hStereoClassif->xtalk_score_fx, 31 ); - fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_score_buf_fx, hCPE->hStereoClassif->xtalk_score_buf, 31, XTALK_SCORE_BUF_LEN ); - hCPE->hStereoClassif->xtalk_wscore = fixedToFloat( hCPE->hStereoClassif->xtalk_wscore_fx, 31 ); - - fixedToFloat_arrL( hCPE->hStereoDft->sidSideGain_fx, hCPE->hStereoDft->sidSideGain, Q31, STEREO_DFT_ERB4_BANDS ); - hCPE->hStereoDft->sid_gipd = fixedToFloat( hCPE->hStereoDft->sid_gipd_fx, Q13 ); - /*local fix2flt*/ - fixedToFloat_arrL( hCPE->hStereoClassif->unclr_relE_0_1_LT_fx, hCPE->hStereoClassif->unclr_relE_0_1_LT, 31, UNCLR_RC_ORDER ); - hCPE->hStereoClassif->unclr_wscore = fixedToFloat( hCPE->hStereoClassif->unclr_wscore_fx, 31 ); + /*local fix2flt*/ - for ( i = 0; i < 2; i++ ) - { - hCPE->hStereoDft->nrg_L[i] = me2f( hCPE->hStereoDft->nrg_L_fx[i], hCPE->hStereoDft->nrg_L_fx_e[i] ); - hCPE->hStereoDft->nrg_R[i] = me2f( hCPE->hStereoDft->nrg_R_fx[i], hCPE->hStereoDft->nrg_R_fx_e[i] ); - hCPE->hStereoDft->nrg_DMX[i] = me2f( hCPE->hStereoDft->nrg_DMX_fx[i], hCPE->hStereoDft->nrg_DMX_fx_e[i] ); - } for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) { hCPE->hStereoDft->res_cod_NRG_M[i] = me2f( hCPE->hStereoDft->res_cod_NRG_M_fx[i], hCPE->hStereoDft->res_cod_NRG_M_fx_e[i] ); @@ -651,8 +936,6 @@ ivas_error ivas_cpe_enc( } /*fix2flt: dft_synthesize*/ - hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); - hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); fixedToFloat_arrL( sts[0]->input32_fx + out_start_ind, sts[0]->input + out_start_ind, 16, out_end_ind - out_start_ind ); fixedToFloat_arrL( old_inp_12k8_fx[0] + L_INP_MEM + out_12k8_start_ind[0], old_inp_12k8[0] + L_INP_MEM + out_12k8_start_ind[0], 16, out_12k8_end_ind[0] - out_12k8_start_ind[0] ); fixedToFloat_arrL( old_inp_16k_fx[0] + L_INP_MEM + out_16k_start_ind, old_inp_16k[0] + L_INP_MEM + out_16k_start_ind, 16, out_16k_end_ind - out_16k_start_ind ); @@ -667,6 +950,7 @@ ivas_error ivas_cpe_enc( fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); + /*fix2flt end*/ #endif #else @@ -710,10 +994,10 @@ ivas_error ivas_cpe_enc( for ( n = 0; n < n_CoreChannels; n++ ) { #ifdef IVAS_FLOAT_FIXED - error = pre_proc_front_ivas_fx( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], + error = pre_proc_front_ivas_fx( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8_16fx[n], old_inp_12k8[n], old_inp_16k[n], &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], &vad_hover_flag[n], &attack_flag[n], realBuffer[n], imagBuffer[n], old_wsp[n], pitch_fr[n], voicing_fr[n], &loc_harm[n], &cor_map_sum[n], &vad_flag_dtx[n], enerBuffer[n], - fft_buff[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0, ivas_format, st_ivas->hMCT != NULL, ivas_total_brate ); + fft_buff[n], fft_buff_fx[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0, ivas_format, st_ivas->hMCT != NULL, ivas_total_brate ); #else error = pre_proc_front_ivas( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], &vad_hover_flag[n], &attack_flag[n], @@ -751,7 +1035,36 @@ ivas_error ivas_cpe_enc( /* MDCT stereo DTX: active/inactive frame decision; compute FD CNG coherence */ if ( hCPE->element_mode == IVAS_CPE_MDCT && hEncoderConfig->Opt_DTX_ON ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 max_e = -16, tmp_e, tmp_e2; + Word16 i; + + for ( i = 0; i < 2 * L_FFT; i++ ) + { + f2me_16( fft_buff[0][i], &fft_buff_fx[0][i], &tmp_e ); + f2me_16( fft_buff[1][i], &fft_buff_fx[1][i], &tmp_e2 ); + tmp_e = max( tmp_e, tmp_e2 ); + max_e = ( max_e > tmp_e ) ? max_e : tmp_e; + } + max_e += 2; + for ( i = 0; i < 2 * L_FFT; i++ ) + { + f2me_16( fft_buff[0][i], &fft_buff_fx[0][i], &tmp_e ); + f2me_16( fft_buff[1][i], &fft_buff_fx[1][i], &tmp_e2 ); + fft_buff_fx[0][i] = shr( fft_buff_fx[0][i], max_e - tmp_e ); + fft_buff_fx[1][i] = shr( fft_buff_fx[1][i], max_e - tmp_e2 ); + } + fft_exp = max_e; +#endif + stereoFdCngCoherence_fx( sts, hCPE->last_element_mode, fft_buff_fx, fft_exp ); + +#ifdef IVAS_FLOAT_FIXED + sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = fixedToFloat( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx, Q15 ); +#endif +#else stereoFdCngCoherence( sts, hCPE->last_element_mode, fft_buff ); +#endif /* Reset metadata */ if ( sts[0]->cng_sba_flag || ( ivas_format == SBA_FORMAT ) ) @@ -763,7 +1076,27 @@ ivas_error ivas_cpe_enc( /*----------------------------------------------------------------* * Core codec configuration *----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + /* IGF reconfiguration */ + FOR( n = 0; n < n_CoreChannels; n++ ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( NE_32( hCPE->last_element_brate, hCPE->element_brate ) || NE_16( hCPE->element_mode, hCPE->last_element_mode ) || ( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) && NE_16( sts[0]->bits_frame_nominal, last_bits_frame_nominal ) ) || NE_16( sts[n]->last_bwidth, sts[n]->bwidth ) ) && ( n == 0 || EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) ) + { + Word16 igf; + igf = getIgfPresent_fx( sts[n]->element_mode, L_mult0( sts[n]->bits_frame_nominal, FRAMES_PER_SEC ), sts[n]->max_bwidth, sts[n]->rf_mode ); + IF( NE_32( ( error = IGF_Reconfig_fx( &sts[n]->hIGFEnc, igf, 0, L_mult0( sts[n]->bits_frame_nominal, FRAMES_PER_SEC ), sts[n]->max_bwidth, sts[n]->element_mode, sts[n]->rf_mode ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } +#else /* IGF reconfiguration */ for ( n = 0; n < n_CoreChannels; n++ ) { @@ -777,7 +1110,7 @@ ivas_error ivas_cpe_enc( } } } - +#endif if ( hCPE->element_mode == IVAS_CPE_MDCT && st_ivas->hMCT == NULL ) { /* set coded BW for MDCT stereo */ @@ -819,9 +1152,42 @@ ivas_error ivas_cpe_enc( /* configure TD stereo encoder */ if ( hCPE->element_mode == IVAS_CPE_TD ) { - tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( pitch_fr[0], pitch_fr_fx[0], Q6, NB_SUBFR ); + floatToFixed_arr( pitch_fr[1], pitch_fr_fx[1], Q6, NB_SUBFR ); + floatToFixed_arr( voicing_fr[0], voicing_fr_fx[0], Q15, NB_SUBFR ); + floatToFixed_arr( voicing_fr[1], voicing_fr_fx[1], Q15, NB_SUBFR ); + floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, Q15, 3 ); + floatToFixed_arr( hCPE->hCoreCoder[1]->voicing, hCPE->hCoreCoder[1]->voicing_fx, Q15, 3 ); + hCPE->hCoreCoder[0]->old_corr_fx = float_to_fix16( hCPE->hCoreCoder[0]->old_corr, Q15 ); + hCPE->hCoreCoder[0]->old_thres_fx = float_to_fix16( hCPE->hCoreCoder[0]->old_thres, Q15 ); +#endif + tdm_ol_pitch_comparison_fx( hCPE, pitch_fr_fx, voicing_fr_fx ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( pitch_fr_fx[0], pitch_fr[0], Q6, NB_SUBFR ); + fixedToFloat_arr( pitch_fr_fx[1], pitch_fr[1], Q6, NB_SUBFR ); + fixedToFloat_arr( voicing_fr_fx[0], voicing_fr[0], Q15, NB_SUBFR ); + fixedToFloat_arr( voicing_fr_fx[1], voicing_fr[1], Q15, NB_SUBFR ); + fixedToFloat_arr( hCPE->hCoreCoder[0]->voicing_fx, hCPE->hCoreCoder[0]->voicing, Q15, 3 ); + fixedToFloat_arr( hCPE->hCoreCoder[1]->voicing_fx, hCPE->hCoreCoder[1]->voicing, Q15, 3 ); + hCPE->hCoreCoder[1]->old_corr = fix16_to_float( hCPE->hCoreCoder[1]->old_corr_fx, Q15 ); + hCPE->hCoreCoder[1]->old_thres = fix16_to_float( hCPE->hCoreCoder[1]->old_thres_fx, Q15 ); +#endif +#else + tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); +#endif +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Etot_last_fx[0] = float_to_fix16( Etot_last[0], Q8 ); + Etot_last_fx[1] = float_to_fix16( Etot_last[1], Q8 ); +#endif + tdm_configure_enc_fx( ivas_format, st_ivas->ism_mode, hCPE, Etot_last_fx, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); +#else tdm_configure_enc( ivas_format, st_ivas->ism_mode, hCPE, Etot_last, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); +#endif if ( hEncoderConfig->Opt_DTX_ON ) { @@ -861,11 +1227,13 @@ ivas_error ivas_cpe_enc( *----------------------------------------------------------------*/ cpe_brate = 0; - if ( hCPE->element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) { - if ( hEncoderConfig->Opt_DTX_ON ) + IF( hEncoderConfig->Opt_DTX_ON ) { - if ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) + test(); + IF( EQ_32( sts[0]->core_brate, SID_2k40 ) || EQ_32( sts[0]->core_brate, FRAME_NO_DATA ) ) { /* Reconfigure DFT Stereo for inactive frames */ #ifndef IVAS_FLOAT_FIXED @@ -888,29 +1256,39 @@ ivas_error ivas_cpe_enc( } #endif - stereo_dft_cng_side_gain( hCPE->hStereoDft, hCPE->hStereoCng, sts[0]->core_brate, sts[0]->last_core_brate, sts[0]->bwidth ); + stereo_dft_cng_side_gain_fx( hCPE->hStereoDft, hCPE->hStereoCng, sts[0]->core_brate, sts[0]->last_core_brate, sts[0]->bwidth ); } - else + ELSE { - stereo_cng_upd_counters( hCPE->hStereoCng, hCPE->element_mode, hCPE->hStereoDft->nbands, hCPE->hStereoDft->sidSideGain, sts[0]->hTdCngEnc->burst_ho_cnt, &hCPE->hStereoDft->coh_fade_counter ); + stereo_cng_upd_counters_fx( hCPE->hStereoCng, hCPE->element_mode, hCPE->hStereoDft->nbands, hCPE->hStereoDft->sidSideGain_fx, sts[0]->hTdCngEnc->burst_ho_cnt, &hCPE->hStereoDft->coh_fade_counter ); } } /* Write stereo bitstream */ cpe_brate = st_ivas->hCPE[0]->element_brate; + move16(); /* DFT stereo side bits */ - if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && cpe_brate < MASA_STEREO_MIN_BITRATE && sts[0]->core_brate != SID_2k40 && sts[0]->core_brate != FRAME_NO_DATA ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) && NE_32( sts[0]->core_brate, SID_2k40 ) && NE_32( sts[0]->core_brate, FRAME_NO_DATA ) ) { nb_bits = 0; /* Only mono downmix is transmitted in this case */ + move16(); } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) ) + ELSE IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && ( EQ_32( sts[0]->core_brate, SID_2k40 ) || EQ_32( sts[0]->core_brate, FRAME_NO_DATA ) ) ) { nb_bits = hCPE->hMetaData->nb_bits_tot; + move16(); } - else + ELSE { - stereo_dft_enc_write_BS( hCPE, &nb_bits ); + stereo_dft_enc_write_BS_fx( hCPE, &nb_bits ); } /* Residual coding in MDCT domain */ @@ -926,7 +1304,13 @@ ivas_error ivas_cpe_enc( } } - stereo_dft_enc_res( hCPE->hStereoDft, old_inp_12k8[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, max_bits ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < CPE_CHANNELS; i++ ) + { + floatToFixed_arrL( old_inp_12k8[i], old_inp_12k8_fx[i], Q16, L_INP_12k8 ); + } +#endif + stereo_dft_enc_res_fx( hCPE->hStereoDft, old_inp_12k8_fx[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, max_bits ); } if ( sts[0]->core_brate == FRAME_NO_DATA || sts[0]->core_brate == SID_2k40 ) @@ -1089,7 +1473,9 @@ ivas_error ivas_cpe_enc( tdm_SM_or_LRTD_Pri = 0; tdm_ratio_idx = -1; tdm_ratio_idx_SM = -1; +#ifndef IVAS_FLOAT_FIXED tdm_last_ratio = 0; +#endif /*------------------------------------------------------------------* @@ -2058,6 +2444,9 @@ ivas_error create_cpe_enc( } stereo_icBWE_init_enc( hCPE->hStereoICBWE ); +#ifdef IVAS_FLOAT_FIXED + stereo_icBWE_init_enc_fx( hCPE->hStereoICBWE ); +#endif } /*-----------------------------------------------------------------* @@ -2070,8 +2459,11 @@ ivas_error create_cpe_enc( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); } - +#ifndef IVAS_FLOAT_FIXED stereo_td_init_enc( hCPE->hStereoTD, hCPE->last_element_mode ); +#else + stereo_td_init_enc_fx( hCPE->hStereoTD, hCPE->last_element_mode ); +#endif } /*-----------------------------------------------------------------* @@ -2173,7 +2565,6 @@ ivas_error create_cpe_enc_fx( { 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 @@ -2183,6 +2574,26 @@ ivas_error create_cpe_enc_fx( } } + +#if 1 // TODO: To be removed later + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + if ( ivas_format == STEREO_FORMAT || ivas_format == MASA_FORMAT || ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCMASA ) || ivas_format == MASA_ISM_FORMAT ) + { + if ( ( hCPE->input_mem[n] = (float *) malloc( sizeof( float ) * 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( hCPE->input_mem[n], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + } + else + { + hCPE->input_mem[n] = NULL; + } + } +#endif + /*-----------------------------------------------------------------* * stereo classifier: allocate and initialize *-----------------------------------------------------------------*/ @@ -2193,6 +2604,9 @@ ivas_error create_cpe_enc_fx( } stereo_classifier_init_fx( hCPE->hStereoClassif ); +#if 1 // TODO: To be removed later + stereo_classifier_init( hCPE->hStereoClassif ); +#endif /*-----------------------------------------------------------------* * Metadata: allocate and initialize @@ -2459,7 +2873,75 @@ free( hCPE ); return; } +#ifdef IVAS_FLOAT_FIXED + +/*------------------------------------------------------------------------- + * stereo_mode_combined_format_enc() + * + * Set stereo format in a combined format + *-------------------------------------------------------------------------*/ + +static void stereo_mode_combined_format_enc_fx( + const Encoder_Struct *st_ivas, /* i : encoder main structure */ + CPE_ENC_HANDLE hCPE /* i/o: CPE handle */ +) +{ + ENCODER_CONFIG_HANDLE hEncoderConfig; + Word32 element_brate_ref; + + hEncoderConfig = st_ivas->hEncoderConfig; + + IF( EQ_16( hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) + { + element_brate_ref = hCPE->element_brate; + move32(); + + test(); + test(); + test(); + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && + ( ( EQ_16( hEncoderConfig->nchan_ism, 3 ) && EQ_32( hEncoderConfig->ivas_total_brate, IVAS_96k ) ) || + ( EQ_16( hEncoderConfig->nchan_ism, 4 ) && EQ_32( hEncoderConfig->ivas_total_brate, IVAS_128k ) ) ) ) + { + IF( GT_32( L_add( hCPE->element_brate, hCPE->brate_surplus ), IVAS_64k ) ) + { + st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt = 0; + move16(); + } + ELSE + { + st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt = add( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt, 1 ); + move16(); + st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt = s_min( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt, OMASA_STEREO_SW_CNT_MAX ); + move16(); + } + + IF( LT_16( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt, OMASA_STEREO_SW_CNT_MAX ) ) + { + hCPE->element_mode = IVAS_CPE_MDCT; + move16(); + hCPE->element_brate = IVAS_64k; + move32(); + hCPE->brate_surplus = L_sub( hCPE->brate_surplus, L_sub( hCPE->element_brate, element_brate_ref ) ); + move32(); + } + + /* write OMASA stereo mode signalling */ + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + push_indice( hCPE->hCoreCoder[0]->hBstr, IND_SMODE_OMASA, 1, NBITS_ELEMENT_MODE ); + } + ELSE + { + push_indice( hCPE->hCoreCoder[0]->hBstr, IND_SMODE_OMASA, 0, NBITS_ELEMENT_MODE ); + } + } + } + return; +} +#else /*------------------------------------------------------------------------- * stereo_mode_combined_format_enc() * @@ -2515,3 +2997,4 @@ static void stereo_mode_combined_format_enc( return; } +#endif diff --git a/lib_enc/ivas_decision_matrix_enc.c b/lib_enc/ivas_decision_matrix_enc.c index a8f4d8aa189988c1fb68562069f1094b82ddfa0e..b3ae38f109ba56f8e67fc35de1d1c70744066365 100644 --- a/lib_enc/ivas_decision_matrix_enc.c +++ b/lib_enc/ivas_decision_matrix_enc.c @@ -39,7 +39,10 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "wmc_auto.h" - +#include "prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ /*-----------------------------------------------------------------* * ivas_decision_matrix_enc() @@ -69,6 +72,7 @@ * Note: in MDCT stereo mode, TCX core is selected for all content * -------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void ivas_decision_matrix_enc( Encoder_State *st, /* i : encoder state structure */ const int32_t element_brate, /* i : element bitrate */ @@ -338,7 +342,406 @@ void ivas_decision_matrix_enc( return; } +#else +void ivas_decision_matrix_enc_fx( + Encoder_State *st, /* i : encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + const Word16 fft_buff[], /* i : FFT buffer */ + const Word32 enerBuffer[], /* i : energy buffer */ + Word16 enerBuffer_exp, + const Word16 last_element_mode /* i : last element mode */ +) +{ + Word32 icbwe_brate; + /* init */ + icbwe_brate = 0; + move32(); + + /* initialization */ + st->core = -1; + move16(); + + st->extl = -1; + move16(); + + st->extl_brate = 0; + move16(); + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + st->igf = 0; + move16(); + } + + test(); + test(); + + /* SID and FRAME_NO_DATA frames */ + IF( st->Opt_DTX_ON && ( EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) ) + { + st->core = ACELP_CORE; + move16(); + + test(); + IF( GE_32( st->input_Fs, 32000 ) || GE_16( st->bwidth, SWB ) ) + { + st->extl = SWB_CNG; + move16(); + } + st->rf_mode = 0; + move16(); + + return; + } + + /*---------------------------------------------------------------------* + * Select the core + *---------------------------------------------------------------------*/ + + test(); + test(); + test(); + + IF( EQ_16( st->element_mode, IVAS_SCE ) && st->low_rate_mode ) + { + /* ISM low-rate mode */ + st->core = ACELP_CORE; + move16(); + + st->coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_32( st->total_brate, MAX_ACELP_BRATE ) ) + { + /* highest bitrates */ + st->core = TCX_20_CORE; + move16(); + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* in MDCT stereo set TCX core */ + st->core = TCX_20_CORE; + move16(); + } + ELSE IF( EQ_16( st->coder_type, INACTIVE ) ) + { + /* inactive frames */ + test(); + IF( EQ_16( st->cng_type, FD_CNG ) && GE_32( st->total_brate, STEREO_TCX_MIN_RATE ) ) + { + st->core = TCX_20_CORE; + move16(); + } + ELSE + { + st->core = ACELP_CORE; + move16(); + } + } + ELSE IF( st->sp_aud_decision1 == 0 && st->sp_aud_decision2 == 0 ) + { + /* speech */ + st->core = ACELP_CORE; + move16(); + } + ELSE IF( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) + { + /* music w. GSC core */ + st->core = ACELP_CORE; + + move16(); + } + ELSE /* sp_aud_decision1 == 1 && *sp_aud_decision2 == 1 */ + { + /* music w. TCX or HQ core */ + st->core = TCX_20_CORE; + move16(); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) || st->sp_aud_decision0 == 0 ) + { + st->core = TCX_20_CORE; + move16(); + } + ELSE + { + /* select TCX core or HQ core using bits_frame_nominal to match the TCX configuration bitrate */ + st->core = mdct_classifier_ivas_fx( st, fft_buff, enerBuffer, enerBuffer_exp, ( st->bits_frame_nominal * FRAMES_PER_SEC ) ); + move16(); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + + /* do not allow TD stereo ACELP core -> DFT stereo TCX core switching as it is on the WC complexity path */ + IF( ( ( EQ_16( st->last_core, ACELP_CORE ) && EQ_16( last_element_mode, IVAS_CPE_TD ) && EQ_16( st->element_mode, IVAS_CPE_DFT ) ) || ( EQ_16( st->tdm_LRTD_flag, 1 ) && LE_32( st->total_brate, IVAS_16k4 ) ) ) && EQ_16( st->core, TCX_20_CORE ) && LE_32( st->total_brate, MAX_ACELP_BRATE ) ) /* Override TCX in case of LRTD && primary channel has low bitrate*/ + { + st->core = ACELP_CORE; + move16(); + } + + test(); + IF( st->is_ism_format && st->tcxonly ) + { + st->core = TCX_20_CORE; + move16(); + } + + /* TCX not available at low bitrates -> replace it by GSC */ + + test(); + IF( EQ_16( st->core, TCX_20_CORE ) && LT_32( st->total_brate, STEREO_TCX_MIN_RATE ) ) + { + st->core = ACELP_CORE; + st->coder_type = AUDIO; + st->sp_aud_decision2 = 0; + + move16(); + move16(); + move16(); + + IF( st->low_rate_mode ) + { + st->coder_type = INACTIVE; + move16(); + } + } + + /* sanity check to avoid too low ACELP bitrate in case of "limitation to avoid too high bitrate in one active TCX channel" at element_brate = 32000 */ + test(); + test(); + test(); + test(); + IF( st->is_ism_format && st->flag_ACELP16k && !st->low_rate_mode && EQ_16( st->core, ACELP_CORE ) && LT_32( st->total_brate, add( ACELP_16k_LOW_LIMIT, FB_TBE_1k8 ) ) ) + { + st->core = TCX_20_CORE; + move16(); + } + + /*---------------------------------------------------------------------* + * Select ACELP and GSC extension layer + *---------------------------------------------------------------------*/ + + IF( EQ_16( st->core, ACELP_CORE ) ) + { + /* WB */ + IF( EQ_16( st->bwidth, WB ) ) + { + test(); + test(); + test(); + test(); + IF( LT_32( st->total_brate, MIN_BRATE_WB_BWE ) || ( EQ_16( st->idchan, 1 ) && EQ_16( st->element_mode, IVAS_CPE_TD ) ) ) + { + st->extl = WB_BWE; + move16(); + } + ELSE IF( GE_16( extract_l( st->total_brate ), MIN_BRATE_WB_BWE ) && !st->flag_ACELP16k ) + { + test(); + test(); + IF( ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) || EQ_16( st->coder_type, INACTIVE ) ) + { + st->extl = WB_BWE; + move16(); + + st->extl_brate = WB_BWE_0k35; + move32(); + } + ELSE + { + st->extl = WB_TBE; + move16(); + + test(); + test(); + IF( LT_32( st->total_brate, MIN_BRATE_WB_TBE_1k05 ) || ( EQ_16( st->element_mode, IVAS_CPE_TD ) && LT_32( st->total_brate, MIN_TDM_BRATE_WB_TBE_1k05 ) ) ) + { + st->extl_brate = WB_TBE_0k35; + move32(); + } + ELSE + { + st->extl_brate = WB_TBE_1k05; + move32(); + } + } + } + } + + /* SWB and FB */ + ELSE IF( EQ_16( st->bwidth, SWB ) || EQ_16( st->bwidth, FB ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( GE_32( st->total_brate, MIN_BRATE_SWB_BWE ) /*&& (NE_16(*coder_type, AUDIO) || GE_32(st->total_brate, add(MIN_BWE_PRI_BRATE, 600)))*/ + || ( GE_32( st->total_brate, MIN_MIN_BRATE_LRTD_SWB_BWE ) && EQ_16( st->element_mode, IVAS_CPE_TD ) && EQ_16( st->bwidth, SWB ) && st->tdm_LRTD_flag ) || ( LT_32( element_brate, IVAS_16k4 ) && GE_32( st->total_brate, MIN_MIN_BRATE_LRTD_SWB_BWE ) && EQ_16( st->element_mode, IVAS_CPE_TD ) && EQ_16( st->bwidth, SWB ) ) ) + { + test(); + test(); + test(); + IF( ( ( ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) || EQ_16( st->coder_type, INACTIVE ) ) && !st->GSC_noisy_speech ) /* Note: SWB BWE is not used for GSC noisy speech */ ) + { + st->extl = SWB_BWE; + move16(); + + st->extl_brate = SWB_BWE_1k6; + move32(); + + IF( EQ_16( st->bwidth, FB ) ) + { + st->extl = FB_BWE; + move16(); + + st->extl_brate = FB_BWE_1k8; + move32(); + } + } + ELSE + { + st->extl = SWB_TBE; + move16(); + st->extl_brate = SWB_TBE_1k6; + move32(); + + test(); + test(); + test(); + IF( GE_32( st->total_brate, MIN_BRATE_SWB_TBE_2k80 ) && st->flag_ACELP16k && EQ_16( st->element_mode, IVAS_SCE ) ) + { + st->extl_brate = SWB_TBE_2k8; + move32(); + } + ELSE IF( EQ_16( st->tdm_LRTD_flag, 1 ) && EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + IF( LT_32( st->element_brate, IVAS_24k4 ) ) + { + st->extl_brate = SWB_TBE_1k10; + move32(); + } + ELSE + { + st->extl_brate = SWB_TBE_1k75; + move32(); + } + } + ELSE IF( LT_32( st->total_brate, MIN_BRATE_SWB_TBE_1k60 ) ) + { + st->extl_brate = SWB_TBE_0k95; + move32(); + } + + IF( EQ_16( st->bwidth, FB ) ) + { + st->extl = FB_TBE; + move16(); + + st->extl_brate = FB_TBE_1k8; + move32(); + + test(); + test(); + IF( GE_32( st->total_brate, MIN_BRATE_SWB_TBE_2k80 ) && st->flag_ACELP16k && EQ_16( st->element_mode, IVAS_SCE ) ) + { + st->extl_brate = FB_TBE_3k0; + move32(); + } + } + } + } + ELSE + { + st->extl = WB_BWE; + move16(); + + st->extl_brate = 0; + move32(); + } + + /* set IC-BWE bitrate */ + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) && ( st->idchan == 0 ) && !st->tdm_LRTD_flag ) + { + icbwe_brate = STEREO_BITS_ICBWE * FRAMES_PER_SEC; + move32(); + + IF( st->flag_ACELP16k == 0 ) + { + icbwe_brate = ( STEREO_BITS_ICBWE - STEREO_ICBWE_SPBITS ) * FRAMES_PER_SEC; + move32(); + } + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + icbwe_brate = STEREO_BITS_ICBWE_DFT * FRAMES_PER_SEC; + move32(); + + IF( st->flag_ACELP16k == 0 ) + { + icbwe_brate = ( STEREO_BITS_ICBWE_DFT - STEREO_ICBWE_SPBITS ) * FRAMES_PER_SEC; + move32(); + } + } + + test(); + test(); + test(); + test(); + test(); + if ( GE_16( st->element_mode, IVAS_CPE_DFT ) && EQ_16( st->core, ACELP_CORE ) && ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && !( EQ_16( st->element_mode, IVAS_CPE_TD ) && st->tdm_LRTD_flag ) ) + { + icbwe_brate = L_add( icbwe_brate, STEREO_ICBWE_MSFLAG_BITS * FRAMES_PER_SEC ); + move32(); + } + } + } + + /* set core bitrate */ + + st->core_brate = L_sub( L_sub( st->total_brate, st->extl_brate ), icbwe_brate ); + move32(); + + IF( st->ini_frame == 0 ) + { + /* avoid core switching in the very first frame */ + st->last_core = st->core; + move16(); + + st->last_core_brate = st->core_brate; + move32(); + + st->last_extl = st->extl; + move16(); + } + + /*-----------------------------------------------------------------* + * set inactive coder_type flag in ACELP core + *-----------------------------------------------------------------*/ + + st->inactive_coder_type_flag = 0; /* AVQ by default */ + move16(); + + IF( LE_32( st->total_brate, MAX_GSC_INACTIVE_BRATE ) ) + { + st->inactive_coder_type_flag = 1; /* GSC */ + move16(); + } + + return; +} +#endif /*---------------------------------------------------------------------* * ivas_signaling_enc() diff --git a/lib_enc/ivas_dirac_enc.c b/lib_enc/ivas_dirac_enc.c index 61a8092ca67773bdba18e7689be0b88932ce8f3c..1d327f291a2e1cc75e52ed61e28148161a6d46de 100644 --- a/lib_enc/ivas_dirac_enc.c +++ b/lib_enc/ivas_dirac_enc.c @@ -308,26 +308,21 @@ ivas_error ivas_dirac_enc_reconfigure( * DirAC main configuration *-----------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED IF( ( error = ivas_dirac_config_fx( (void *) st_ivas, ENC ) ) != IVAS_ERR_OK ) { return error; } -#else - if ( ( error = ivas_dirac_config( (void *) st_ivas, ENC ) ) != IVAS_ERR_OK ) - { - return error; - } -#endif - if ( st_ivas->hQMetaData->useLowerRes ) + IF( st_ivas->hQMetaData->useLowerRes ) { hDirAC->block_grouping[0] = 0; + move16(); hDirAC->block_grouping[1] = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); } - else + ELSE { - mvs2s( DirAC_block_grouping_5ms_MDFT, hDirAC->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + MVR2R_WORD16( DirAC_block_grouping_5ms_MDFT, hDirAC->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); } return error; @@ -490,10 +485,36 @@ ivas_error ivas_dirac_enc( } } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < hQMetaData->no_directions; i++ ) + { + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].energy_ratio, hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, Q30, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].azimuth, hQMetaData->q_direction[i].band_data[j].azimuth_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].elevation, hQMetaData->q_direction[i].band_data[j].elevation_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].q_azimuth, hQMetaData->q_direction[i].band_data[j].q_azimuth_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].q_elevation, hQMetaData->q_direction[i].band_data[j].q_elevation_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } +#endif if ( ( error = ivas_qmetadata_enc_encode( hMetaData, hQMetaData, hodirac_flag ) ) != IVAS_ERR_OK ) { return error; } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < hQMetaData->no_directions; i++ ) + { + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, hQMetaData->q_direction[i].band_data[j].energy_ratio, Q30, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].azimuth_fx, hQMetaData->q_direction[i].band_data[j].azimuth, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].elevation_fx, hQMetaData->q_direction[i].band_data[j].elevation, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].q_azimuth_fx, hQMetaData->q_direction[i].band_data[j].q_azimuth, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].q_elevation_fx, hQMetaData->q_direction[i].band_data[j].q_elevation, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } +#endif } else { @@ -908,8 +929,68 @@ void computeReferencePower_enc( return; } - - +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * computeReferencePower_enc() + * + * + *-------------------------------------------------------------------------*/ +void computeReferencePower_enc_fx( + const Word16 *band_grouping, /* i : Band grouping for estimation */ + Word32 Cldfb_RealBuffer[][DIRAC_NO_FB_BANDS_MAX], /* i : Real part of input signal */ + Word32 Cldfb_ImagBuffer[][DIRAC_NO_FB_BANDS_MAX], /* i : Imag part of input signal */ + Word32 *reference_power, /* o : Estimated power */ + const Word16 enc_param_start_band, /* i : first band to process */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + const IVAS_FORMAT ivas_format, /* i : ivas_format */ + Word16 ref_power_w, /* i : use 0 if hodirac is enabled */ + const Word16 nchan_ana /* i : number of analysis channels */ +) +{ + Word16 brange[2]; + Word16 ch_idx, i, j; + Word32 reference_power_W[DIRAC_MAX_NBANDS]; + FOR( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = band_grouping[i + enc_param_start_band]; + move16(); + brange[1] = band_grouping[i + enc_param_start_band + 1]; + move16(); + reference_power[i] = 0; + move32(); + reference_power_W[i] = 0; + move32(); + FOR( j = brange[0]; j < brange[1]; j++ ) + { + reference_power_W[i] = L_add( reference_power_W[i], L_add( Mpy_32_32( Cldfb_RealBuffer[0][j], Cldfb_RealBuffer[0][j] ), Mpy_32_32( Cldfb_ImagBuffer[0][j], Cldfb_ImagBuffer[0][j] ) ) ); + move32(); + } + reference_power[i] = L_add( reference_power[i], reference_power_W[i] ); // 2*inp_q -31 + move32(); + FOR( ch_idx = 1; ch_idx < nchan_ana; ch_idx++ ) + { + /* abs()^2 */ + FOR( j = brange[0]; j < brange[1]; j++ ) + { + reference_power[i] = L_add( reference_power[i], L_add( Mpy_32_32( Cldfb_RealBuffer[ch_idx][j], Cldfb_RealBuffer[ch_idx][j] ), Mpy_32_32( Cldfb_ImagBuffer[ch_idx][j], Cldfb_ImagBuffer[ch_idx][j] ) ) ); + move32(); + } + // 2*inp_q - 31 + } + } + v_multc_fixed( reference_power, ONE_IN_Q30, reference_power, num_freq_bands ); + test(); + IF( EQ_16( ivas_format, SBA_FORMAT ) && EQ_16( ref_power_w, 1 ) ) + { + FOR( i = 0; i < num_freq_bands; i++ ) + { + reference_power[i] = max( reference_power[i], reference_power_W[i] ); + move32(); + } + } + return; +} +#endif /*------------------------------------------------------------------------- * ivas_dirac_param_est_enc() * @@ -1608,3 +1689,117 @@ void computeDiffuseness_mdft( return; } +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * computeDiffuseness_mdft() + * + * + *------------------------------------------------------------------------*/ +void computeDiffuseness_mdft_fx( + Word32 **buffer_intensity[DIRAC_NUM_DIMS], + const Word32 *buffer_energy, + const Word16 num_freq_bands, + const UWord16 no_col_avg_diff, + Word32 *diffuseness, + Word16 *q_factor_intensity, + Word16 *q_factor_energy, + Word16 *q_diffuseness /*Ouput Q*/ +) +{ + Word32 intensity_slow[DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS]; + Word16 intensity_slow_e[DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS]; + Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS]; + Word16 intensity_slow_abs_e[MASA_FREQUENCY_BANDS]; + Word32 energy_slow[MASA_FREQUENCY_BANDS]; + Word16 energy_slow_e[MASA_FREQUENCY_BANDS]; + Word16 i, j, k; + Word32 tmp; + Word32 *p_tmp; + const Word32 *p_tmp_c; + Word16 *p_tmp_e, tmp_q; + + /* Compute Intensity slow and energy slow buffer_intensity and buffer_energy */ + + set_zero_fx( intensity_slow, i_mult( DIRAC_NUM_DIMS, MASA_FREQUENCY_BANDS ) ); + set16_fx( intensity_slow_e, 0, i_mult( DIRAC_NUM_DIMS, MASA_FREQUENCY_BANDS ) ); + set_zero_fx( intensity_slow_abs, MASA_FREQUENCY_BANDS ); + set16_fx( intensity_slow_abs_e, 0, no_col_avg_diff ); + set_zero_fx( energy_slow, MASA_FREQUENCY_BANDS ); + set16_fx( energy_slow_e, 0, no_col_avg_diff ); + + FOR( i = 0; i < no_col_avg_diff; ++i ) + { + /* Energy slow */ + p_tmp_c = buffer_energy + i_mult( i, num_freq_bands ); + tmp_q = q_factor_energy[i]; + move16(); + + FOR( k = 0; k < num_freq_bands; k++ ) + { + energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], p_tmp_c[k], sub( 31, tmp_q ), &energy_slow_e[k] ); + move32(); + } + + /* Intensity slow */ + FOR( j = 0; j < DIRAC_NUM_DIMS; ++j ) + { + p_tmp = buffer_intensity[j][i]; + FOR( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow[j * num_freq_bands + k] = BASOP_Util_Add_Mant32Exp( intensity_slow[j * num_freq_bands + k], intensity_slow_e[j * num_freq_bands + k], p_tmp[k], sub( 31, q_factor_intensity[i] ), &intensity_slow_e[j * num_freq_bands + k] ); + move32(); + } + } + } + + /* intensity_slow.^2 + intensity_slow_abs*/ + FOR( j = 0; j < DIRAC_NUM_DIMS; ++j ) + { + p_tmp = intensity_slow + i_mult( j, num_freq_bands ); + p_tmp_e = intensity_slow_e + i_mult( j, num_freq_bands ); + + FOR( k = 0; k < num_freq_bands; k++ ) + { + p_tmp[k] = Mpy_32_32( p_tmp[k], p_tmp[k] ); + move32(); + tmp_q = sub( shl( sub( 31, p_tmp_e[k] ), 1 ), 31 ); + intensity_slow_abs[k] = BASOP_Util_Add_Mant32Exp( intensity_slow_abs[k], intensity_slow_abs_e[k], p_tmp[k], sub( 31, tmp_q ), &intensity_slow_abs_e[k] ); + move32(); + } + } + + /* Compute Diffuseness */ + p_tmp = intensity_slow_abs; + tmp_q = 0; + move16(); + FOR( i = 0; i < num_freq_bands; ++i ) + { + tmp = Sqrt32( p_tmp[i], &intensity_slow_abs_e[i] ); + + tmp = L_deposit_h( BASOP_Util_Divide3232_Scale( tmp, L_add( energy_slow[i], EPSILLON_FX ), &tmp_q ) ); + tmp_q = add( tmp_q, sub( intensity_slow_abs_e[i], energy_slow_e[i] ) ); + tmp = L_shl_sat( tmp, tmp_q ); + tmp = L_sub( ONE_IN_Q31, tmp ); + diffuseness[i] = tmp; + move32(); + + IF( LT_32( tmp, ONE_IN_Q31 ) ) + { + IF( tmp < 0 ) + { + diffuseness[i] = 0; + move32(); + } + } + ELSE + { + diffuseness[i] = ONE_IN_Q31; + move32(); + } + } + *q_diffuseness = Q31; + move16(); + + return; +} +#endif diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index d37b71664e30a0c9c90e14c05f44da7050b3b59c..2e966212cffefedcfa76ac3c95f93b8de0fb4b24 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -741,21 +741,23 @@ ivas_error ivas_enc( test(); IF( ( EQ_32( ivas_format, SBA_FORMAT ) ) && !( GT_16( st_ivas->sba_analysis_order, 1 ) ) ) { +#ifndef IVAS_FLOAT_FIXED hp20_flt( data_f[HOA_keep_ind[st_ivas->hSpar->hMdEnc->HOA_md_ind[i]]], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); -#if 0 // To be enabled, precision loss observed +#else hp20_fix32( data_fx[HOA_keep_ind[st_ivas->hSpar->hMdEnc->HOA_md_ind[i]]], input_frame, st_ivas->mem_hp20_in_fx[i], input_Fs ); #endif } ELSE IF( !( EQ_32( ivas_format, MC_FORMAT ) && EQ_16( i, LFE_CHANNEL ) ) ) { +#ifndef IVAS_FLOAT_FIXED hp20_flt( data_f[i], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); // To be removed -#if 0 // To be enabled, precision loss observed +#else hp20_fix32( data_fx[i], input_frame, st_ivas->mem_hp20_in_fx[i], input_Fs ); #endif } } -#if 0 /* Fixed to float conversion To be removed */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS for ( i = 0; i < n; i++ ) { fixedToFloat_arrL( data_fx[i], data_f[i], st_ivas->q_data_fx, input_frame ); @@ -793,10 +795,48 @@ ivas_error ivas_enc( if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + floatToFixed_arr32( data_f[i], data_fx[i], Q14, input_frame ); + } + for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + st_ivas->hIsmMetaData[i]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[i]->azimuth, Q22 ); + st_ivas->hIsmMetaData[i]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[i]->elevation, Q22 ); + floatToFixed_arr32( st_ivas->hParamIsm->hFbMixer->ppFilterbank_prior_input[i], st_ivas->hParamIsm->hFbMixer->ppFilterbank_prior_input_fx[i], Q14, st_ivas->hParamIsm->hFbMixer->fb_cfg->prior_input_length ); + st_ivas->hParamIsm->last_cardioid_left_fx[i] = float_to_fix16( st_ivas->hParamIsm->last_cardioid_left[i], Q14 ); + } + st_ivas->hParamIsm->last_dmx_gain_e = 15 - norm_s( (Word16) st_ivas->hParamIsm->last_dmx_gain ); + st_ivas->hParamIsm->last_dmx_gain_fx = float_to_fix16( st_ivas->hParamIsm->last_dmx_gain, 15 - st_ivas->hParamIsm->last_dmx_gain_e ); +#endif + + ivas_param_ism_enc_fx( st_ivas, data_fx, input_frame, Q14 ); + + /* Stereo DMX generation */ + ivas_param_ism_stereo_dmx_fx( st_ivas, data_fx, input_frame ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + fixedToFloat_arrL32( data_fx[i], data_f[i], Q14, input_frame ); + } + for ( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + st_ivas->hIsmMetaData[i]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[i]->azimuth, Q22 ); + fixedToFloat_arrL32( st_ivas->hParamIsm->hFbMixer->ppFilterbank_prior_input_fx[i], st_ivas->hParamIsm->hFbMixer->ppFilterbank_prior_input[i], Q14, st_ivas->hParamIsm->hFbMixer->fb_cfg->prior_input_length ); + st_ivas->hParamIsm->last_cardioid_left[i] = fixedToFloat_16( st_ivas->hParamIsm->last_cardioid_left_fx[i], Q14 ); + } + + st_ivas->hParamIsm->last_dmx_gain = fixedToFloat_16( st_ivas->hParamIsm->last_dmx_gain_fx, 15 - st_ivas->hParamIsm->last_dmx_gain_e ); +#endif +#else ivas_param_ism_enc( st_ivas, data_f, input_frame ); /* Stereo DMX generation */ ivas_param_ism_stereo_dmx( st_ivas, data_f, input_frame ); +#endif /* Core coding of Stereo DMX */ if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, nb_bits_metadata, 0 ) ) != IVAS_ERR_OK ) @@ -908,7 +948,7 @@ ivas_error ivas_enc( if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) { /* Estimate MASA parameters for the objects */ - ivas_omasa_enc( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hIsmMetaData, data_f, input_frame, st_ivas->nchan_transport, hEncoderConfig->nchan_ism, st_ivas->ism_mode, data_separated_object, &idx_separated_object ); + ivas_omasa_enc( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hIsmMetaData, data_f, data_fx, st_ivas->q_data_fx, input_frame, st_ivas->nchan_transport, hEncoderConfig->nchan_ism, st_ivas->ism_mode, data_separated_object, &idx_separated_object ); } /* Encode ISMs transport channels */ @@ -929,7 +969,11 @@ ivas_error ivas_enc( } else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) { - flag_omasa_ener_brate = ivas_omasa_ener_brate( st_ivas->hEncoderConfig->nchan_ism, ivas_total_brate, data_f, input_frame ); +#ifdef IVAS_FLOAT_FIXED + flag_omasa_ener_brate = ivas_omasa_ener_brate_fx( st_ivas->hEncoderConfig->nchan_ism, ivas_total_brate, data_fx, input_frame, sub( 31, st_ivas->q_data_fx ) ); +#else + flag_omasa_ener_brate = ivas_omasa_ener_brate( st_ivas->hEncoderConfig->nchan_ism, ivas_total_brate, data_fx, input_frame, sub( 31, st_ivas->q_data_fx ) ); +#endif // IVAS_FLOAT_FIXED /* Analysis, decision about bitrates per channel & core coding */ if ( ( error = ivas_ism_enc( st_ivas, data_f, input_frame, &nb_bits_metadata[1], flag_omasa_ener_brate ) ) != IVAS_ERR_OK ) @@ -973,10 +1017,25 @@ ivas_error ivas_enc( { int16_t planar_sba_orig; planar_sba_orig = hEncoderConfig->sba_planar; - +#ifdef IVAS_FLOAT_FIXED + /* Analyze objects and determine needed audio signals */ + ivas_osba_enc_fx( st_ivas->hOSba, st_ivas->hIsmMetaData, data_fx, input_frame, hEncoderConfig->nchan_ism, st_ivas->ism_mode, st_ivas->sba_analysis_order, hEncoderConfig->input_Fs, hEncoderConfig->sba_planar, &st_ivas->q_data_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 nchan; + if ( st_ivas->ism_mode == ISM_MODE_NONE ) + nchan = ( st_ivas->sba_analysis_order + 1 ) * ( st_ivas->sba_analysis_order + 1 ); + else + nchan = hEncoderConfig->nchan_ism; + for ( n = 0; n < nchan; n++ ) + { + fixedToFloat_arrL32( data_fx[n], data_f[n], st_ivas->q_data_fx, input_frame ); + } +#endif +#else /* Analyze objects and determine needed audio signals */ ivas_osba_enc( st_ivas->hOSba, st_ivas->hIsmMetaData, data_f, input_frame, hEncoderConfig->nchan_ism, st_ivas->ism_mode, st_ivas->sba_analysis_order, hEncoderConfig->input_Fs, hEncoderConfig->sba_planar ); +#endif if ( st_ivas->ism_mode == ISM_MODE_NONE ) { /*once SBA and ISM are combined into SBA signal then disable planar flag*/ @@ -1090,8 +1149,12 @@ ivas_error ivas_enc( else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) { /* encode MC ParamUpmix parameters and write bitstream */ +#ifdef IVAS_FLOAT_FIXED + ivas_mc_paramupmix_enc( st_ivas, hMetaData, data_f, data_fx, input_frame ); +#else ivas_mc_paramupmix_enc( st_ivas, hMetaData, data_f, input_frame ); +#endif st_ivas->hLFE->hBstr = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0]->hBstr : st_ivas->hCPE[0]->hCoreCoder[0]->hBstr; ivas_lfe_enc_fx( st_ivas->hLFE, data_fx[LFE_CHANNEL], st_ivas->q_data_fx, input_frame, st_ivas->hLFE->hBstr ); @@ -1129,9 +1192,40 @@ ivas_error ivas_enc( { hMetaData = st_ivas->hCPE[0]->hMetaData; /* Metadata is always with CPE in the case of separated channel */ } - +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_data = Q8; + for ( i = 0; i < nchan_inp; i++ ) + { + floatToFixed_arrL32( data_f[i], data_fx[i], q_data, input_frame ); + } +#endif + ivas_mcmasa_enc_fx( st_ivas->hMcMasa, st_ivas->hQMetaData, st_ivas->hMasa, data_fx, input_frame, st_ivas->nchan_transport, nchan_inp, q_data ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + st_ivas->hMasa->data.lfeToTotalEnergyRatio[i] = st_ivas->hMasa->data.lfeToTotalEnergyRatio_fx[i] / (float) ( 1 << ( Q31 - st_ivas->hMasa->data.lfeToTotalEnergyRatio_e[i] ) ); + } + for ( i = 0; i < nchan_inp; i++ ) + { + fixedToFloat_arrL( data_fx[i], data_f[i], q_data, input_frame ); + } + Word32 ii, jj; + Word16 nBands = st_ivas->hMcMasa->nbands; + Word16 nBlocks = MAX_PARAM_SPATIAL_SUBFRAMES; + FOR( ii = 0; ii < nBands; ii++ ) + { + FOR( jj = 0; jj < nBlocks; jj++ ) + { + st_ivas->hQMetaData->q_direction[0].band_data[ii].azimuth[jj] = fixedToFloat( st_ivas->hQMetaData->q_direction[0].band_data[ii].azimuth_fx[jj], Q22 ); + st_ivas->hQMetaData->q_direction[0].band_data[ii].elevation[jj] = fixedToFloat( st_ivas->hQMetaData->q_direction[0].band_data[ii].elevation_fx[jj], Q22 ); + st_ivas->hQMetaData->q_direction[0].band_data[ii].energy_ratio[jj] = fixedToFloat( st_ivas->hQMetaData->q_direction[0].band_data[ii].energy_ratio_fx[jj], Q31 ); + } + } +#endif +#else ivas_mcmasa_enc( st_ivas->hMcMasa, st_ivas->hQMetaData, st_ivas->hMasa, data_f, input_frame, st_ivas->nchan_transport, nchan_inp ); - +#endif if ( ( error = ivas_masa_encode( st_ivas->hMasa, st_ivas->hQMetaData, hMetaData, &nb_bits_metadata[0], st_ivas->nchan_transport, ivas_format, ivas_total_brate, 0, -1, ISM_MODE_NONE, -1, NULL, -1, NULL, 0, 0 ) ) != IVAS_ERR_OK ) { diff --git a/lib_enc/ivas_front_vad.c b/lib_enc/ivas_front_vad.c index 95ead975af07e91064352e1c0d4a7753be3dc983..34eab69e8b064177d95219881921556c32ed51aa 100644 --- a/lib_enc/ivas_front_vad.c +++ b/lib_enc/ivas_front_vad.c @@ -52,7 +52,7 @@ * * Standalone front-VAD module *-----------------------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error front_vad( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure, nullable */ Encoder_State *st, /* i/o: encoder state structure */ @@ -125,7 +125,7 @@ ivas_error front_vad( { for ( n = 0; n < n_chan; n++ ) { - front_vad_destroy( &hFrontVads[n] ); + front_vad_destroy_fx( &hFrontVads[n] ); hFrontVads[n] = NULL; } } @@ -242,7 +242,262 @@ ivas_error front_vad( pop_wmops(); return error; } +#else +ivas_error front_vad_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure, nullable */ + Encoder_State *st, /* i/o: encoder state structure */ + const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */ + FRONT_VAD_ENC_HANDLE *hFrontVads, /* i/o: FrontVad handles */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const Word16 input_frame, /* i : frame length */ + Word16 vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ + Word32 fr_bands_fx[][2 * NB_BANDS], /* o : energy in frequency bands Q_buffer[n] + QSCALE + 2 */ + Word16 Etot_LR_fx[], /* o : total energy Left & Right channel Q8 */ + Word32 lf_E_fx[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels Q_buffer[n] + QSCALE */ + Word16 localVAD_HE_SAD[], /* o : HE-SAD flag without hangover, LR channels */ + Word16 vad_hover_flag[], /* o : VAD hangover flag */ + Word32 band_energies_LR_fx[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN Q_buffer[1] + QSCALE + 2 - band_ener_guardbits*/ + Word32 *PS_out_fx, /* o : energy spectrum Q_buffer + QSCALE */ + Word16 *Bin_E_out_fx, /* o : log-energy spectrum of the current frame Q7 */ + Word16 Q_inp, + Word16 *Q_buffer, + Word16 Q_add, + Word16 *front_create_flag ) +{ + ENC_CORE_HANDLE *sts; + Word32 band_energies_fx[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 PS_fx[128]; + Word16 *lgBin_E_fx; + Word16 snr_sum_he_fx; + // Word32 fr_bands_cp_fx[2 * NB_BANDS] = { 0 }; + Word32 Bin_E_fx[L_FFT] = { 0 }; /* per bin log energy spectrum for mid-frame */ + Word32 Bin_E_old_fx[L_FFT / 2] = { 0 }; /* old per bin log energy spectrum for mid-frame */ + Word16 fft_buffLR_fx[2 * L_FFT]; /* fft buffer */ + // Word16 front_create_flag = 0; + Word16 n, n_chan, dummy; + Word8 dummy_short; + Word16 element_mode, last_element_mode; + ivas_error error; + Word16 Q_new = 0, band_ener_guardbits = 0; + Word16 Qband, mem_decim_size; + error = IVAS_ERR_OK; + push_wmops( "front_vad" ); + lgBin_E_fx = NULL; + if ( st != NULL ) + { + lgBin_E_fx = &st->lgBin_E_fx[0]; + move16(); + } + IF( hCPE != NULL ) + { + n_chan = CPE_CHANNELS; + sts = &hCPE->hCoreCoder[0]; + element_mode = hCPE->element_mode; + move16(); + last_element_mode = hCPE->last_element_mode; + move16(); + } + ELSE IF( st != NULL ) + { + n_chan = 1; + move16(); + sts = &st; + element_mode = IVAS_SCE; + move16(); + last_element_mode = IVAS_SCE; + move16(); + } + ELSE + { + assert( 0 && "Either CPE or SCE must be given!" ); + return IVAS_ERR_INTERNAL_FATAL; + } + + FOR( n = 0; n < n_chan; n++ ) + { + localVAD_HE_SAD[n] = 0; + move16(); + vad_hover_flag[n] = 0; + move16(); + vad_flag_dtx[n] = 1; + move16(); + } + + /*------------------------------------------------------------------* + * Allocate/deallocate hFrontVad handles in case of element_mode change + *-----------------------------------------------------------------*/ + test(); + test(); + IF( sts[0]->ini_frame > 0 && MCT_flag == 0 && NE_16( last_element_mode, element_mode ) ) + { + IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) + { + IF( hFrontVads[0] != NULL ) + { + FOR( n = 0; n < n_chan; n++ ) + { + front_vad_destroy_fx( &hFrontVads[n] ); + hFrontVads[n] = NULL; + } + } + } + ELSE + { + test(); + IF( sts[0]->Opt_DTX_ON && hFrontVads[0] == NULL ) + { + for ( n = 0; n < n_chan; n++ ) + { + *front_create_flag = 1; + move16(); + IF( NE_32( ( error = front_vad_create_fx( &hFrontVads[n], hEncoderConfig ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } + } + } + test(); + /* Only run VAD if DTX is on and TD stereo or unified stereo is selected */ + IF( hFrontVads[0] != NULL && NE_16( element_mode, IVAS_CPE_MDCT ) ) + { + + /*------------------------------------------------------------------* + * VAD + *-----------------------------------------------------------------*/ + set_val_Word32( band_energies_LR_fx, 0, 2 * NB_BANDS ); + Qband = -1; + move16(); + Word16 Q_new_old = add( sub( Q_inp, Qband ), Q_add ); + + IF( *front_create_flag ) + { + FOR( n = 0; n < n_chan; n++ ) + { + scale_sig32( hFrontVads[n]->hNoiseEst->bckr_fx, 20, sub( add( Q_new_old, QSCALE ), Q11 ) ); + scale_sig32( hFrontVads[n]->hNoiseEst->enrO_fx, 20, sub( add( Q_new_old, QSCALE ), Q11 ) ); + hFrontVads[n]->lp_speech_fx = shr( hFrontVads[n]->lp_speech_fx, 1 ); + move16(); + } + } + band_ener_guardbits = find_guarded_bits_fx( 2 * NB_BANDS ); + FOR( n = 0; n < n_chan; n++ ) + { + FRONT_VAD_ENC_HANDLE hFrontVad; + hFrontVad = hFrontVads[n]; + + /* Move previous frame 12k8 signal */ + + MVR2R_WORD16( hFrontVad->buffer_12k8_fx + L_FFT, hFrontVad->buffer_12k8_fx, L_FFT / 2 ); + + /* Resample to 12k8 */ + modify_Fs_fx( sts[n]->input_fx, input_frame, sts[0]->input_Fs, hFrontVad->buffer_12k8_fx + L_FFT / 2, INT_FS_12k8, hFrontVad->mem_decim_fx, ( sts[0]->max_bwidth == NB ), &Qband, &mem_decim_size ); + + /* Preemphasis */ + hFrontVad->mem_preemph_fx = shl( hFrontVad->mem_preemph_fx, -1 - Qband ); + + PREEMPH_FX( hFrontVad->buffer_12k8_fx + L_FFT / 2, PREEMPH_FAC, L_FRAME, &hFrontVad->mem_preemph_fx ); + + Word16 Scale_fac[2]; + Q_new = add( sub( Q_inp, Qband ), Q_add ); + Scale_sig( hFrontVad->buffer_12k8_fx, L_FFT / 2, Q_new - Q_buffer[n] ); + Scale_sig( hFrontVad->buffer_12k8_fx + L_FFT / 2, 384 - L_FFT / 2, Q_new - add( Q_inp, Qband ) ); + + Q_buffer[n] = Q_new; + Word32 Le_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_new, QSCALE ) ) ), 1 ), 1 ); + Le_min_scaled = L_shl( Le_min_scaled, 2 ); + ivas_analy_sp_fx( IVAS_CPE_TD, hCPE, sts[0]->input_Fs, hFrontVad->buffer_12k8_fx + L_FFT / 2 - 3 * ( L_SUBFR / 2 ), Q_new, fr_bands_fx[n], lf_E_fx[n], &Etot_LR_fx[n], sts[0]->min_band, sts[0]->max_band, Le_min_scaled, Scale_fac, Bin_E_fx, Bin_E_old_fx, PS_fx, lgBin_E_fx, band_energies_fx, fft_buffLR_fx ); + + /* add up energies for later calculating average of channel energies */ + // Scale_sig32( &band_energies_LR_fx[0], ( Q_new + QSCALE + 2 ) - ( Q_new_old + QSCALE + 2 - band_ener_guardbits ), 40 ); + Q_new_old = Q_new; + v_add_fixed( &band_energies_fx[0], &band_energies_LR_fx[0], &band_energies_LR_fx[0], 2 * NB_BANDS, band_ener_guardbits ); + + Word32 Etot_fx = L_deposit_h( Etot_LR_fx[n] ); + + noise_est_pre_32fx( Etot_fx, hFrontVads[0]->ini_frame, hFrontVad->hNoiseEst, 0, 0, 0 ); + + /* wb_vad */ + Scale_sig32( hFrontVads[n]->hNoiseEst->bckr_fx, Q_new + QSCALE - ( Q_new_old + QSCALE ), 20 ); + Scale_sig32( hFrontVads[n]->hNoiseEst->enrO_fx, Q_new + QSCALE - ( Q_new_old + QSCALE ), 20 ); + hFrontVad->hNoiseEst->sign_dyn_lp_fx = extract_h( hFrontVad->hNoiseEst->sign_dyn_lp_32fx ); + hFrontVad->hNoiseEst->Etot_v_h2_fx = extract_h( hFrontVad->hNoiseEst->Etot_v_h2_32fx ); + hFrontVad->hVAD->vad_flag = wb_vad_ivas_fx( sts[n], fr_bands_fx[n], &dummy, &dummy, &dummy, &snr_sum_he_fx, &localVAD_HE_SAD[n], &dummy_short, Q_new, hFrontVad->hVAD, hFrontVad->hNoiseEst, hFrontVad->lp_speech_fx, hFrontVad->lp_noise_fx ); + + test(); + test(); + if ( n == 0 && GT_16( n_chan, 1 ) && EQ_16( last_element_mode, IVAS_CPE_DFT ) ) + { + sts[1]->last_coder_type = sts[0]->last_coder_type; + move16(); + } + vad_flag_dtx[n] = ivas_dtx_hangover_addition_fx( sts[n], hFrontVad->hVAD->vad_flag, hFrontVad->lp_speech_fx - hFrontVad->lp_noise_fx, 0 /* <- no cldfb addition */, &vad_hover_flag[n], hFrontVad->hVAD, hFrontVad->hNoiseEst, &hFrontVads[n]->rem_dtx_ho ); + move16(); + + if ( EQ_16( n_chan, 1 ) ) + { + sts[n]->vad_flag = hFrontVad->hVAD->vad_flag; + move16(); + } + } + + IF( EQ_16( n_chan, CPE_CHANNELS ) ) + { + /* get average channel energies, adding up was already done, so only need to scale by number of channels */ + v_multc_fixed( &band_energies_LR_fx[0], ONE_IN_Q30, &band_energies_LR_fx[0], 2 * NB_BANDS ); + + /* Logical OR between L and R decisions */ + vad_flag_dtx[0] = vad_flag_dtx[0] || vad_flag_dtx[1]; + } + IF( sts[0]->hFdCngEnc != NULL ) + { + resetFdCngEnc_fx( sts[0] ); + } + test(); + /* Part of DTX to decide if SID/NO_DATA */ + IF( vad_flag_dtx[0] == 0 && GT_16( sts[0]->ini_frame, 2 ) ) /* CNG coding starts after 3 frames */ + { + IF( sts[0]->fd_cng_reset_flag == 0 ) + { + if ( hCPE != NULL ) + { + hCPE->element_mode = IVAS_CPE_DFT; + move16(); + sts[1]->active_cnt = 0; + move16(); + } + } + ELSE + { + vad_flag_dtx[0] = 1; + move16(); + } + } + ELSE + { + vad_flag_dtx[0] = 1; + move16(); + } + } + + IF( PS_out_fx != NULL ) + { + MVR2R_WORD32( PS_fx, PS_out_fx, L_FRAME / 2 ); + } + + IF( Bin_E_out_fx != NULL ) + { + + MVR2R_WORD16( lgBin_E_fx, Bin_E_out_fx, L_FRAME / 2 ); + } + + pop_wmops(); + return error; +} + +#endif /*-----------------------------------------------------------------------------------------* * Function front_vad_create() @@ -266,18 +521,29 @@ ivas_error front_vad_create( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); } +#ifdef IVAS_FLOAT_FIXED + noise_est_init_ivas_fx( hFrontVad->hNoiseEst ); +#else noise_est_init( hFrontVad->hNoiseEst ); - +#endif if ( ( hFrontVad->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } - wb_vad_init( hFrontVad->hVAD ); - hFrontVad->lp_speech = 45.0f; /* Initialize the long-term active speech level in dB */ - hFrontVad->lp_noise = 0.0f; /* Initialize the long-term noise level in dB */ set_f( hFrontVad->mem_decim, 0, 2 * L_FILT_MAX ); set_f( hFrontVad->buffer_12k8, 0, 3 * L_FRAME / 2 ); +#ifdef IVAS_FLOAT_FIXED + wb_vad_init_ivas_fx( hFrontVad->hVAD ); + hFrontVad->lp_speech_fx = 11520; /* Initialize the long-term active speech level in dB */ + hFrontVad->lp_noise_fx = 0; /* Initialize the long-term noise level in dB */ + set16_fx( hFrontVad->mem_decim_fx, 0, shl( L_FILT_MAX, 1 ) ); + set16_fx( hFrontVad->buffer_12k8_fx, 0, i_mult( 3, shr( L_FRAME, 1 ) ) ); + hFrontVad->mem_preemph_fx = 0; +#else + wb_vad_init( hFrontVad->hVAD ); +#endif hFrontVad->mem_preemph = 0; hFrontVad->ini_frame = 0; hFrontVad->hVAD->vad_flag = 1; @@ -293,7 +559,9 @@ ivas_error front_vad_create( } set_f( hFrontVad->delay_buf, 0, hFrontVad->delay_samples ); } - +#ifdef IVAS_FLOAT_FIXED + hFrontVad->delay_buf_fx = NULL; +#endif *hFrontVad_out = hFrontVad; return IVAS_ERR_OK; @@ -315,7 +583,7 @@ ivas_error front_vad_create_fx( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); } - noise_est_init_fx( hFrontVad->hNoiseEst ); + noise_est_init_ivas_fx( hFrontVad->hNoiseEst ); IF( ( hFrontVad->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) { @@ -323,16 +591,22 @@ ivas_error front_vad_create_fx( } wb_vad_init_ivas_fx( hFrontVad->hVAD ); - hFrontVad->lp_speech_fx = 23040; /* Initialize the long-term active speech level in dB */ - hFrontVad->lp_noise_fx = 0; /* Initialize the long-term noise level in dB */ + hFrontVad->lp_speech_fx = 23040; // Q9/* Initialize the long-term active speech level in dB */ + move16(); + hFrontVad->lp_noise_fx = 0; /* Initialize the long-term noise level in dB */ + move16(); set16_fx( hFrontVad->mem_decim_fx, 0, shl( L_FILT_MAX, 1 ) ); set16_fx( hFrontVad->buffer_12k8_fx, 0, i_mult( 3, shr( L_FRAME, 1 ) ) ); hFrontVad->mem_preemph_fx = 0; + move16(); hFrontVad->ini_frame = 0; + move16(); hFrontVad->hVAD->vad_flag = 1; + move16(); /* allocate delay buffer to compensate for filterbank delay */ hFrontVad->delay_samples = NS2SA( hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ); + move16(); hFrontVad->delay_buf_fx = NULL; IF( GT_16( hFrontVad->delay_samples, 0 ) ) { @@ -343,6 +617,18 @@ ivas_error front_vad_create_fx( set16_fx( hFrontVad->delay_buf_fx, 0, hFrontVad->delay_samples ); } +#if 1 + hFrontVad->delay_buf = NULL; // Inorder to avoid issue in front_vad_distroy_fx call , Will have to be removed later + if ( hFrontVad->delay_samples > 0 ) + { + if ( ( hFrontVad->delay_buf = (float *) malloc( hFrontVad->delay_samples * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD delay buffer\n" ) ); + } + set_f( hFrontVad->delay_buf, 0, hFrontVad->delay_samples ); + } +#endif + *hFrontVad_out = hFrontVad; return IVAS_ERR_OK; @@ -379,8 +665,36 @@ void front_vad_destroy( return; } +#ifdef IVAS_FLOAT_FIXED +void front_vad_destroy_fx( + FRONT_VAD_ENC_HANDLE *hFrontVad /* i/o: front-VAD handle */ +) +{ + IF( *hFrontVad != NULL ) + { + free( ( *hFrontVad )->hNoiseEst ); + ( *hFrontVad )->hNoiseEst = NULL; + free( ( *hFrontVad )->hVAD ); + ( *hFrontVad )->hVAD = NULL; + + IF( ( *hFrontVad )->delay_buf_fx != NULL ) + { + free( ( *hFrontVad )->delay_buf_fx ); + ( *hFrontVad )->delay_buf_fx = NULL; + } + IF( ( *hFrontVad )->delay_buf != NULL ) + { + free( ( *hFrontVad )->delay_buf ); + ( *hFrontVad )->delay_buf = NULL; + } + free( *hFrontVad ); + *hFrontVad = NULL; + } + return; +} +#endif /*-----------------------------------------------------------------------------------------* * Function front_vad_spar() * @@ -395,7 +709,8 @@ ivas_error front_vad_spar( ) { FRONT_VAD_ENC_HANDLE hFrontVad; - float input[L_FRAME48k]; + float input[L_FRAME48k] = { 0 }; + Word16 input_fx[L_FRAME48k]; int16_t vad_flag_dtx[1]; float fr_bands[1][2 * NB_BANDS]; Word32 fr_bands_fx[1][2 * NB_BANDS] = { { 0 } }; @@ -406,25 +721,27 @@ ivas_error front_vad_spar( int16_t localVAD_HE_SAD[1]; int16_t vad_hover_flag[1]; float band_energies[2 * NB_BANDS]; + Word32 band_energies_fx[2 * NB_BANDS]; int16_t high_lpn_flag; Encoder_State *st; float tmpN[NB_BANDS], tmpE[NB_BANDS]; Word32 tmpN_fx[NB_BANDS] = { 0 }; Word32 tmpE_fx[NB_BANDS] = { 0 }; float corr_shift; - float dummy, res_energy; + // float res_energy; + // float ncharX; + // float sp_div, dummy; Word16 corr_shift_fx; #if 1 - // Word32 res_energy_fx; + Word32 res_energy_fx; Word16 A_fx[NB_SUBFR16k * ( M + 1 )], Aw_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 Q_esp; + Word32 epsP_fx[M + 1]; -// Word32 epsP_fx[M + 1]; -// Word16 epsP_h[M + 1]; -// Word16 epsP_l[M + 1]; -// Word16 alw_voicing_fx[2]; -// Word16 lsp_new_fx[M]; -// Word16 lsp_mid_fx[M]; + Word16 alw_voicing_fx[2]; + Word16 lsp_new_fx[M]; + Word16 lsp_mid_fx[M]; #endif float A[NB_SUBFR16k * ( M + 1 )], Aw[NB_SUBFR16k * ( M + 1 )]; float epsP[M + 1]; @@ -433,28 +750,26 @@ ivas_error front_vad_spar( int16_t alw_pitch_lag_12k8[2]; float alw_voicing[2]; float cor_map_sum; - float ncharX; - float sp_div; float non_staX; int16_t loc_harm; float S_map[L_FFT / 2]; #if 1 - - - // Word32 lf_E_fx[1][2 * VOIC_BINS]; - - - // Word16 non_staX_fx; - + Word16 epsP_h[M + 1]; + Word16 epsP_l[M + 1]; + Word32 lf_E_fx[1][2 * VOIC_BINS]; + + Word16 sp_div_fx; + Word16 Q_sp_div; + Word16 non_staX_fx; + Word16 sp_floor; +#else + float ncharX; + float sp_div, dummy; #endif - - // Word16 sp_floor; - // Word16 sp_div_fx; - // Word16 Q_sp_div; Word16 cor_map_sum_fx; Word16 dummy_fx; Word16 S_map_fx[L_FFT / 2]; - // Word16 relE_fx; + Word16 relE_fx; Word16 *wsp_fx; float *inp_12k8; #if 1 @@ -468,6 +783,7 @@ ivas_error front_vad_spar( int16_t flag_spitch; float PS[L_FRAME / 2]; + Word32 PS_fx[L_FRAME / 2]; int16_t old_pitch; ivas_error error; #ifdef DUMP_VAD_SPAR @@ -501,16 +817,16 @@ ivas_error front_vad_spar( inp_12k8 = hFrontVad->buffer_12k8; Word16 Q_bands = Q31; #if 1 - Word16 Q_inp_12k8 = Q10; + Word16 Q_inp_12k8 = Q9; #endif #if 1 inp_12k8_fx = hFrontVad->buffer_12k8_fx; #endif mvr2r( st->old_wsp, old_wsp, L_WSP_MEM ); - floatToFixed_arr( st->old_wsp, st->old_wsp_fx, Q10, L_WSP_MEM ); - floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q10, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q10, 3 ); + floatToFixed_arr( st->old_wsp, st->old_wsp_fx, Q9, L_WSP_MEM ); + floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q9, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q9, 3 ); // st->mem_wsp_fx = (Word16) floatToFixed( st->mem_wsp, Q_inp_12k8 ); MVR2R_WORD16( st->old_wsp_fx, old_wsp_fx, L_WSP_MEM ); @@ -523,21 +839,89 @@ ivas_error front_vad_spar( /*------------------------------------------------------------------* * compensate for SPAR filterbank delay *-----------------------------------------------------------------*/ - + Q_bands = Q9; st->input = input; + st->input_fx = input_fx; mvr2r( omni_in, st->input, input_frame ); - delay_signal_float( st->input, input_frame, hFrontVad->delay_buf, hFrontVad->delay_samples ); - + Word16 Q_inp; + Q_inp = Q_factor_arr( st->input, L_FRAME48k ); +#if 0 + FILE *fp = fopen( "input_before.txt", "ab+" ); + for ( int i = 0; i < L_FRAME48k; i++ ) + { + fprintf( fp, "%d\t", i ); + fprintf( fp, "%f\n", st->input[i] ); + } + fclose( fp ); +#endif + floatToFixed_arr( st->input, st->input_fx, Q_inp, L_FRAME48k ); + Word16 Q_add = 0; + move16(); /*------------------------------------------------------------------* * Front-VAD *-----------------------------------------------------------------*/ - +#if 0 if ( ( error = front_vad( NULL, st, hEncoderConfig, &hFrontVad, 0 /* MCT_flag */, input_frame, vad_flag_dtx, fr_bands, Etot, lf_E, localVAD_HE_SAD, vad_hover_flag, band_energies, &PS[0], &st->Bin_E[0] ) ) != IVAS_ERR_OK ) { return error; } - Q_bands = Q10; +#else + // Word16 n_chan = 1; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 front_create_flag = 0; + move16(); + Word16 Qband = -1; + move16(); + Word16 Q_new_old = add( sub( Q_inp, Qband ), Q_add ); + Word16 band_ener_guardbits = find_guarded_bits_fx( 2 * NB_BANDS ); + floatToFixed_arr( hFrontVad->mem_decim, hFrontVad->mem_decim_fx, Q_inp, 90 ); + hFrontVad->mem_preemph_fx = (Word16) floatToFixed( hFrontVad->mem_preemph, Q_inp - 1 ); + Word16 Q_buffer = Q_factor_arr( hFrontVad->buffer_12k8 + L_FFT, L_FFT / 2 ); + floatToFixed_arr( hFrontVad->buffer_12k8, hFrontVad->buffer_12k8_fx, Q_buffer, 384 ); + hFrontVad->hNoiseEst->Etot_l_lp_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_l_lp * 16777216.0 ); + hFrontVad->hNoiseEst->Etot_last_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_last * 16777216.0 ); + hFrontVad->hNoiseEst->Etot_v_h2_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_v_h2 * 16777216.0 ); + hFrontVad->hNoiseEst->Etot_lp_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_lp * 16777216.0 ); + hFrontVad->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( hFrontVad->hNoiseEst->sign_dyn_lp * 16777216.0 ); + st->lp_speech_fx = (Word16) floatToFixed( st->lp_speech, Q8 ); + st->lp_noise_fx = (Word16) floatToFixed( st->lp_noise, Q8 ); + floatToFixed_arrL( hFrontVad->hNoiseEst->bckr, hFrontVad->hNoiseEst->bckr_fx, Q_new_old + QSCALE + 2, 20 ); + floatToFixed_arrL( hFrontVad->hNoiseEst->enrO, hFrontVad->hNoiseEst->enrO_fx, Q_new_old + QSCALE + 2, 20 ); + st->flag_noisy_speech_snr_fx = (Word8) st->flag_noisy_speech_snr; + floatToFixed_arrL( &band_energies[0], &band_energies_fx[0], Q_new_old + QSCALE + 2, 40 ); +#endif + if ( ( error = front_vad_fx( NULL, st, hEncoderConfig, &hFrontVad, 0 /* MCT_flag */, input_frame, vad_flag_dtx, fr_bands_fx, Etot_fx, lf_E_fx, localVAD_HE_SAD, vad_hover_flag, band_energies_fx, &PS_fx[0], &st->lgBin_E_fx[0], Q_inp, &Q_buffer, Q_add, &front_create_flag ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // fixedToFloat_arrL( &band_energies_LR_fx[0], &band_energies_LR[0], Q_new + QSCALE + 2 - band_ener_guardbits, 40 ); + fixedToFloat_arr( hFrontVad->mem_decim_fx, hFrontVad->mem_decim, Q_inp, 90 ); + hFrontVad->mem_preemph = fixedToFloat( hFrontVad->mem_preemph_fx, Q_inp + Qband ); + fixedToFloat_arr( hFrontVad->buffer_12k8_fx, hFrontVad->buffer_12k8, Q_buffer, 384 ); + fixedToFloat_arrL( fr_bands_fx[0], fr_bands[0], Q_buffer + QSCALE + 2, 40 ); + fixedToFloat_arrL( lf_E_fx[0], lf_E[0], Q_buffer + QSCALE, 148 ); + if ( st->lgBin_E_fx != NULL ) + { + fixedToFloat_arr( st->lgBin_E_fx, st->Bin_E, Q7, 128 ); + } + fixedToFloat_arrL( PS_fx, PS, Q_buffer + QSCALE, 128 ); + Etot[0] = fixedToFloat( Etot_fx[0], Q8 ); + hFrontVad->hNoiseEst->Etot_l_lp = (float) ( hFrontVad->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); + hFrontVad->hNoiseEst->Etot_last = (float) ( hFrontVad->hNoiseEst->Etot_last_32fx / 16777216.0 ); + // hFrontVad->hNoiseEst->Etot_v_h2 = (float) ( hFrontVad->hNoiseEst->Etot_v_h2_32fx / 16777216.0 ); + hFrontVad->hNoiseEst->Etot_lp = (float) ( hFrontVad->hNoiseEst->Etot_lp_32fx / 16777216.0 ); + // hFrontVad->hNoiseEst->sign_dyn_lp = (float) ( hFrontVad->hNoiseEst->sign_dyn_lp_32fx / 16777216.0 ); + + hFrontVad->hNoiseEst->Etot_v_h2 = (float) ( hFrontVad->hNoiseEst->Etot_v_h2_fx / ( 256.0 ) ); + hFrontVad->hNoiseEst->sign_dyn_lp = (float) ( hFrontVad->hNoiseEst->sign_dyn_lp_fx / ( 256.0 ) ); + fixedToFloat_arrL( &band_energies_fx[0], &band_energies[0], Q_buffer + QSCALE + 2 - band_ener_guardbits, 40 ); +#endif +#endif + + Word32 e_min_scaled; + e_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_bands, QSCALE ) ) ), 1 ), 1 ); // floatToFixed_arr( inp_12k8, inp_12k8_fx, Q_inp_12k8, 3 * L_FRAME / 2 ); // Q_bands = Q_factor_arrL( fr_bands[0], 2 * NB_BANDS ); floatToFixed_arrL( fr_bands[0], fr_bands_fx[0], Q_bands + QSCALE, 2 * NB_BANDS ); @@ -545,11 +929,10 @@ ivas_error front_vad_spar( #ifndef MSAN_FIX floatToFixed_arrL( tmpE, tmpE_fx, Q_bands + QSCALE, NB_BANDS ); #endif - hFrontVad->hNoiseEst->totalNoise_fx = (Word16) ( hFrontVad->hNoiseEst->totalNoise * ONE_IN_Q8 ); Etot_fx[0] = (Word16) ( Etot[0] * ONE_IN_Q8 ); hFrontVad->hNoiseEst->Etot_last_fx = (Word16) ( hFrontVad->hNoiseEst->Etot_last * ONE_IN_Q8 ); hFrontVad->hNoiseEst->Etot_v_h2_fx = (Word16) ( hFrontVad->hNoiseEst->Etot_v_h2 * ONE_IN_Q8 ); - noise_est_down_fx( fr_bands_fx[0], hFrontVad->hNoiseEst->bckr_fx, tmpN_fx, tmpE_fx, st->min_band, st->max_band, &hFrontVad->hNoiseEst->totalNoise_fx, Etot_fx[0], &hFrontVad->hNoiseEst->Etot_last_fx, &hFrontVad->hNoiseEst->Etot_v_h2_fx, Q_bands, Q_bands + QSCALE ); + noise_est_down_fx( fr_bands_fx[0], hFrontVad->hNoiseEst->bckr_fx, tmpN_fx, tmpE_fx, st->min_band, st->max_band, &hFrontVad->hNoiseEst->totalNoise_fx, Etot_fx[0], &hFrontVad->hNoiseEst->Etot_last_fx, &hFrontVad->hNoiseEst->Etot_v_h2_fx, Q_bands, e_min_scaled ); // noise_est_down( fr_bands[0], hFrontVad->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &hFrontVad->hNoiseEst->totalNoise, Etot[0], &hFrontVad->hNoiseEst->Etot_last, &hFrontVad->hNoiseEst->Etot_v_h2 ); #ifdef DUMP_VAD_SPAR for ( Word16 i = 0; i < 20; i++ ) @@ -561,7 +944,6 @@ ivas_error front_vad_spar( #endif // fixedToFloat_arrL( fr_bands_fx[0], fr_bands[0], Q_bands, 2 * NB_BANDS ); fixedToFloat_arrL( hFrontVad->hNoiseEst->bckr_fx, hFrontVad->hNoiseEst->bckr, Q_bands + Q7, NB_BANDS ); - hFrontVad->hNoiseEst->totalNoise = (float) hFrontVad->hNoiseEst->totalNoise_fx / ONE_IN_Q8; fixedToFloat_arrL( tmpN_fx, tmpN, Q_bands + QSCALE, 20 ); fixedToFloat_arrL( tmpE_fx, tmpE, Q_bands + QSCALE, 20 ); // Etot[0] = (float) Etot_fx[0] / ONE_IN_Q8; @@ -582,7 +964,7 @@ ivas_error front_vad_spar( Q_inp_12k8 = Q9; // Q_factor_arr( inp_12k8, 3 * L_FRAME / 2 ); floatToFixed_arr( inp_12k8, inp_12k8_fx, Q_inp_12k8, 3 * L_FRAME / 2 ); // Q_lp_noise = Q_factor( st->lp_noise ); - st->lp_noise_fx = (Word16) floatToFixed( st->lp_noise, Q8 ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, Q8 ); dtx_ivas_fx( st, hEncoderConfig->ivas_total_brate, vad_flag_dtx[0], inp_12k8_fx ); Word16 guard_bits = find_guarded_bits_fx( L_FRAME ); IF( st->Opt_DTX_ON ) @@ -597,7 +979,7 @@ ivas_error front_vad_spar( alw_pitch_lag_12k8[1] = st->old_pitch_la; alw_voicing[0] = st->voicing[2]; alw_voicing[1] = st->voicing[2]; -#if 1 +#if 0 analy_lp( inp_12k8, L_FRAME, L_LOOK_12k8, &res_energy, A, epsP, lsp_new, lsp_mid, st->lsp_old1, alw_pitch_lag_12k8, alw_voicing, INT_FS_12k8, 0 /* <-- sec_chan_low_rate */ ); #else // analy_lp( inp_12k8, L_FRAME, L_LOOK_12k8, &res_energy, A, epsP, lsp_new, lsp_mid, st->lsp_old1, alw_pitch_lag_12k8, alw_voicing, INT_FS_12k8, 0 /* <-- sec_chan_low_rate */ ); @@ -605,19 +987,19 @@ ivas_error front_vad_spar( Word16 Q_r[2] = { 0 }; floatToFixed_arr( st->lsp_old1, st->lsp_old1_fx, Q15, M ); floatToFixed_arr( alw_voicing, alw_voicing_fx, Q15, 2 ); - Q_inp_12k8 = Q12; // Q_factor_arr( inp_12k8 - 90, 3 * L_FRAME / 2 + 90 ); + Q_inp_12k8 = Q9; // Q_factor_arr( inp_12k8 - 90, 3 * L_FRAME / 2 + 90 ); floatToFixed_arr( inp_12k8 - 90, inp_12k8_fx - 90, Q_inp_12k8, 3 * L_FRAME / 2 + 90 ); analy_lp_fx( inp_12k8_fx, L_FRAME, L_LOOK_12k8, &res_energy_fx, A_fx, epsP_h, epsP_l, lsp_new_fx, lsp_mid_fx, st->lsp_old1_fx, alw_pitch_lag_12k8, alw_voicing_fx, INT_FS_12k8, 0 /* <-- sec_chan_low_rate */, Q_inp_12k8, Q_r ); for ( Word16 i = 0; i <= M; i++ ) { epsP_fx[i] = L_Comp( epsP_h[i], epsP_l[i] ); } - fixedToFloat_arrL( epsP_fx, epsP, Q_r[0] - 24, M + 1 ); + fixedToFloat_arrL( epsP_fx, epsP, Q_r[0], M + 1 ); fixedToFloat_arr( A_fx, A, Q14, NB_SUBFR16k * ( M + 1 ) ); fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); fixedToFloat_arr( st->lsp_old1_fx, st->lsp_old1, Q15, M ); - fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q12, 3 ); + fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q9, 3 ); #endif relE = Etot[0] - st->lp_speech; @@ -644,7 +1026,7 @@ ivas_error front_vad_spar( if ( st->vad_flag == 0 ) { /* reset the OL pitch tracker memories during inactive frames */ -#if 1 +#if 0 pitch_ol_init( &st->old_thres, &st->old_pitch, &st->delta_pit, &st->old_corr ); #else pitch_ol_init_fx( &st->old_thres_fx, &st->old_pitch, &st->delta_pit, &st->old_corr_fx ); @@ -652,33 +1034,32 @@ ivas_error front_vad_spar( } old_pitch = st->pitch[1]; -#if 0 - floatToFixed_arr( st->voicing, st->voicing_fx, Q15,3 ); - floatToFixed_arr( wsp, wsp_fx, Q12, 368 ); - floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q12, 115 ); - floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q12, 3 ); - // st->old_corr_fx = (Word16)floatToFixed( st->old_corr, Q15 ); - corr_shift_fx = (Word16)floatToFixed( corr_shift, Q15); - // st->old_thres_fx = (Word16) floatToFixed( st->old_thres, Q15 ); +#if 1 + floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); + floatToFixed_arr( wsp, wsp_fx, Q8, 368 ); + floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q8, 115 ); + floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q8, 3 ); + // st->old_corr_fx = (Word16)floatToFixed( st->old_corr, Q15 ); + corr_shift_fx = (Word16) floatToFixed( corr_shift, Q15 ); + // st->old_thres_fx = (Word16) floatToFixed( st->old_thres, Q15 ); relE_fx = (Word16) floatToFixed( relE, Q8 ); pitch_ol_ivas_fx( st->pitch, st->voicing_fx, &st->old_pitch, &st->old_corr_fx, corr_shift_fx, &st->old_thres_fx, &st->delta_pit, st->old_wsp2_fx, wsp_fx, st->mem_decim2_fx, relE_fx, st->clas, st->input_bwidth, st->Opt_SC_VBR ); - //pitch_ol( st->pitch, st->voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, relE, L_LOOK_12k8, st->clas, st->input_bwidth, st->Opt_SC_VBR ); - + // pitch_ol( st->pitch, st->voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, relE, L_LOOK_12k8, st->clas, st->input_bwidth, st->Opt_SC_VBR ); + fixedToFloat_arr( st->voicing_fx, st->voicing, Q15, 3 ); - fixedToFloat_arr( st->old_wsp2_fx, st->old_wsp2, Q12, 115 ); - fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q12, 3 ); + fixedToFloat_arr( st->old_wsp2_fx, st->old_wsp2, Q8, 115 ); + fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q8, 3 ); st->old_corr = fixedToFloat( st->old_corr_fx, Q15 ); - // corr_shift_fx = floatToFixed( corr_shift, Q15 ); + // corr_shift_fx = floatToFixed( corr_shift, Q15 ); st->old_thres = fixedToFloat( st->old_thres_fx, Q15 ); - //st->old_thres_fx = floatToFixed( relE, Q8 ); - for ( Word16 i = 0; i < 3; i++ ) + // st->old_thres_fx = floatToFixed( relE, Q8 ); + /*for ( Word16 i = 0; i < 3; i++ ) { fprintf( fp_pitch, "%d\n", st->pitch[i] ); fprintf( fp_voice, "%f\n", st->voicing[i] ); - - } - // fprintf( fpbckr_fl, "%f\n", hFrontVad->hNoiseEst->bckr[i] ); + }*/ + // fprintf( fpbckr_fl, "%f\n", hFrontVad->hNoiseEst->bckr[i] ); #else pitch_ol( st->pitch, st->voicing, &st->old_pitch, &st->old_corr, corr_shift, &st->old_thres, &st->delta_pit, st->old_wsp2, wsp, st->mem_decim2, relE, L_LOOK_12k8, st->clas, st->input_bwidth, st->Opt_SC_VBR ); #endif @@ -692,7 +1073,7 @@ ivas_error front_vad_spar( floatToFixed_arr( wsp, wsp_fx, Q9, 368 ); floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); floatToFixed_arr( st->Bin_E, st->lgBin_E_fx, Q7, 128 ); - StableHighPitchDetect_fx( &flag_spitch, st->pitch, st->voicing_fx, wsp_fx, st->localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, &st->LF_EnergyRatio_sm_fx, &st->predecision_flag, &st->diff_sm_fx, &st->energy_sm_fx, Q12, st->lgBin_E_fx ); + StableHighPitchDetect_ivas_fx( &flag_spitch, st->pitch, st->voicing_fx, wsp_fx, st->localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, &st->LF_EnergyRatio_sm_fx, &st->predecision_flag, &st->diff_sm_fx, &st->energy_sm_fx, Q12, st->lgBin_E_fx ); fixedToFloat_arr( st->lgBin_E_fx, st->Bin_E, Q7, 128 ); st->LF_EnergyRatio_sm = fixedToFloat( st->LF_EnergyRatio_sm_fx, Q7 ); st->voicing_sm = fixedToFloat( st->voicing_sm_fx, Q15 ); @@ -705,63 +1086,42 @@ ivas_error front_vad_spar( #if 0 loc_harm = multi_harm( st->Bin_E, hFrontVad->hNoiseEst->old_S, hFrontVad->hNoiseEst->cor_map, &hFrontVad->hNoiseEst->multi_harm_limit, st->total_brate, st->bwidth, ( st->hGSCEnc != NULL ) ? &st->hGSCEnc->cor_strong_limit : &dummy_int, &st->hSpMusClas->mean_avr_dyn, &st->hSpMusClas->last_sw_dyn, &cor_map_sum, &dummy, S_map ); #else - floatToFixed_arr( hFrontVad->hNoiseEst->old_S, hFrontVad->hNoiseEst->old_S_fx, Q7, 128 ); - floatToFixed_arr( hFrontVad->hNoiseEst->cor_map, hFrontVad->hNoiseEst->cor_map_fx, Q15, 128 ); - // floatToFixed_arr( hFrontVad->hNoiseEst->cor_map, hFrontVad->hNoiseEst->old_S_fx, Q15, 128 ); - hFrontVad->hNoiseEst->multi_harm_limit_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->multi_harm_limit, Q9 ); - st->hSpMusClas->mean_avr_dyn_fx = (Word16) floatToFixed( st->hSpMusClas->mean_avr_dyn, Q7 ); - st->hSpMusClas->last_sw_dyn_fx = (Word16) floatToFixed( st->hSpMusClas->last_sw_dyn, Q7 ); - // cor_map_sum_fx = (Word16) floatToFixed( cor_map_sum, Q8 ); - // dummy_fx = (Word16) floatToFixed( dummy, Q7 ); - floatToFixed_arr( hFrontVad->hNoiseEst->old_S, hFrontVad->hNoiseEst->old_S_fx, Q7, 128 ); - // loc_harm = multi_harm( st->lgBin_E_fx, hFrontVad->hNoiseEst->old_S_fx, hFrontVad->hNoiseEst->cor_map_fx, &hFrontVad->hNoiseEst->multi_harm_limit, st->total_brate, st->bwidth, ( st->hGSCEnc != NULL ) ? &st->hGSCEnc->cor_strong_limit : &dummy_int, &st->hSpMusClas->mean_avr_dyn, &st->hSpMusClas->last_sw_dyn, &cor_map_sum, &dummy, S_map ); - loc_harm = multi_harm_fx( st->lgBin_E_fx, hFrontVad->hNoiseEst->old_S_fx, hFrontVad->hNoiseEst->cor_map_fx, &hFrontVad->hNoiseEst->multi_harm_limit_fx, st->total_brate, st->bwidth, ( st->hGSCEnc != NULL ) ? &st->hGSCEnc->cor_strong_limit : &dummy_int, &st->hSpMusClas->mean_avr_dyn_fx, &st->hSpMusClas->last_sw_dyn_fx, &cor_map_sum_fx, &dummy_fx, S_map_fx ); - fixedToFloat_arr( hFrontVad->hNoiseEst->old_S_fx, hFrontVad->hNoiseEst->old_S, Q7, 128 ); - fixedToFloat_arr( hFrontVad->hNoiseEst->cor_map_fx, hFrontVad->hNoiseEst->cor_map, Q15, 128 ); - // floatToFixed_arr( hFrontVad->hNoiseEst->cor_map, hFrontVad->hNoiseEst->old_S_fx, Q15, 128 ); - hFrontVad->hNoiseEst->multi_harm_limit = fixedToFloat( hFrontVad->hNoiseEst->multi_harm_limit_fx, Q9 ); - st->hSpMusClas->mean_avr_dyn = fixedToFloat( st->hSpMusClas->mean_avr_dyn_fx, Q7 ); - st->hSpMusClas->last_sw_dyn = fixedToFloat( st->hSpMusClas->last_sw_dyn_fx, Q7 ); - cor_map_sum = fixedToFloat( cor_map_sum_fx, Q8 ); - // dummy = fixedToFloat( dummy_fx, Q7 ); - fixedToFloat_arr( hFrontVad->hNoiseEst->old_S_fx, hFrontVad->hNoiseEst->old_S, Q7, 128 ); + loc_harm = multi_harm_ivas_fx( st->lgBin_E_fx, hFrontVad->hNoiseEst->old_S_fx, hFrontVad->hNoiseEst->cor_map_fx, &hFrontVad->hNoiseEst->multi_harm_limit_fx, st->total_brate, st->bwidth, ( st->hGSCEnc != NULL ) ? &st->hGSCEnc->cor_strong_limit : &dummy_int, &st->hSpMusClas->mean_avr_dyn_fx, &st->hSpMusClas->last_sw_dyn_fx, &cor_map_sum_fx, &dummy_fx, S_map_fx ); + cor_map_sum = fixedToFloat( cor_map_sum_fx, Q8 ); #endif } -#if 1 +#if 0 noise_est( st, old_pitch, tmpN, epsP, Etot[0], Etot[0] - hFrontVad->lp_speech, corr_shift, tmpE, fr_bands[0], &cor_map_sum, &ncharX, &sp_div, &non_staX, &loc_harm, lf_E[0], &hFrontVad->hNoiseEst->harm_cor_cnt, hFrontVad->hNoiseEst->Etot_l_lp, &dummy, S_map, NULL, hFrontVad, hFrontVad->ini_frame ); #else // noise_est( st, old_pitch, tmpN, epsP, Etot[0], Etot[0] - hFrontVad->lp_speech, corr_shift, tmpE, fr_bands[0], &cor_map_sum, &ncharX, &sp_div, &non_staX, &loc_harm, lf_E[0], &hFrontVad->hNoiseEst->harm_cor_cnt, hFrontVad->hNoiseEst->Etot_l_lp, &dummy, S_map, NULL, hFrontVad, hFrontVad->ini_frame ); - Word16 Q_esp = Q_factor_arrL( epsP, M + 1 ); + Q_esp = Q_factor_arrL( epsP, M + 1 ); floatToFixed_arrL( epsP, epsP_fx, Q_esp, M + 1 ); FOR( Word16 i = 0; i <= M; i++ ) { L_Extract( epsP_fx[i], &epsP_h[i], &epsP_l[i] ); } + Q_bands = Q9; floatToFixed_arrL( lf_E[0], lf_E_fx[0], Q_bands + QSCALE - 2, 148 ); floatToFixed_arrL( hFrontVad->hNoiseEst->fr_bands1, hFrontVad->hNoiseEst->fr_bands1_fx, Q_bands + QSCALE, NB_BANDS ); floatToFixed_arrL( hFrontVad->hNoiseEst->fr_bands2, hFrontVad->hNoiseEst->fr_bands2_fx, Q_bands + QSCALE, NB_BANDS ); floatToFixed_arrL( hFrontVad->hNoiseEst->ave_enr, hFrontVad->hNoiseEst->ave_enr_fx, Q_bands + QSCALE, NB_BANDS ); floatToFixed_arrL( hFrontVad->hNoiseEst->ave_enr2, hFrontVad->hNoiseEst->ave_enr2_fx, Q_bands + QSCALE, NB_BANDS ); - hFrontVad->hNoiseEst->noise_char_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->noise_char, Q11 ); - hFrontVad->hNoiseEst->act_pred_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->act_pred, Q15 ); - hFrontVad->hNoiseEst->lt_haco_ev_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_haco_ev, Q15 ); - hFrontVad->hNoiseEst->lt_tn_track_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_tn_track, Q15 ); - hFrontVad->hNoiseEst->lt_aEn_zero_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_aEn_zero, Q15 ); - hFrontVad->hNoiseEst->epsP_0_2_ad_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->epsP_0_2_ad_lp, Q12 ); - hFrontVad->hNoiseEst->epsP_0_2_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->epsP_0_2_lp, Q12 ); - hFrontVad->hNoiseEst->epsP_2_16_dlp_lp2_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->epsP_2_16_dlp_lp2, Q12 ); - hFrontVad->hNoiseEst->epsP_2_16_lp2_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->epsP_2_16_lp2, Q12 ); - hFrontVad->hNoiseEst->epsP_2_16_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->epsP_2_16_lp, Q12 ); - // hFrontVad->hNoiseEst->totalNoise_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_tn_track, Q15 ); + hFrontVad->hNoiseEst->sign_dyn_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->sign_dyn_lp, Q8 ); hFrontVad->hNoiseEst->Etot_l_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->Etot_l_lp, Q8 ); hFrontVad->hNoiseEst->Etot_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->Etot_lp, Q8 ); hFrontVad->hNoiseEst->Etot_v_h2_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->Etot_v_h2, Q8 ); - hFrontVad->lp_speech_fx = (Word16) floatToFixed( hFrontVad->lp_speech, Q8 ); corr_shift_fx = (Word16) floatToFixed( corr_shift, Q15 ); - noise_est_ivas_fx( st, old_pitch, tmpN_fx, epsP_h, epsP_l, Etot_fx[0], Etot_fx[0] - hFrontVad->lp_speech_fx, corr_shift_fx, tmpE_fx, fr_bands_fx[0], &cor_map_sum_fx, &sp_div_fx, &Q_sp_div, &non_staX_fx, &loc_harm, lf_E_fx[0], &hFrontVad->hNoiseEst->harm_cor_cnt, hFrontVad->hNoiseEst->Etot_l_lp_fx, hFrontVad->hNoiseEst->Etot_v_h2_fx, &hFrontVad->hNoiseEst->bg_cnt, st->lgBin_E_fx, Q_bands, Q_bands + QSCALE, &sp_floor, S_map_fx, NULL, hFrontVad, hFrontVad->ini_frame ); + floatToFixed_arrL( hFrontVad->hNoiseEst->bckr, hFrontVad->hNoiseEst->bckr_fx, Q_bands + QSCALE, NB_BANDS ); + + noise_est_ivas_fx( st, old_pitch, tmpN_fx, epsP_h, epsP_l, Etot_fx[0], Etot_fx[0] - hFrontVad->lp_speech_fx, corr_shift_fx, tmpE_fx, fr_bands_fx[0], &cor_map_sum_fx, NULL, &sp_div_fx, &Q_sp_div, &non_staX_fx, &loc_harm, lf_E_fx[0], &hFrontVad->hNoiseEst->harm_cor_cnt, hFrontVad->hNoiseEst->Etot_l_lp_fx, hFrontVad->hNoiseEst->Etot_v_h2_fx, &hFrontVad->hNoiseEst->bg_cnt, st->lgBin_E_fx, Q_bands, e_min_scaled, &sp_floor, S_map_fx, NULL, hFrontVad, hFrontVad->ini_frame ); + fixedToFloat_arrL( hFrontVad->hNoiseEst->fr_bands1_fx, hFrontVad->hNoiseEst->fr_bands1, Q_bands + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hFrontVad->hNoiseEst->fr_bands2_fx, hFrontVad->hNoiseEst->fr_bands2, Q_bands + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hFrontVad->hNoiseEst->ave_enr_fx, hFrontVad->hNoiseEst->ave_enr, Q_bands + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hFrontVad->hNoiseEst->ave_enr2_fx, hFrontVad->hNoiseEst->ave_enr2, Q_bands + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hFrontVad->hNoiseEst->bckr_fx, hFrontVad->hNoiseEst->bckr, Q_bands + Q7, NB_BANDS ); cor_map_sum = fixedToFloat( cor_map_sum_fx, Q8 ); non_staX = fixedToFloat( non_staX_fx, Q8 ); fixedToFloat_arr( S_map_fx, S_map, Q7, 128 ); @@ -771,8 +1131,6 @@ ivas_error front_vad_spar( #else MVR2R_WORD16( st->pitch, st->pitch, 3 ); corr_shift_fx = (Word16) floatToFixed( corr_shift, Q15 ); - hFrontVad->hVAD->running_avg_fx = (Word16) floatToFixed( hFrontVad->hVAD->running_avg, Q15 ); - hFrontVad->hVAD->ra_deltasum_fx = (Word16) floatToFixed( hFrontVad->hVAD->ra_deltasum, Q15 ); #ifdef MSAN_FIX floatToFixed_arr( A, A_fx, Q12, ( L_FRAME / L_SUBFR ) * ( M + 1 ) ); #else @@ -780,9 +1138,6 @@ ivas_error front_vad_spar( #endif // MSAN_FIX floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); vad_param_updt_fx( st, st->pitch[1], corr_shift_fx, corr_shift_fx, A_fx, &hFrontVad, 1 ); - hFrontVad->hVAD->running_avg = fixedToFloat( hFrontVad->hVAD->running_avg_fx, Q15 ); - hFrontVad->hVAD->ra_deltasum = fixedToFloat( hFrontVad->hVAD->ra_deltasum_fx, Q15 ); - #endif /* 1st stage speech/music classification (GMM model) */ /* run only to get 'high_lpn_flag' parameter */ @@ -791,59 +1146,58 @@ ivas_error front_vad_spar( #else SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; #if 1 - Word16 relE_fx; - Word16 lsp_new_fx[M]; - Word32 PS_fx[128]; - Word32 epsP_fx[M + 1]; - cor_map_sum_fx = (Word16) floatToFixed( cor_map_sum, Q8 ); - Word16 non_sta_fx = (Word16) floatToFixed( non_staX, Q8 ); + // Word16 relE_fx; + // Word16 lsp_new_fx[M]; + // Word32 PS_fx[128]; + // Word32 epsP_fx[M + 1]; + cor_map_sum_fx = float_to_fix16( cor_map_sum, Q8 ); + Word16 non_sta_fx = float_to_fix16( non_staX, Q6 ); // Word32 epsP_fx[M + 1]; - Word16 Etot_fx_0 = (Word16) floatToFixed( Etot[0], Q8 ); + Word16 Etot_fx_0 = float_to_fix16( Etot[0], Q8 ); floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); - hSpMusClas->wdlp_0_95_sp_fx = (Word16) floatToFixed( hSpMusClas->wdlp_0_95_sp, Q8 ); + hSpMusClas->wdlp_0_95_sp_32fx = float_to_fix( hSpMusClas->wdlp_0_95_sp, Q24 ); hSpMusClas->wdlp_xtalk_fx = floatToFixed( hSpMusClas->wdlp_xtalk, Q19 ); - hSpMusClas->wrise_fx = (Word16) ( hSpMusClas->wrise * ONE_IN_Q9 ); - relE_fx = (Word16) ( relE * ONE_IN_Q9 ); - hSpMusClas->prev_relE_fx = (Word16) ( hSpMusClas->prev_relE * ONE_IN_Q9 ); - hSpMusClas->relE_attack_sum_fx = (Word16) ( hSpMusClas->relE_attack_sum * ONE_IN_Q9 ); + hSpMusClas->wrise_fx = float_to_fix16( hSpMusClas->wrise, 9 ); + relE_fx = float_to_fix16( relE, 8 ); + floatToFixed_arr16( st->voicing, st->voicing_fx, 15, 3 ); Word16 Qfact_PS = Q_factor_arrL( PS, 128 ); floatToFixed_arr32( PS, PS_fx, Qfact_PS, 128 ); - Word16 Q_esp, e_esp; + Word16 e_esp; f2me_buf( epsP, epsP_fx, &e_esp, M + 1 ); Q_esp = sub( 31, e_esp ); Word16 Qfact_PS_past = Q_factor_arrL( hSpMusClas->past_PS, 67 ); floatToFixed_arr32( hSpMusClas->past_PS, hSpMusClas->past_PS_fx, Qfact_PS_past, 67 ); + hSpMusClas->dlp_var_LT_fx = float_to_fix( hSpMusClas->dlp_var_LT, Q19 ); + hSpMusClas->dlp_mean_LT_fx = float_to_fix( hSpMusClas->dlp_mean_LT, Q19 ); + hSpMusClas->dlp_mean_ST_fx = float_to_fix( hSpMusClas->dlp_mean_ST, Q19 ); + floatToFixed_arr32( hSpMusClas->past_dlp_mean_ST, hSpMusClas->past_dlp_mean_ST_fx, Q19, 7 ); + floatToFixed_arr32( hSpMusClas->prev_FV, hSpMusClas->prev_FV_fx, Q20, 15 ); + floatToFixed_arrL( hSpMusClas->FV_st, hSpMusClas->FV_st_fx, Q20, 15 ); #endif ivas_smc_gmm_fx( st, NULL, localVAD_HE_SAD[0], Etot_fx_0, lsp_new_fx, cor_map_sum_fx, epsP_fx, PS_fx, non_sta_fx, relE_fx, &high_lpn_flag, flag_spitch, Qfact_PS, Q_esp, Qfact_PS_past ); #if 1 fixedToFloat_arr( hSpMusClas->past_dlp_fx, hSpMusClas->past_dlp, Q9, HANG_LEN - 1 ); - hSpMusClas->lpm = (Word16) fixedToFloat( hSpMusClas->lpm_fx, Q8 ); // Q8 - hSpMusClas->lps = (Word16) fixedToFloat( hSpMusClas->lps_fx, Q8 ); // Q8 - hSpMusClas->lpn = (Word16) fixedToFloat( hSpMusClas->lpn_fx, Q8 ); // Q8 - hSpMusClas->wdrop = (Word16) fixedToFloat( hSpMusClas->wdrop_fx, Q9 ); // Q8 - hSpMusClas->wrise = (Word16) fixedToFloat( hSpMusClas->wrise_fx, Q9 ); // Q8 - hSpMusClas->lt_dec_thres = (Word16) fixedToFloat( hSpMusClas->lt_dec_thres_fx, Q9 ); // Q8 - hSpMusClas->wdlp_0_95_sp = fixedToFloat( hSpMusClas->wdlp_0_95_sp_fx, Q8 ); + hSpMusClas->lpm = fixedToFloat( hSpMusClas->lpm_fx, Q7 ); // Q7 + hSpMusClas->lps = fixedToFloat( hSpMusClas->lps_fx, Q7 ); // Q7 + hSpMusClas->wdrop = fixedToFloat( hSpMusClas->wdrop_fx, Q9 ); // Q9 + hSpMusClas->wrise = fixedToFloat( hSpMusClas->wrise_fx, Q9 ); // Q9 + hSpMusClas->wdlp_0_95_sp = fixedToFloat( hSpMusClas->wdlp_0_95_sp_32fx, Q24 ); // Q24 hSpMusClas->dlp_mean_LT = fixedToFloat_32( hSpMusClas->dlp_mean_LT_fx, Q19 ); hSpMusClas->wdlp_xtalk = fixedToFloat( hSpMusClas->wdlp_xtalk_fx, Q19 ); hSpMusClas->dlp_var_LT = fixedToFloat_32( hSpMusClas->dlp_var_LT_fx, Q19 ); - hSpMusClas->prev_relE = (Word16) fixedToFloat( hSpMusClas->prev_relE_fx, Q9 ); - hSpMusClas->prev_Etot = (Word16) fixedToFloat( hSpMusClas->prev_Etot_fx, Q8 ); fixedToFloat_arrL32( hSpMusClas->past_PS_fx, hSpMusClas->past_PS, Qfact_PS_past, 67 ); - hSpMusClas->relE_attack_sum = (Word16) fixedToFloat( hSpMusClas->relE_attack_sum_fx, Q9 ); fixedToFloat_arrL32( hSpMusClas->FV_st_fx, hSpMusClas->FV_st, Q20, 15 ); + hSpMusClas->dlp_mean_ST = fixedToFloat( hSpMusClas->dlp_mean_ST_fx, Q19 ); + fixedToFloat_arrL32( hSpMusClas->past_dlp_mean_ST_fx, hSpMusClas->past_dlp_mean_ST, Q19, 7 ); + fixedToFloat_arrL32( hSpMusClas->prev_FV_fx, hSpMusClas->prev_FV, Q20, 15 ); #endif #endif #if 0 /* long-term energy update */ long_enr( st, -1, localVAD_HE_SAD[0], high_lpn_flag, &hFrontVad, 1, localVAD_HE_SAD, Etot ); #else - hFrontVad->lp_speech_fx = (Word16) floatToFixed( hFrontVad->lp_speech, Q8 ); - hFrontVad->lp_noise_fx = (Word16) floatToFixed( hFrontVad->lp_noise, Q8 ); /* long-term energy update */ ivas_long_enr_fx( st, -1, localVAD_HE_SAD[0], high_lpn_flag, &hFrontVad, 1, localVAD_HE_SAD, Etot_fx ); - hFrontVad->lp_speech = fixedToFloat( hFrontVad->lp_speech_fx, Q8 ); - hFrontVad->lp_noise = fixedToFloat( hFrontVad->lp_noise_fx, Q8 ); hFrontVad->hNoiseEst->Etot_last = fixedToFloat( hFrontVad->hNoiseEst->Etot_last_fx, Q8 ); #endif /* increase ini_frame counter */ diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index f190545687a8b84204230dd882f6bed5df50e1aa..023434678f357af654de741fd503282e90944a43 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -501,26 +501,39 @@ void copy_encoder_config_fx( IF( flag_all ) { st_fx->input_Fs = st_ivas->hEncoderConfig->input_Fs; + move32(); st_fx->last_codec_mode = st_ivas->last_codec_mode; + move16(); st_fx->last_total_brate = st_ivas->hEncoderConfig->last_ivas_total_brate; + move32(); st_fx->Opt_DTX_ON = st_ivas->hEncoderConfig->Opt_DTX_ON; + move16(); st_fx->last_Opt_SC_VBR = st_ivas->hEncoderConfig->last_Opt_SC_VBR; + move16(); } st_fx->Opt_AMR_WB = st_ivas->hEncoderConfig->Opt_AMR_WB; + move16(); st_fx->Opt_SC_VBR = st_ivas->hEncoderConfig->Opt_SC_VBR; + move16(); st_fx->codec_mode = st_ivas->codec_mode; + move16(); st_fx->max_bwidth = st_ivas->hEncoderConfig->max_bwidth; + move16(); st_fx->Opt_RF_ON = st_ivas->hEncoderConfig->Opt_RF_ON; + move16(); st_fx->rf_fec_offset = st_ivas->hEncoderConfig->rf_fec_offset; + move16(); st_fx->rf_fec_indicator = st_ivas->hEncoderConfig->rf_fec_indicator; + move16(); st_fx->element_mode = st_ivas->hEncoderConfig->element_mode_init; + move16(); return; } @@ -744,7 +757,7 @@ ivas_error ivas_init_encoder( move16(); test(); - IF( NE_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( NE_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) ) { IF( NE_32( ( error = create_sce_enc( st_ivas, sce_id, ivas_total_brate ) ), IVAS_ERR_OK ) ) { @@ -1031,11 +1044,17 @@ ivas_error ivas_init_encoder( return error; } } - +#ifdef IVAS_FLOAT_FIXED + if ( ( error = ivas_osba_enc_open_fx( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_osba_enc_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( ivas_format == MC_FORMAT ) { @@ -1154,8 +1173,11 @@ ivas_error ivas_init_encoder( { return error; } - +#ifndef IVAS_FLOAT_FIXED if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_mcmasa_enc_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1375,7 +1397,7 @@ ivas_error ivas_init_encoder_fx( move16(); test(); - IF( EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) && !st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) ) { IF( NE_32( ( error = create_evs_sce_enc( st_ivas, sce_id, ivas_total_brate ) ), IVAS_ERR_OK ) ) { @@ -1662,11 +1684,17 @@ ivas_error ivas_init_encoder_fx( return error; } } - +#ifdef IVAS_FLOAT_FIXED + if ( ( error = ivas_osba_enc_open_fx( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_osba_enc_open( st_ivas ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( ivas_format == MC_FORMAT ) { @@ -1782,7 +1810,11 @@ ivas_error ivas_init_encoder_fx( return error; } +#ifndef IVAS_FLOAT_FIXED if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_mcmasa_enc_open_fx( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -2042,7 +2074,7 @@ void ivas_destroy_enc( { if ( st_ivas->hSCE[i] != NULL ) { - destroy_sce_enc( st_ivas->hSCE[i], ( EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) && !st_ivas->hEncoderConfig->stereo_dmx_evs ) ); + destroy_sce_enc( st_ivas->hSCE[i], EQ_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) ); st_ivas->hSCE[i] = NULL; } } @@ -2123,14 +2155,18 @@ void ivas_destroy_enc( /* Parametric MC handle */ ivas_param_mc_enc_close( &( st_ivas->hParamMC ), st_ivas->hEncoderConfig->input_Fs ); - /* Multi-channel MASA handle */ +/* Multi-channel MASA handle */ +#ifdef IVAS_FLOAT_FIXED + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#else ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#endif /* OMASA handle */ ivas_omasa_enc_close( &( st_ivas->hOMasa ) ); /* OSBA handle */ - ivas_osba_enc_close( &( st_ivas->hOSba ) ); + ivas_osba_enc_close_fx( &( st_ivas->hOSba ) ); /* Stereo downmix for EVS encoder handle */ stereo_dmx_evs_close_encoder( &( st_ivas->hStereoDmxEVS ) ); @@ -2354,6 +2390,7 @@ void ivas_destroy_MD_bstr_enc( BSTR_ENC_HANDLE *hMetaData /* i/o: encoder MD bitstream handle */ ) { + test(); IF( hMetaData == NULL || *hMetaData == NULL ) { return; diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index 80ace46765266d44ec4818bfa9f1a6e6d735873c..177d52e38c4737f82aefba96787ea7853a9b3007 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -431,18 +431,25 @@ ivas_error ivas_ism_enc( Encoder_State *st; Word16 sce_id; #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion - float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ - float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ + float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ + float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ + Word16 old_inp_12k8_fx[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ #else - float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ - float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP]; /* buffer of input signal @ 16kHz */ + float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP]; /* buffer of input signal @ 16kHz */ +#endif + Word16 vad_flag[MAX_NUM_OBJECTS]; /* VAD flag */ + float ener[MAX_NUM_OBJECTS][1]; /* residual energy from Levinson-Durbin */ + float relE[MAX_NUM_OBJECTS][1]; /* frame relative energy */ + Word16 relE_fx[MAX_NUM_OBJECTS][1]; + /* frame relative energy, Q8 */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion + float A[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* A(z) unquantized for subframes */ + float Aw[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* weighted A(z) unquantized for subframes */ +#else + float A[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ + float Aw[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ #endif - Word16 vad_flag[MAX_NUM_OBJECTS]; /* VAD flag */ - float ener[MAX_NUM_OBJECTS][1]; /* residual energy from Levinson-Durbin */ - float relE[MAX_NUM_OBJECTS][1]; /* frame relative energy */ - Word16 relE_fx[MAX_NUM_OBJECTS][1]; /* frame relative energy, Q8 */ - float A[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ - float Aw[MAX_NUM_OBJECTS][1][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ float epsP[MAX_NUM_OBJECTS][1][M + 1]; /* LP prediction errors */ float lsp_new[MAX_NUM_OBJECTS][1][M]; /* LSPs at the end of the frame */ float lsp_mid[MAX_NUM_OBJECTS][1][M]; /* ISPs in the middle of the frame */ @@ -457,8 +464,10 @@ ivas_error ivas_ism_enc( float cor_map_sum[MAX_NUM_OBJECTS][1]; /* speech/music clasif. parameter */ Word16 vad_flag_dtx[MAX_NUM_OBJECTS][1]; /* HE-SAD flag with additional DTX HO */ float enerBuffer[MAX_NUM_OBJECTS][1][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ + Word16 currFlatness_fx[1]; /* flatness parameter */ float currFlatness[1]; /* flatness parameter */ float fft_buff[MAX_NUM_OBJECTS][1][2 * L_FFT]; /* FFT buffer */ + Word16 fft_buff_fx[MAX_NUM_OBJECTS][1][2 * L_FFT]; /* FFT buffer */ float fr_bands[1][2 * NB_BANDS]; /* energy in frequency bands */ float Etot_LR[1]; /* total energy; correlation shift */ float lf_E[1][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ @@ -546,8 +555,74 @@ ivas_error ivas_ism_enc( * Time Domain Transient Detector *---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTranDet->subblockEnergies.firState1 = (Word16) floatToFixed( st->hTranDet->subblockEnergies.firState1_flt, -1 ); + st->hTranDet->subblockEnergies.firState2 = (Word16) floatToFixed( st->hTranDet->subblockEnergies.firState2_flt, -1 ); + + FOR( i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st->hTranDet->subblockEnergies.accSubblockNrg[i] = floatToFixed( st->hTranDet->subblockEnergies.accSubblockNrg_flt[i], 7 ); + } + + FOR( i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st->hTranDet->subblockEnergies.subblockNrg[i] = floatToFixed( st->hTranDet->subblockEnergies.subblockNrg_flt[i], 7 ); + st->hTranDet->subblockEnergies.subblockNrgChange[i] = (Word16) floatToFixed( st->hTranDet->subblockEnergies.subblockNrgChange_flt[i], 7 ); + } + + + FOR( i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st->hTranDet->delayBuffer.buffer[i] = (Word16) floatToFixed( st->hTranDet->delayBuffer.buffer_flt[i], 7 ); + } + + st->hTranDet->transientDetector.attackRatioThreshold = (Word16) floatToFixed( st->hTranDet->transientDetector.attackRatioThreshold_flt, 11 ); + + floatToFixed_arr16( st->input, st->input_fx, -1, input_frame ); + st->hTranDet->subblockEnergies.facAccSubblockNrg = float_to_fix16( st->hTranDet->subblockEnergies.facAccSubblockNrg_flt, 15 ); + +#endif + + RunTransientDetection_ivas_fx( st->input_fx, input_frame, st->hTranDet ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st->hTranDet->subblockEnergies.firState1_flt = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.firState1, -1 ); + st->hTranDet->subblockEnergies.firState2_flt = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.firState2, -1 ); + + FOR( i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st->hTranDet->subblockEnergies.subblockNrg_flt[i] = fixedToFloat( st->hTranDet->subblockEnergies.subblockNrg[i], 7 ); + st->hTranDet->subblockEnergies.subblockNrgChange_flt[i] = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.subblockNrgChange[i], 7 ); + } + + FOR( i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st->hTranDet->subblockEnergies.accSubblockNrg_flt[i] = fixedToFloat( st->hTranDet->subblockEnergies.accSubblockNrg[i], 7 ); + } + + FOR( i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st->hTranDet->delayBuffer.buffer_flt[i] = fixedToFloat( (Word32) st->hTranDet->delayBuffer.buffer[i], -1 ); + } +#endif +#else RunTransientDetection( st->input, input_frame, st->hTranDet ); +#endif + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 e_tmp; + f2me_buf_16( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, &e_tmp, 24 ); +#endif + currFlatness_fx[0] = GetTCXAvgTemporalFlatnessMeasure_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + currFlatness[0] = me2f_16( currFlatness_fx[0], e_tmp ); +#endif +#else currFlatness[0] = GetTCXAvgTemporalFlatnessMeasure( st->hTranDet, NSUBBLOCKS, 0 ); +#endif /*----------------------------------------------------------------* * Configuration of core encoder @@ -562,10 +637,10 @@ ivas_error ivas_ism_enc( /*----------------------------------------------------------------* * Front Pre-processing *----------------------------------------------------------------*/ - error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata[sce_id], input_frame, 0, old_inp_12k8[sce_id][0], old_inp_16k[sce_id][0], + error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata[sce_id], input_frame, 0, old_inp_12k8_fx[sce_id][0], old_inp_12k8[sce_id][0], old_inp_16k[sce_id][0], &ener[sce_id][0], &relE[sce_id][0], A[sce_id][0], Aw[sce_id][0], epsP[sce_id][0], lsp_new[sce_id][0], lsp_mid[sce_id][0], &vad_hover_flag[sce_id][0], &attack_flag[sce_id][0], realBuffer[sce_id][0], imagBuffer[sce_id][0], old_wsp[sce_id][0], pitch_fr[sce_id][0], voicing_fr[sce_id][0], &loc_harm[sce_id][0], &cor_map_sum[sce_id][0], &vad_flag_dtx[sce_id][0], enerBuffer[sce_id][0], - fft_buff[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0, ISM_FORMAT, 0, st_ivas->hEncoderConfig->ivas_total_brate ); + fft_buff[sce_id][0], fft_buff_fx[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0, ISM_FORMAT, 0, st_ivas->hEncoderConfig->ivas_total_brate ); IF( NE_32( error, IVAS_ERR_OK ) ) { @@ -588,28 +663,53 @@ ivas_error ivas_ism_enc( * DTX analysis *-----------------------------------------------------------------*/ - IF( st_ivas->hEncoderConfig->Opt_DTX_ON ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( st_ivas->hIsmMetaData != NULL ) { - /* compute the dominant sce_id using long term energy */ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS /************************flt_to_fix****************************/ - for ( int j = 0; j < st_ivas->nchan_transport; j++ ) - { - floatToFixed_arrL( st_ivas->hSCE[j]->hCoreCoder[0]->input, st_ivas->hSCE[j]->hCoreCoder[0]->input32_fx, Q11, input_frame ); /*Q0*/ - } - f2me_buf( &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc[0][0], &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_fx[0][0], &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_e, st_ivas->nchan_transport * PARAM_ISM_HYS_BUF_SIZE ); - for ( int ch = 0; ch < nchan_ism; ch++ ) - { - st_ivas->hIsmMetaData[ch]->azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->last_azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->last_elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_elevation, Q22 ); - } - for ( int ch = 0; ch < st_ivas->nchan_transport; ch++ ) + FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) { - st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise_fx = float_to_fix16( st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise, Q8 ); /*Q8*/ + st_ivas->hIsmMetaData[ch]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); + st_ivas->hIsmMetaData[ch]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); + st_ivas->hIsmMetaData[ch]->yaw_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->yaw, Q22 ); + st_ivas->hIsmMetaData[ch]->pitch_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->pitch, Q22 ); + st_ivas->hIsmMetaData[ch]->radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->radius, Q9 ); + st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_azimuth, Q22 ); + st_ivas->hIsmMetaData[ch]->last_true_elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_elevation, Q22 ); + st_ivas->hIsmMetaData[ch]->last_true_radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->last_true_radius, Q9 ); } + } + if ( st_ivas->hISMDTX ) + { floatToFixed_arr16( st_ivas->hISMDTX->coh, st_ivas->hISMDTX->coh_fx, Q15, st_ivas->nchan_transport ); -#endif /****************************ends here*********************************/ + } + for ( int ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + IF( st_ivas->hSCE[ch] ) + st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise_fx = float_to_fix16( st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise, Q8 ); /*Q8*/ + } + + /* compute the dominant sce_id using long term energy */ + for ( int j = 0; j < st_ivas->nchan_transport; j++ ) + { + IF( st_ivas->hSCE[j] && st_ivas->hSCE[j]->hCoreCoder[0] ) + floatToFixed_arrL( st_ivas->hSCE[j]->hCoreCoder[0]->input, st_ivas->hSCE[j]->hCoreCoder[0]->input32_fx, Q11, input_frame ); /*Q0*/ + } + IF( st_ivas->hISMDTX ) + f2me_buf( &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc[0][0], &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_fx[0][0], &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_e, st_ivas->nchan_transport * PARAM_ISM_HYS_BUF_SIZE ); + + IF( st_ivas->hMasa != NULL ) + { + st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = floatToFixed( st_ivas->hMasa->data.hOmasaData->lp_noise_CPE, Q8 ); + } + + FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) + { + relE_fx[sce_id][0] = float_to_fix16( relE[sce_id][0], Q8 ); + } +#endif + + IF( st_ivas->hEncoderConfig->Opt_DTX_ON ) + { ivas_ism_get_sce_id_dtx_fx( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->nchan_transport, input_frame ); dtx_flag = ivas_ism_dtx_enc_fx( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, st_ivas->nchan_transport, vad_flag, st_ivas->hIsmMetaData, md_diff_flag, &sid_flag ); @@ -619,10 +719,6 @@ ivas_error ivas_ism_enc( /* estimate coherence between objects */ ivas_ism_coh_estim_dtx_enc_fx( st_ivas->hISMDTX, st_ivas->hSCE, st_ivas->nchan_transport, input_frame ); } -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS /************************fix_to_flt****************************/ - me2f_buf( &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_fx[0][0], st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_e, &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc[0][0], st_ivas->nchan_transport * PARAM_ISM_HYS_BUF_SIZE ); - fixedToFloat_arr( st_ivas->hISMDTX->coh_fx, st_ivas->hISMDTX->coh, Q15, st_ivas->nchan_transport ); -#endif /****************************ends here*********************************/ } /*------------------------------------------------------------------* @@ -639,348 +735,195 @@ ivas_error ivas_ism_enc( IF( dtx_flag ) { -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - /*================flt-to-fix===================================*/ - if ( sid_flag ) - { - if ( GT_16( st_ivas->nchan_transport, 1 ) ) - { - /* write sce id */ - /* quantize and write coherence */ - floatToFixed_arr16( st_ivas->hISMDTX->coh, st_ivas->hISMDTX->coh_fx, Q15, st_ivas->nchan_transport ); - } - } - /*================flt-to-fix===================================*/ -#endif ivas_ism_metadata_sid_enc( st_ivas->hISMDTX, flag_noisy_speech, nchan_ism, st_ivas->nchan_transport, st_ivas->ism_mode, st_ivas->hIsmMetaData, sid_flag, md_diff_flag, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata ); } - ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ){ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - IF( NE_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || NE_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ){ - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ){ - IF( EQ_16( st_ivas->ism_mode, ISM_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ){ - IF( EQ_16( st_ivas->hIsmMetaData[ch]->ism_metadata_flag, 1 ) ){ - IF( NE_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ){ - st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise_fx = float_to_fix16( st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise, Q8 ); -} -IF( st_ivas->hIsmMetaData[ch]->ism_metadata_flag == 0 ) -{ - st_ivas->hIsmMetaData[ch]->azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->radius, Q9 ); - st_ivas->hIsmMetaData[ch]->last_true_radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->last_true_radius, Q9 ); -} -} -} -} -} -IF( st_ivas->hIsmMetaData != NULL ) -{ - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) - { - st_ivas->hIsmMetaData[ch]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->yaw_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->yaw, Q22 ); - st_ivas->hIsmMetaData[ch]->pitch_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->pitch, Q22 ); - st_ivas->hIsmMetaData[ch]->radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->radius, Q9 ); - } -} -#endif - -IF( NE_32( ( error = ivas_ism_metadata_enc( &st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag, L_negate( ONE_IN_Q8 ), 0, NULL, st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame ) ), IVAS_ERR_OK ) ) -{ - return error; -} - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS -IF( st_ivas->hIsmMetaData != NULL ) -{ - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) - { - st_ivas->hIsmMetaData[ch]->last_true_azimuth = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_elevation = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_elevation_fx, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_radius = fix16_to_float( st_ivas->hIsmMetaData[ch]->last_true_radius_fx, Q9 ); - } -} -#endif -} -ELSE /* ISM_MODE_DISC */ -{ - test(); - IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) { - ism_total_brate = 0; - move16(); - FOR( i = 0; i < st_ivas->nSCE; i++ ) + IF( NE_32( ( error = ivas_ism_metadata_enc( &st_ivas->hEncoderConfig->ivas_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata, vad_flag, st_ivas->ism_mode, st_ivas->hParamIsm, st_ivas->hEncoderConfig->ism_extended_metadata_flag, L_negate( ONE_IN_Q8 ), 0, NULL, st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame ) ), IVAS_ERR_OK ) ) { - ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate ); + return error; } } - ELSE + ELSE /* ISM_MODE_DISC */ { - ism_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; - move32(); - } - - ism_total_brate_ref = ism_total_brate; - move32(); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - IF( st_ivas->hMasa != NULL ) - { - st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx = floatToFixed( st_ivas->hMasa->data.hOmasaData->lp_noise_CPE, Q8 ); - } - - IF( NE_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || NE_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) - { - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + test(); + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) { - IF( EQ_16( st_ivas->ism_mode, ISM_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + ism_total_brate = 0; + move16(); + FOR( i = 0; i < st_ivas->nSCE; i++ ) { - IF( EQ_16( st_ivas->hIsmMetaData[ch]->ism_metadata_flag, 1 ) ) - { - IF( NE_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) - { - st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise_fx = float_to_fix16( st_ivas->hSCE[ch]->hCoreCoder[0]->lp_noise, Q8 ); - } - IF( st_ivas->hIsmMetaData[ch]->ism_metadata_flag == 0 ) - { - st_ivas->hIsmMetaData[ch]->azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_elevation_fx = float_to_fix( st_ivas->hIsmMetaData[ch]->last_true_elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->radius, Q9 ); - st_ivas->hIsmMetaData[ch]->last_true_radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->last_true_radius, Q9 ); - } - } + ism_total_brate = L_add( ism_total_brate, st_ivas->hSCE[i]->element_brate ); } } - } - IF( st_ivas->hIsmMetaData != NULL ) - { - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + ELSE { - st_ivas->hIsmMetaData[ch]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); - st_ivas->hIsmMetaData[ch]->yaw_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->yaw, Q22 ); - st_ivas->hIsmMetaData[ch]->pitch_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->pitch, Q22 ); - st_ivas->hIsmMetaData[ch]->radius_fx = float_to_fix16( st_ivas->hIsmMetaData[ch]->radius, Q9 ); + ism_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + move32(); } - } -#endif - IF( NE_32( ( error = ivas_ism_metadata_enc( &ism_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, - nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag, st_ivas->hMasa != NULL ? st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx : 0, flag_omasa_ener_brate, st_ivas->hMasa != NULL ? &( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt ) : NULL, st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame ) ), - IVAS_ERR_OK ) ) - { - return error; - } + ism_total_brate_ref = ism_total_brate; + move32(); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - IF( st_ivas->hIsmMetaData != NULL ) - { - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + IF( NE_32( ( error = ivas_ism_metadata_enc( &ism_total_brate, nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, + nb_bits_metadata, vad_flag, st_ivas->ism_mode, NULL, st_ivas->hEncoderConfig->ism_extended_metadata_flag, st_ivas->hMasa != NULL ? st_ivas->hMasa->data.hOmasaData->lp_noise_CPE_fx : 0, flag_omasa_ener_brate, st_ivas->hMasa != NULL ? &( st_ivas->hMasa->data.hOmasaData->omasa_stereo_sw_cnt ) : NULL, st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame ) ), + IVAS_ERR_OK ) ) { - st_ivas->hIsmMetaData[ch]->last_true_azimuth = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_elevation = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_elevation_fx, Q22 ); - st_ivas->hIsmMetaData[ch]->last_true_radius = fix16_to_float( st_ivas->hIsmMetaData[ch]->last_true_radius_fx, Q9 ); + return error; } - } -#endif - IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) - { - st_ivas->hCPE[0]->brate_surplus = L_sub( ism_total_brate_ref, ism_total_brate ); - move32(); + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) ) + { + st_ivas->hCPE[0]->brate_surplus = L_sub( ism_total_brate_ref, ism_total_brate ); + move32(); + } } -} + update_last_metadata_fx( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS -IF( st_ivas->hIsmMetaData != NULL ) -{ - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + /*----------------------------------------------------------------* + * Write IVAS format signaling in SID frames + *----------------------------------------------------------------*/ + + st = st_ivas->hSCE[0]->hCoreCoder[0]; + + IF( sid_flag ) { - st_ivas->hIsmMetaData[ch]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); - st_ivas->hIsmMetaData[ch]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); + ivas_write_format_sid_fx( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); } -} -#endif -update_last_metadata_fx( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS -IF( st_ivas->hIsmMetaData != NULL ) -{ - FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + /*only metadata encoding is needed for this case*/ + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) ) { - st_ivas->hIsmMetaData[ch]->last_azimuth = fix_to_float( st_ivas->hIsmMetaData[ch]->last_azimuth_fx, Q22 ); - st_ivas->hIsmMetaData[ch]->last_elevation = fix_to_float( st_ivas->hIsmMetaData[ch]->last_elevation_fx, Q22 ); + assert( st_ivas->ism_mode != ISM_MODE_NONE ); + return error; } -} -#endif - -/*----------------------------------------------------------------* - * Write IVAS format signaling in SID frames - *----------------------------------------------------------------*/ - -st = st_ivas->hSCE[0]->hCoreCoder[0]; - -IF( sid_flag ) -{ - ivas_write_format_sid_fx( st_ivas->hEncoderConfig->ivas_format, IVAS_SCE, st->hBstr ); -} -/*only metadata encoding is needed for this case*/ -IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) ) -{ - assert( st_ivas->ism_mode != ISM_MODE_NONE ); - return error; -} - -/*------------------------------------------------------------------* - * CoreCoders encoding - *-----------------------------------------------------------------*/ - -FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) -{ - hSCE = st_ivas->hSCE[sce_id]; - st = hSCE->hCoreCoder[0]; + /*------------------------------------------------------------------* + * CoreCoders encoding + *-----------------------------------------------------------------*/ - /* update pointer to the buffer of indices of the next channel */ - IF( sce_id > 0 ) + FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) { - st->hBstr->ind_list = prev_st->hBstr->ind_list + prev_st->hBstr->nb_ind_tot; - } + hSCE = st_ivas->hSCE[sce_id]; + st = hSCE->hCoreCoder[0]; - if ( st->low_rate_mode ) - { - st->bwidth = WB; - move16(); - } + /* update pointer to the buffer of indices of the next channel */ + IF( sce_id > 0 ) + { + st->hBstr->ind_list = prev_st->hBstr->ind_list + prev_st->hBstr->nb_ind_tot; + } - /*----------------------------------------------------------------* - * Core codec configuration - *----------------------------------------------------------------*/ + if ( st->low_rate_mode ) + { + st->bwidth = WB; + move16(); + } - /* IGF reconfiguration */ - test(); - IF( NE_32( hSCE->last_element_brate, hSCE->element_brate ) || NE_32( st->last_bwidth, st->bwidth ) ) - { - Word16 igf; - igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->rf_mode ); - IF( NE_32( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) + /*----------------------------------------------------------------* + * Core codec configuration + *----------------------------------------------------------------*/ + + /* IGF reconfiguration */ + test(); + IF( NE_32( hSCE->last_element_brate, hSCE->element_brate ) || NE_32( st->last_bwidth, st->bwidth ) ) { - return error; + Word16 igf; + igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->rf_mode ); + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) + { + return error; + } } - } - /* set ACELP@12k8 / ACELP@16k flag for flexible ACELP core */ - test(); - IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) - { - st->flag_ACELP16k = set_ACELP_flag_IVAS( IVAS_SCE, hSCE->element_brate, st->core_brate, 0, 0, -1, -1 ); - move16(); - } - ELSE IF( st->low_rate_mode ) - { - st->flag_ACELP16k = 0; - move16(); - } - ELSE - { - st->flag_ACELP16k = set_ACELP_flag_IVAS( IVAS_SCE, hSCE->element_brate, st->total_brate, 0, 0, -1, -1 ); - move16(); - } + /* set ACELP@12k8 / ACELP@16k flag for flexible ACELP core */ + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) + { + st->flag_ACELP16k = set_ACELP_flag_IVAS( IVAS_SCE, hSCE->element_brate, st->core_brate, 0, 0, -1, -1 ); + move16(); + } + ELSE IF( st->low_rate_mode ) + { + st->flag_ACELP16k = 0; + move16(); + } + ELSE + { + st->flag_ACELP16k = set_ACELP_flag_IVAS( IVAS_SCE, hSCE->element_brate, st->total_brate, 0, 0, -1, -1 ); + move16(); + } -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - relE_fx[sce_id][0] = float_to_fix16( relE[sce_id][0], Q8 ); -#endif - /* modify the coder_type depending on the total_brate per channel */ - coder_type_modif_ivas_fx( st, relE_fx[sce_id][0] ); + /* modify the coder_type depending on the total_brate per channel */ + coder_type_modif_ivas_fx( st, relE_fx[sce_id][0] ); - /*----------------------------------------------------------------* - * Encoder - *----------------------------------------------------------------*/ - test(); - test(); - IF( !dtx_flag || ( dtx_flag && EQ_16( sce_id, st_ivas->hISMDTX->sce_id_dtx ) ) ) - { - IF( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8[sce_id], old_inp_16k[sce_id], ener[sce_id], A[sce_id], Aw[sce_id], epsP[sce_id], lsp_new[sce_id], lsp_mid[sce_id], vad_hover_flag[sce_id], attack_flag[sce_id], realBuffer[sce_id], imagBuffer[sce_id], old_wsp[sce_id], loc_harm[sce_id], cor_map_sum[sce_id], vad_flag_dtx[sce_id], enerBuffer[sce_id], fft_buff[sce_id], 0, ISM_FORMAT, 0 ) ) != IVAS_ERR_OK ) + /*----------------------------------------------------------------* + * Encoder + *----------------------------------------------------------------*/ + test(); + test(); + IF( !dtx_flag || ( dtx_flag && EQ_16( sce_id, st_ivas->hISMDTX->sce_id_dtx ) ) ) { - return error; + IF( ( error = ivas_core_enc( hSCE, NULL, NULL, 1, old_inp_12k8[sce_id], old_inp_16k[sce_id], ener[sce_id], A[sce_id], Aw[sce_id], epsP[sce_id], lsp_new[sce_id], lsp_mid[sce_id], vad_hover_flag[sce_id], attack_flag[sce_id], realBuffer[sce_id], imagBuffer[sce_id], old_wsp[sce_id], loc_harm[sce_id], cor_map_sum[sce_id], vad_flag_dtx[sce_id], enerBuffer[sce_id], fft_buff[sce_id], 0, ISM_FORMAT, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } } - } - /*----------------------------------------------------------------* - * Common updates - *----------------------------------------------------------------*/ + /*----------------------------------------------------------------* + * Common updates + *----------------------------------------------------------------*/ - /* update input samples buffer */ - mvr2r( st->input, st->old_input_signal, input_frame ); + /* update input samples buffer */ + mvr2r( st->input, st->old_input_signal, input_frame ); - hSCE->last_element_brate = hSCE->element_brate; - move32(); + hSCE->last_element_brate = hSCE->element_brate; + move32(); - /* Store previous attack detection flag */ - st->hTranDet->transientDetector.prev_bIsAttackPresent = st->hTranDet->transientDetector.bIsAttackPresent; - move16(); + /* Store previous attack detection flag */ + st->hTranDet->transientDetector.prev_bIsAttackPresent = st->hTranDet->transientDetector.bIsAttackPresent; + move16(); - prev_st = st; -} + prev_st = st; + } -IF( dtx_flag ) -{ - FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) + IF( dtx_flag ) { - IF( NE_16( sce_id, st_ivas->hISMDTX->sce_id_dtx ) ) + FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) { - st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_core; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core_brate = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->core_brate; - st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_L_frame = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_L_frame; - move16(); - move32(); - move16(); + IF( NE_16( sce_id, st_ivas->hISMDTX->sce_id_dtx ) ) + { + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_core; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_core_brate = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->core_brate; + st_ivas->hSCE[sce_id]->hCoreCoder[0]->last_L_frame = st_ivas->hSCE[st_ivas->hISMDTX->sce_id_dtx]->hCoreCoder[0]->last_L_frame; + move16(); + move32(); + move16(); + } } } -} -#ifdef DEBUG_MODE_INFO -if ( dtx_flag ) -{ - float tmpF; - int16_t id, n; + pop_wmops(); - n = 0; - for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( st_ivas->hIsmMetaData != NULL ) { - if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) + FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) { - st = st_ivas->hSCE[sce_id]->hCoreCoder[0]; - id = st->id_element; - - dbgwrite( &st->core, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "core", n, id, ENC ) ); - dbgwrite( &st->extl, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "extl", n, id, ENC ) ); - dbgwrite( &st->bwidth, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "bwidth", n, id, ENC ) ); - tmpF = st->total_brate / 1000.0f; - dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "total_brate", n, id, ENC ) ); - tmpF = st->core_brate / 1000.0f; - dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "core_brate", n, id, ENC ) ); - tmpF = st->extl_brate / 1000.0f; - dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "extl_brate", n, id, ENC ) ); - - dbgwrite( &st->coder_type, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type", n, id, ENC ) ); - dbgwrite( &st->coder_type_raw, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type_raw", n, id, ENC ) ); - dbgwrite( &st->vad_flag, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "vad_flag", n, id, ENC ) ); - dbgwrite( &st->localVAD, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "localVAD", n, id, ENC ) ); + st_ivas->hIsmMetaData[ch]->last_true_azimuth = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx, Q22 ); + st_ivas->hIsmMetaData[ch]->last_true_elevation = fix_to_float( st_ivas->hIsmMetaData[ch]->last_true_elevation_fx, Q22 ); + st_ivas->hIsmMetaData[ch]->last_true_radius = fix16_to_float( st_ivas->hIsmMetaData[ch]->last_true_radius_fx, Q9 ); + st_ivas->hIsmMetaData[ch]->last_azimuth = fix_to_float( st_ivas->hIsmMetaData[ch]->last_azimuth_fx, Q22 ); + st_ivas->hIsmMetaData[ch]->last_elevation = fix_to_float( st_ivas->hIsmMetaData[ch]->last_elevation_fx, Q22 ); } } -} + IF( st_ivas->hISMDTX ) + { + me2f_buf( &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_fx[0][0], st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc_e, &st_ivas->hISMDTX->long_term_energy_stereo_dmx_enc[0][0], st_ivas->nchan_transport * PARAM_ISM_HYS_BUF_SIZE ); + fixedToFloat_arr( st_ivas->hISMDTX->coh_fx, st_ivas->hISMDTX->coh, Q15, st_ivas->nchan_transport ); + } #endif -pop_wmops(); - -return error; + return error; } #endif @@ -991,6 +934,7 @@ return error; * - reconfigure the ISM format encoder *-------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_ism_enc_config( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) @@ -1056,3 +1000,82 @@ ivas_error ivas_ism_enc_config( return error; } +#else +ivas_error ivas_ism_enc_config( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + ivas_error error; + ISM_MODE last_ism_mode; + Word16 nchan_transport_old; + Word16 nSCE_old, nCPE_old; + + error = IVAS_ERR_OK; + move32(); + last_ism_mode = st_ivas->ism_mode; + move16(); + + /* select ISM format mode */ + st_ivas->ism_mode = ivas_ism_mode_select( st_ivas->hEncoderConfig->nchan_inp, st_ivas->hEncoderConfig->ivas_total_brate ); + move16(); + + /* ISM bit-rate switching */ + test(); + IF( NE_16( st_ivas->ism_mode, last_ism_mode ) || NE_32( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + Word32 element_brate_tmp[MAX_NUM_OBJECTS]; + + nchan_transport_old = st_ivas->nchan_transport; + move16(); + + /* Reset and Initialize */ + IF( EQ_16( st_ivas->ism_mode, ISM_MODE_PARAM ) ) + { + st_ivas->nchan_transport = MAX_PARAM_ISM_WAVE; + } + ELSE + { + st_ivas->nchan_transport = st_ivas->hEncoderConfig->nchan_inp; + } + move16(); + + nCPE_old = st_ivas->nCPE; + move16(); + nSCE_old = st_ivas->nSCE; + move16(); + st_ivas->nSCE = st_ivas->nchan_transport; + move16(); + st_ivas->nCPE = 0; + move16(); + + IF( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hEncoderConfig->nchan_inp, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport, imult3216( ( st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport ), CPE_CHANNELS ), MC_MODE_NONE ) ) != IVAS_ERR_OK ) + { + return error; + } + + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MODE_PARAM ) && EQ_16( last_ism_mode, ISM_MODE_DISC ) ) + { + /* Allocate and Initialize the memory used by ParamISM when switch from Discrete ISM */ + IF( ( error = ivas_param_ism_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MODE_DISC ) && EQ_16( last_ism_mode, ISM_MODE_PARAM ) ) + { + /* Deallocate the memory used by ParamISM when switch to Discrete ISM */ + ivas_param_ism_enc_close( &( st_ivas->hParamIsm ), st_ivas->hEncoderConfig->input_Fs ); + } + } + + return error; +} +#endif diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index 5c016561869f4604d9c8567aaa36590b9b1f79a9..fdd17fa68c988b853ac2608da1eb4cd492e919ef 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -2616,7 +2616,7 @@ void ivas_ism_metadata_sid_enc( { IF( EQ_16( ch, hISMDTX->sce_id_dtx ) ) { - continue; + CONTINUE; } Word32 tmp = Mpy_32_32( L_shr( L_deposit_h( hISMDTX->coh_fx[ch] ), 1 ) /*Q30*/, L_deposit_h( sub( shl( 1, nBits_coh ), 1 ) ) ); // Q15 Word32 tmp_2 = L_add( tmp, 16384 /*0.5f in Q15*/ ); @@ -2638,10 +2638,6 @@ void ivas_ism_metadata_sid_enc( hIsmMetaData = hIsmMeta[ch]; #ifdef IVAS_FLOAT_FIXED - /*===============================flt-2-fix======================================*/ - hIsmMetaData->azimuth_fx = floatToFixed( hIsmMetaData->azimuth, Q22 ); - hIsmMetaData->elevation_fx = floatToFixed( hIsmMetaData->elevation, Q22 ); - /*===============================flt-2-fix======================================*/ idx_azimuth = ism_quant_meta_fx( hIsmMetaData->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, q_step_fx, q_step_border_fx, 1 << nBits_azimuth ); idx_elevation = ism_quant_meta_fx( hIsmMetaData->elevation_fx, &valQ_fx, ism_elevation_borders_fx, q_step_fx, q_step_border_fx, 1 << nBits_elevation ); #else diff --git a/lib_enc/ivas_ism_param_enc.c b/lib_enc/ivas_ism_param_enc.c index eed03579efa702d021df487882f8fba2c50d8ea4..d1b83331ef933735bbb16814b6a2a3fd163e19c5 100644 --- a/lib_enc/ivas_ism_param_enc.c +++ b/lib_enc/ivas_ism_param_enc.c @@ -50,7 +50,160 @@ * Local function definitions *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_param_ism_compute_obj_parameters_fx( + const Word16 nchan_ism, /* i : number of ISM channels */ + Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX], /* i : Reference power Qx */ + PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM Enc Handle */ +) +{ + Word16 i, b, m, br, mr; + Word16 brange_start, brange_end, mrange_start, mrange_end, time_merge_fac; + Word16 power_ratios_m[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS]; + Word64 ref_power_local_frame[MAX_NUM_OBJECTS]; + Word64 tmp_ratio; + Word16 e_tmp, tmp1, tmp2; + Word64 Wtmp; + + set64_fx( ref_power_local_frame, 0, MAX_NUM_OBJECTS ); + + assert( nchan_ism == 3 || nchan_ism == 4 ); + + FOR( b = 0; b < hParamIsm->nbands; b++ ) + { + /* current frequency band borders */ + brange_start = hParamIsm->band_grouping[b]; + brange_end = hParamIsm->band_grouping[b + 1]; + move16(); + move16(); + + /* time slots to aggregate for current block */ + time_merge_fac = idiv1616( PARAM_ISM_MDFT_NO_SLOTS, hParamIsm->nblocks[b] ); + + FOR( m = 0; m < hParamIsm->nblocks[b]; m++ ) + { + Word16 index_1, index_2; + Word64 ref_power_local[MAX_NUM_OBJECTS]; + + /* initialize to 0 so unused entries are not considered later */ + set64_fx( ref_power_local, 0, MAX_NUM_OBJECTS ); + + /* current block borders */ + mrange_start = i_mult( m, time_merge_fac ); + mrange_end = i_mult( add( m, 1 ), time_merge_fac ); + + /* for each object, sum up reference power within current T/F tile */ + + FOR( i = 0; i < nchan_ism; i++ ) + { + FOR( mr = mrange_start; mr < mrange_end; mr++ ) + { + FOR( br = brange_start; br < brange_end; br++ ) + { + ref_power_local[i] = W_add( ref_power_local[i], reference_power_obj[i][mr][br] ); // Qx + move64(); + } + } + /* Sum up T/F tiles per object */ + ref_power_local_frame[i] = W_add( ref_power_local[i], ref_power_local_frame[i] ); // Qx + move64(); + } + + /* find two dominant objects and derive object indices for current T/F tile */ + IF( GE_64( ref_power_local[0], ref_power_local[1] ) ) + { + index_1 = 0; + index_2 = 1; + move16(); + move16(); + } + ELSE + { + index_1 = 1; + index_2 = 0; + move16(); + move16(); + } + + FOR( i = MAX_PARAM_ISM_WAVE; i < nchan_ism; i++ ) + { + IF( GT_64( ref_power_local[i], ref_power_local[index_1] ) ) + { + index_2 = index_1; + index_1 = i; + move16(); + move16(); + } + ELSE IF( GT_64( ref_power_local[i], ref_power_local[index_2] ) ) + { + index_2 = i; + move16(); + } + } + + /* Copy the quantized indices */ + hParamIsm->obj_indices[b][m][0] = index_1; + hParamIsm->obj_indices[b][m][1] = index_2; + move16(); + move16(); + + /* Compute power ratios */ + IF( W_add( ref_power_local[index_1], ref_power_local[index_2] ) == 0 ) + { + power_ratios_m[b][m] = ONE_IN_Q14 /* 0.5 in Q15 */; + move16(); + } + ELSE + { + tmp1 = W_norm( ref_power_local[index_1] ); + Wtmp = W_add( ref_power_local[index_1], ref_power_local[index_2] ); + tmp2 = W_norm( Wtmp ); + power_ratios_m[b][m] = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local[index_1], tmp1 ) ), W_extract_h( W_shl( Wtmp, tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp + power_ratios_m[b][m] = shl_sat( power_ratios_m[b][m], sub( e_tmp, sub( tmp1, tmp2 ) ) ); // Q15 + move16(); + move16(); + } + assert( ( power_ratios_m[b][m] >= ONE_IN_Q14 /* 0.5 in Q15 */ ) && ( power_ratios_m[b][m] <= ONE_IN_Q15 /* 1 in Q15 */ ) ); + + /* Quantize power ratios */ + /* Power ratio range [0.5,1] is mapped to [0,1] first, rounding via truncation float->integer */ + hParamIsm->power_ratios_idx[b][m] = extract_h( L_add( L_mult( shl( sub( power_ratios_m[b][m], ONE_IN_Q14 /* 0.5 in Q15 */ ), 1 ), ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ), ONE_IN_Q15 /* 0.5f in Q16 */ ) ); // Q0 + move16(); + assert( ( hParamIsm->power_ratios_idx[b][m] >= 0 ) && ( hParamIsm->power_ratios_idx[b][m] <= ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ) ); + } + } + + /* Check if objects have roughly equal power by comparing reference power of first object against all others*/ + hParamIsm->flag_equal_energy = 1; + move16(); + FOR( i = 1; i < nchan_ism; i++ ) + { + IF( ref_power_local_frame[i] != 0 ) + { + tmp1 = W_norm( ref_power_local_frame[0] ); + tmp2 = W_norm( ref_power_local_frame[i] ); + tmp_ratio = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local_frame[0], tmp1 ) ), W_extract_h( W_shl( ref_power_local_frame[i], tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp + tmp_ratio = W_shl( tmp_ratio, sub( sub( e_tmp, 1 ), sub( tmp1, tmp2 ) ) ); // Q14 + + test(); + IF( GT_64( tmp_ratio, 15974 /* 0.975f in Q14 */ ) && LT_64( tmp_ratio, 16794 /* 1.025f in Q14*/ ) ) + { + hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 1 ); + move16(); + } + ELSE + { + hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 0 ); + move16(); + break; + } + } + } + return; +} + +#else static void ivas_param_ism_compute_obj_parameters( const int16_t nchan_ism, /* i : number of ISM channels */ float reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX], /* i : Reference power */ @@ -173,52 +326,36 @@ static void ivas_param_ism_compute_obj_parameters( return; } +#endif #ifdef IVAS_FLOAT_FIXED -static void ivas_param_ism_enc_quantize_DOA( - const int16_t nchan_ism, /* i : number of ISM channels */ +static void ivas_param_ism_enc_quantize_DOA_fx( + const Word16 nchan_ism, /* i : number of ISM channels */ ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i : ISM metadata */ PARAM_ISM_CONFIG_HANDLE hParamIsm /* i/o: Param ISM encoder handle */ ) { - int16_t i, azi_idx, ele_idx; - float valQ; -#ifdef IVAS_FLOAT_FIXED + Word16 i, azi_idx, ele_idx; Word32 valQ_fx; -#endif - /* Loop over objects */ - for ( i = 0; i < nchan_ism; i++ ) + FOR( i = 0; i < nchan_ism; i++ ) { -#ifdef IVAS_FLOAT_FIXED - /*===============================flt-2-fix======================================*/ - hIsmMetaData[i]->azimuth_fx = floatToFixed( hIsmMetaData[i]->azimuth, Q22 ); - hIsmMetaData[i]->elevation_fx = floatToFixed( hIsmMetaData[i]->elevation, Q22 ); - /*===============================flt-2-fix======================================*/ - /* Quantize the elevation and obtain quantized elevation value and index */ ele_idx = ism_quant_meta_fx( hIsmMetaData[i]->elevation_fx, &valQ_fx, ism_elevation_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_ELEVATION_NBITS ); /* Obtain the index of quantized azimuth values */ azi_idx = ism_quant_meta_fx( hIsmMetaData[i]->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS ); - /*===============================fix-2-flt======================================*/ - valQ = fixedToFloat( valQ_fx, Q22 ); - /*===============================fix-2-flt======================================*/ -#else - /* Quantize the elevation and obtain quantized elevation value and index */ - ele_idx = ism_quant_meta( hIsmMetaData[i]->elevation, &valQ, ism_elevation_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_ELEVATION_NBITS ); - - /* Obtain the index of quantized azimuth values */ - azi_idx = ism_quant_meta( hIsmMetaData[i]->azimuth, &valQ, ism_azimuth_borders, ISM_Q_STEP, ISM_Q_STEP_BORDER, 1 << ISM_AZIMUTH_NBITS ); -#endif /*Replace azimuth with quantized values */ - hIsmMetaData[i]->azimuth = valQ; + hIsmMetaData[i]->azimuth_fx = valQ_fx; + move32(); /* Copy the quantized indices */ hParamIsm->azi_index[i] = azi_idx; + move16(); hParamIsm->ele_index[i] = ele_idx; + move16(); } return; @@ -261,6 +398,199 @@ static void ivas_param_ism_enc_quantize_DOA( * * Downmix input channels to stereo *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_param_ism_stereo_dmx_fx( + Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ + Word32 *data[MAX_NUM_OBJECTS], /* i/o: input signal/stereo dmx Qx */ + const Word16 input_frame /* i : Length of input frame */ +) +{ + Word16 i, j; + Word32 tmp; + Word16 alpha, azi_shift; + Word16 tmp_1, tmp_2, one_by_input_frame; + Word16 cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; // Q14 + Word32 stereo_dmx[2][L_FRAME48k]; + Word16 dmx_gain, dmx_gain_e; + Word64 ene_data, ene_dmx; + Word16 grad; + Word16 last_dmx_gain, last_dmx_gain_e; + Word16 last_cardioid_left; // Q14 + ISM_METADATA_HANDLE hIsmMetaData; + + push_wmops( "ivas_param_ism_st_dmx" ); + + /*Initialization*/ + alpha = ONE_IN_Q14 /* 0.5 in Q15 */; + move16(); + azi_shift = 0; // Q13 + move16(); + dmx_gain = 0; + move16(); + ene_dmx = 0; + move64(); + ene_data = 0; + move64(); + last_dmx_gain = st_ivas->hParamIsm->last_dmx_gain_fx; + move16(); + last_dmx_gain_e = st_ivas->hParamIsm->last_dmx_gain_e; + move16(); + + /* Set the stereo dmx to zero */ + set_zero_fx( stereo_dmx[0], L_FRAME48k ); + set_zero_fx( stereo_dmx[1], L_FRAME48k ); + + one_by_input_frame = BASOP_Util_Divide1616_Scale( 1, input_frame, &tmp_1 ); + one_by_input_frame = shl( one_by_input_frame, tmp_1 ); // Q15 + + /* Loop over all objects */ + FOR( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + hIsmMetaData = st_ivas->hIsmMetaData[i]; + last_cardioid_left = st_ivas->hParamIsm->last_cardioid_left_fx[i]; + move16(); + /*Compute the Cardioids for the corresponding object direction */ + tmp = Mpy_32_32( hIsmMetaData->azimuth_fx, PI_OVER_180_FX ); // Q22 + tmp_1 = add( EVS_PI_BY_2_FX, azi_shift ); // Q13 + tmp = L_sub( L_shr( tmp, Q22 - Q13 ), L_deposit_l( tmp_1 ) ); + IF( LT_32( tmp, -EVS_PI_FX ) ) + { + tmp = L_add( tmp, 2 * EVS_PI_FX ); + } + cardioid_left[i] = add( shr( alpha, 1 ), mult( sub( ONE_IN_Q15 - 1, alpha ), getCosWord16( extract_l( tmp ) ) ) ); // Q14 + move16(); + + IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 ) + { + Word16 last_cardioid_right; + last_cardioid_right = sub( ONE_IN_Q14 /* 1.0f in Q14 */, last_cardioid_left ); + /* Smoothing */ + cardioid_left[i] = add( mult( 24576 /* 0.75f in Q15 */, cardioid_left[i] ), mult( 8192 /* 0.25f in Q15 */, last_cardioid_left ) ); // Q14 + move16(); + grad = mult( sub( cardioid_left[i], last_cardioid_left ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ); /* Q14 */ /* for the right cardioid, multiply with -1 */ + /* Cardioids sum up to 1 */ + cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */ + move16(); + /* Loop over all samples */ + FOR( j = 0; j < shr( input_frame, 1 ); j++ ) + { + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, add( last_cardioid_left, mult0( j, grad ) ) ), 15 ) ); + stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */ + move32(); + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, add( last_cardioid_right, negate( mult0( j, grad ) ) ) ), 15 ) ); + stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */ + move32(); + ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */ + } + FOR( ; j < input_frame; j++ ) + { + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); + stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */ + move32(); + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); + stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */ + move32(); + ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */ + } + } + ELSE + { + /* Cardioids sum up to 1 */ + cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */ + move16(); + /* Loop over all samples */ + FOR( j = 0; j < input_frame; j++ ) + { + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); + stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp ); /* Qx DMX Left */ + move32(); + tmp = data[i][j]; + move32(); + tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); + stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp ); /* Qx DMX Right */ + move32(); + ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */ + } + } + st_ivas->hParamIsm->last_cardioid_left_fx[i] = cardioid_left[i]; + move16(); + } + + /* Energy compensation */ + FOR( j = 0; j < input_frame; j++ ) + { + ene_dmx = W_mac_32_32( W_mac_32_32( ene_dmx, stereo_dmx[0][j], stereo_dmx[0][j] ), stereo_dmx[1][j], stereo_dmx[1][j] ); /* 2 * Qx + 1 */ + } + tmp_1 = W_norm( ene_data ); + tmp_2 = W_norm( ene_dmx ); + ene_data = W_shl( ene_data, tmp_1 ); + ene_dmx = W_add( W_shl( ene_dmx, tmp_2 ), 1 ); + dmx_gain = BASOP_Util_Divide3232_Scale( W_extract_h( ene_data ), W_extract_h( ene_dmx ), &dmx_gain_e ); + dmx_gain_e = sub( dmx_gain_e, sub( tmp_1, tmp_2 ) ); + dmx_gain = Sqrt16( dmx_gain, &dmx_gain_e ); + + /* Smoothing */ + IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 ) + { + dmx_gain_e = BASOP_Util_Add_MantExp( mult( 24576 /* 0.75f */, dmx_gain ), dmx_gain_e, mult( 8192 /* 0.25f */, last_dmx_gain ), last_dmx_gain_e, &dmx_gain ); + /* 10ms ramp */ + tmp = L_shl( last_dmx_gain, last_dmx_gain_e ); // Q15 + grad = extract_l( Mpy_32_16_r( L_sub( L_shl( dmx_gain, dmx_gain_e ), tmp ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ) ); /* Q15 */ /* slope between two consecutive gains, 480 samples length */ + + tmp_1 = 15 + 1; + move16(); + FOR( i = 0; i < shr( input_frame, 1 ); i++ ) + { + stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[0][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx + move32(); + stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[1][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx + move32(); + } + tmp_1 = add( sub( 15, dmx_gain_e ), 1 ); + FOR( ; i < input_frame; i++ ) + { + stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][i], dmx_gain ), tmp_1 ) ); // Qx + move32(); + stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][i], dmx_gain ), tmp_1 ) ); // Qx + move32(); + } + } + ELSE + { + tmp_1 = add( sub( 15, dmx_gain_e ), 1 ); + FOR( j = 0; j < input_frame; j++ ) + { + stereo_dmx[0][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][j], dmx_gain ), tmp_1 ) ); // Qx + move32(); + stereo_dmx[1][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][j], dmx_gain ), tmp_1 ) ); // Qx + move32(); + } + } + st_ivas->hParamIsm->last_dmx_gain_fx = dmx_gain; + move16(); + st_ivas->hParamIsm->last_dmx_gain_e = dmx_gain_e; + move16(); + + /* Copy the stereo dmx to data variable */ + Copy32( stereo_dmx[0], data[0], input_frame ); // Qx + Copy32( stereo_dmx[1], data[1], input_frame ); // Qx + + pop_wmops(); + + return; +} + +#else void ivas_param_ism_stereo_dmx( Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ @@ -382,7 +712,7 @@ void ivas_param_ism_stereo_dmx( return; } - +#endif /*-------------------------------------------------------------------------* * ivas_param_ism_enc_open() @@ -390,6 +720,7 @@ void ivas_param_ism_stereo_dmx( * Open Param ISM handle *-------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_param_ism_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) @@ -446,6 +777,68 @@ ivas_error ivas_param_ism_enc_open( return error; } +#else +ivas_error ivas_param_ism_enc_open( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + Word16 i; + IVAS_FB_CFG *fb_cfg; + PARAM_ISM_CONFIG_HANDLE hParamIsm; + Word16 max_bins; + Word32 input_Fs; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + /* Assign memory to Param Object handle */ + if ( ( hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM\n" ) ); + } + + input_Fs = st_ivas->hEncoderConfig->input_Fs; + move32(); + + + /* set FB config. */ + IF( ( error = ivas_fb_set_cfg( &fb_cfg, ISM_FORMAT, st_ivas->hEncoderConfig->nchan_inp, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Allocate and initialize FB mixer handle */ + IF( ( error = ivas_FB_mixer_open_fx( &( hParamIsm->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_param_ism_config_fx( hParamIsm, st_ivas->hEncoderConfig->nchan_inp ); + + /* Assign memories for Band and Block grouping */ + hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; + move16(); + + max_bins = extract_l( Mpy_32_32( input_Fs, 10737418 ) ); // (int16_t) ( ( MDFT_FB_BANDS_240 * input_Fs ) / 48000 ); + FOR( i = 0; i < ( hParamIsm->nbands + 1 ); i++ ) + { + hParamIsm->band_grouping[i] = CLDFB_TO_MDFT_FAC * Param_ISM_band_grouping[i]; + move16(); + IF( GT_16( i_mult( Param_ISM_band_grouping[i], CLDFB_TO_MDFT_FAC ), max_bins ) ) + { + hParamIsm->band_grouping[i] = max_bins; + move16(); + } + } + + set16_fx( hParamIsm->noisy_speech_buffer, 0, PARAM_ISM_HYS_BUF_SIZE ); + + st_ivas->hParamIsm = hParamIsm; + + return error; +} +#endif /*-------------------------------------------------------------------------* @@ -454,6 +847,7 @@ ivas_error ivas_param_ism_enc_open( * Close Param ISM encoder handle *-------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void ivas_param_ism_enc_close( PARAM_ISM_CONFIG_HANDLE *hParamIsm, /* i/o: ParamISM handle */ const int32_t input_Fs /* i : input sampling_rate */ @@ -471,6 +865,26 @@ void ivas_param_ism_enc_close( return; } +#else +void ivas_param_ism_enc_close( + PARAM_ISM_CONFIG_HANDLE *hParamIsm, /* i/o: ParamISM handle */ + const Word32 input_Fs /* i : input sampling_rate */ +) +{ + test(); + IF( hParamIsm == NULL || *hParamIsm == NULL ) + { + return; + } + + ivas_FB_mixer_close_fx( &( *hParamIsm )->hFbMixer, input_Fs, 0 ); + + free( ( *hParamIsm ) ); + ( *hParamIsm ) = NULL; + + return; +} +#endif /*-------------------------------------------------------------------------* @@ -479,6 +893,75 @@ void ivas_param_ism_enc_close( * Parametric ISM encoder *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_param_ism_enc_fx( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + Word32 *data[MAX_NUM_OBJECTS], /* i : input signal q_pcm_in */ + const Word16 input_frame, /* i : input frame length per channel */ + const Word16 q_pcm_in ) +{ + Word16 i, j, ts, l_ts; + Word16 nchan_ism; + Word16 num_time_slots; + Word16 q_p_fb_Buffer; + Word32 *pcm_in[MAX_NUM_OBJECTS]; + Word32 fb_RealBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX]; + Word32 fb_ImagBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX]; + Word32 *p_fb_RealBuffer[MAX_NUM_OBJECTS]; + Word32 *p_fb_ImagBuffer[MAX_NUM_OBJECTS]; + Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX]; + PARAM_ISM_CONFIG_HANDLE hParamIsm; + + nchan_ism = st_ivas->hEncoderConfig->nchan_ism; + move16(); + hParamIsm = st_ivas->hParamIsm; + + push_wmops( "ivas_param_ism_enc" ); + + l_ts = shr( input_frame, 2 ); /* input_frame / PARAM_ISM_MDFT_NO_SLOTS */ + num_time_slots = PARAM_ISM_MDFT_NO_SLOTS; + move16(); + + FOR( i = 0; i < nchan_ism; i++ ) + { + pcm_in[i] = data[i]; + + set_zero_fx( fb_RealBuffer[i], DIRAC_NO_FB_BANDS_MAX ); + set_zero_fx( fb_ImagBuffer[i], DIRAC_NO_FB_BANDS_MAX ); + p_fb_RealBuffer[i] = &fb_RealBuffer[i][0]; + p_fb_ImagBuffer[i] = &fb_ImagBuffer[i][0]; + } + + Word16 gb = find_guarded_bits_fx( l_ts ); + q_p_fb_Buffer = sub( q_pcm_in, gb ); + + FOR( ts = 0; ts < num_time_slots; ts++ ) + { + ivas_fb_mixer_get_windowed_fr_fx( hParamIsm->hFbMixer, pcm_in, p_fb_RealBuffer, p_fb_ImagBuffer, l_ts, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans, gb ); + + ivas_fb_mixer_update_prior_input_fx( hParamIsm->hFbMixer, pcm_in, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans ); + + FOR( i = 0; i < nchan_ism; i++ ) + { + pcm_in[i] += l_ts; + FOR( j = 0; j < DIRAC_NO_FB_BANDS_MAX; j++ ) + { + reference_power_obj[i][ts][j] = W_shr( W_add( W_mult0_32_32( fb_RealBuffer[i][j], fb_RealBuffer[i][j] ), W_mult0_32_32( fb_ImagBuffer[i][j], fb_ImagBuffer[i][j] ) ), shl( q_p_fb_Buffer, 1 ) ); // Q0 + move64(); + } + } + } + + ivas_param_ism_enc_quantize_DOA_fx( nchan_ism, st_ivas->hIsmMetaData, hParamIsm ); + + ivas_param_ism_compute_obj_parameters_fx( nchan_ism, reference_power_obj, hParamIsm ); + + pop_wmops(); + return; +} + +#else + void ivas_param_ism_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ float *data[MAX_NUM_OBJECTS], /* i : input signal */ @@ -539,7 +1022,7 @@ void ivas_param_ism_enc( pop_wmops(); return; } - +#endif /*-------------------------------------------------------------------* * ivas_param_ism_compute_noisy_speech_flag() diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index 1684d34a143e64468438dbfc56e7cd18b596dac0..7794f0cfefc73cc653ec53b969463e6d0918f9b4 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -166,6 +166,8 @@ ivas_error ivas_masa_enc_open( hMasa->data.onset_detector_2 = 0.0f; set_zero( hMasa->data.lfeToTotalEnergyRatio, MAX_PARAM_SPATIAL_SUBFRAMES ); + set32_fx( hMasa->data.lfeToTotalEnergyRatio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set16_fx( hMasa->data.lfeToTotalEnergyRatio_e, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); hMasa->data.prevq_lfeToTotalEnergyRatio = 0.0f; hMasa->data.prevq_lfeIndex = 0; @@ -539,10 +541,36 @@ ivas_error ivas_masa_encode( } else { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < hQMetaData->no_directions; i++ ) + { + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].energy_ratio, hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, Q30, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].azimuth, hQMetaData->q_direction[i].band_data[j].azimuth_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].elevation, hQMetaData->q_direction[i].band_data[j].elevation_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].q_azimuth, hQMetaData->q_direction[i].band_data[j].q_azimuth_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + floatToFixed_arrL( hQMetaData->q_direction[i].band_data[j].q_elevation, hQMetaData->q_direction[i].band_data[j].q_elevation_fx, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } +#endif if ( ( error = ivas_qmetadata_enc_encode( hMetaData, hQMetaData, 0 ) ) != IVAS_ERR_OK ) { return error; } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < hQMetaData->no_directions; i++ ) + { + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, hQMetaData->q_direction[i].band_data[j].energy_ratio, Q30, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].azimuth_fx, hQMetaData->q_direction[i].band_data[j].azimuth, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].elevation_fx, hQMetaData->q_direction[i].band_data[j].elevation, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].q_azimuth_fx, hQMetaData->q_direction[i].band_data[j].q_azimuth, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + fixedToFloat_arrL( hQMetaData->q_direction[i].band_data[j].q_elevation_fx, hQMetaData->q_direction[i].band_data[j].q_elevation, Q22, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } +#endif } #ifndef IVAS_FLOAT_FIXED @@ -1379,6 +1407,80 @@ ivas_error ivas_masa_enc_config( return error; } +/*-----------------------------------------------------------------------* + * ivas_masa_surrcoh_signicant() + * + * Determine if surrounding coherence is significant in this frame and should be encoded + *-----------------------------------------------------------------------*/ +UWord8 ivas_masa_surrcoh_signicant_fx( + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Surround coherence */ + Word32 diffuse_to_total_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Diffuse to total ratio */ + const Word16 nSubFrames, /* i : Number of sub frames */ + const Word16 nBands /* i : Number of frequency bands */ /* i : dynamic (min q for surroundingCoherence and diffuse_to_total_ratio) */ +) +{ + Word32 significanceMeasure1, significanceMeasure2, significanceMeasure; + Word32 surrCohToTotal, surrCohToTotalSum, surrCohToTotalTimesDiffSum, diffSum; + Word32 sf, band; + Word16 surrCohToTotalSum_e, surrCohToTotalTimesDiffSum_e, diffSum_e; + + // input buffers Q=31 + Word32 surrCohSignificanceCoef = 858993459; //( 0.4 * ( 1 << q ) ) 0.4 scaled to Q=31 + move32(); + Word32 threshold = 214748365; //( 0.1 * ( 1 << q ) ) 0.1 scaled to Q=31 + move32(); + FOR( sf = 0; sf < nSubFrames; sf++ ) + { + surrCohToTotalSum = 0; + move32(); + surrCohToTotalSum_e = 0; + move16(); + surrCohToTotalTimesDiffSum = 0; + move32(); + surrCohToTotalTimesDiffSum_e = 0; + move16(); + diffSum = 0; + move32(); + diffSum_e = 0; + move16(); + + FOR( band = 0; band < nBands; band++ ) + { + surrCohToTotal = Mpy_32_32( diffuse_to_total_ratio[sf][band], surroundingCoherence[sf][band] ); // 2Q -> Q + surrCohToTotalSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalSum, surrCohToTotalSum_e, surrCohToTotal, 0, &surrCohToTotalSum_e ); + surrCohToTotalTimesDiffSum = BASOP_Util_Add_Mant32Exp( surrCohToTotalTimesDiffSum, surrCohToTotalTimesDiffSum_e, Mpy_32_32( (Word32) diffuse_to_total_ratio[sf][band], surrCohToTotal ), 0, &surrCohToTotalTimesDiffSum_e ); // Q2 -> Q + diffSum = BASOP_Util_Add_Mant32Exp( diffSum, diffSum_e, diffuse_to_total_ratio[sf][band], 0, &diffSum_e ); // Q + } + + Word16 significanceMeasure1_e, significanceMeasure2_e; + Word16 significanceMeasure_e; + significanceMeasure1 = L_deposit_h( BASOP_Util_Divide3216_Scale( surrCohToTotalSum, nBands, &significanceMeasure1_e ) ); // e1 exponent + significanceMeasure1_e = add( significanceMeasure1_e, sub( surrCohToTotalSum_e, 15 ) ); + significanceMeasure2 = L_deposit_h( BASOP_Util_Divide3232_Scale( Mpy_32_32( surrCohSignificanceCoef, surrCohToTotalTimesDiffSum ), L_add( diffSum, EPSILON_FX ), &significanceMeasure2_e ) ); // e2 exponent + significanceMeasure2_e = add( significanceMeasure2_e, sub( surrCohToTotalTimesDiffSum_e, diffSum_e ) ); + + IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure1, significanceMeasure1_e, significanceMeasure2, significanceMeasure2_e ) > 0 ) + { + significanceMeasure = significanceMeasure1; + move32(); + significanceMeasure_e = significanceMeasure1_e; + move16(); + } + ELSE + { + significanceMeasure = significanceMeasure2; + move32(); + significanceMeasure_e = significanceMeasure2_e; + move16(); + } + IF( BASOP_Util_Cmp_Mant32Exp( significanceMeasure, significanceMeasure_e, threshold, 0 ) > 0 ) // Q31 Comparision + { + return 1; + } + } + + return 0; +} /*-----------------------------------------------------------------------* * ivas_masa_surrcoh_signicant() @@ -3202,6 +3304,195 @@ void ivas_merge_masa_metadata( return; } +#ifdef IVAS_FLOAT_FIXED +static void quantize_ratio_ism_vector_ivas_fx( + const Word16 *ratio_ism, /* ratio_ism_e */ + Word16 ratio_ism_e, + Word16 *idx, /* Q0 */ + const Word16 nchan_ism, + const Word32 masa_to_total_energy_ratio, + const Word16 idx_sep_object ) +{ + Word16 i, j, best_i, best_i2; + Word16 dist, div, tmp, dist2, best_dist, temp, temp_e, tmp_e, idx_e, best_dist_e, dist_e, dist2_e; + Word16 part_idx_sum, max_sum_idx; + Word16 ratio_ism_loc[MAX_NUM_OBJECTS]; + Word16 no_ism_loc; + + max_sum_idx = sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 ); + + test(); + IF( GT_16( idx_sep_object, -1 ) ) + { + temp = BASOP_Util_Divide1616_Scale( 1, max_sum_idx, &temp_e ); + BASOP_Util_Add_MantExp( ratio_ism[idx_sep_object], ratio_ism_e, negate( temp ), temp_e, &tmp ); + + test(); + IF( tmp < 0 ) + { + /* take it out from quantize function */ + Copy( ratio_ism, ratio_ism_loc, idx_sep_object ); + Copy( &ratio_ism[idx_sep_object + 1], &ratio_ism_loc[idx_sep_object], nchan_ism - idx_sep_object - 1 ); + no_ism_loc = sub( nchan_ism, 1 ); + } + ELSE + { + no_ism_loc = nchan_ism; + move16(); + Copy( ratio_ism, ratio_ism_loc, nchan_ism ); + } + } + ELSE + { + no_ism_loc = nchan_ism; + move16(); + Copy( ratio_ism, ratio_ism_loc, nchan_ism ); + } + + test(); + IF( GT_16( nchan_ism, 1 ) ) + { + test(); + IF( GE_32( masa_to_total_energy_ratio, MASA2TOTAL_THR_Q30 ) ) + { + distribute_evenly_ism_fx( idx, max_sum_idx, nchan_ism ); + } + ELSE + { + test(); + IF( GT_16( no_ism_loc, 1 ) ) + { + + dist = 0; + dist_e = 0; + div = div_s( 1, max_sum_idx ); // Q15 + move16(); + move16(); + + part_idx_sum = 0; + move16(); + + FOR( i = 0; i < no_ism_loc; i++ ) + { + idx[i] = mult( ratio_ism_loc[i], max_sum_idx ); // exponent : ratio_ism_e + 15 + move16(); + idx[i] = shl( idx[i], sub( add( ratio_ism_e, 15 ), 15 ) ); // Q0 + move16(); + part_idx_sum = add( part_idx_sum, idx[i] ); + + tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( imult1616( idx[i], div ) ), 0, &tmp ); // tmp_e + dist_e = BASOP_Util_Add_MantExp( dist, dist_e, mult( tmp, tmp ), add( tmp_e, tmp_e ), &dist ); // dist_e + } + + best_dist = dist; + best_dist_e = dist_e; + best_i2 = -1; + move16(); + move16(); + move16(); + + WHILE( LT_16( part_idx_sum, max_sum_idx ) ) + { + best_i = -1; + move16(); + /* check which index to increase by 1 for a possible improvement */ + + FOR( i = 0; i < no_ism_loc; i++ ) + { + idx[i] = add( idx[i], 1 ); + move16(); + dist2 = 0; + dist2_e = 0; + move16(); + move16(); + + FOR( j = 0; j < no_ism_loc; j++ ) + { + Word32 temp1 = L_mult( idx[i], div ); // Q : 15 + 0 + 1 + Word16 temp1_n = norm_l( temp1 ); + Word16 temp1_16 = extract_h( L_shl( temp1, temp1_n ) ); // Q : Q + temp1_n - 16 + tmp_e = BASOP_Util_Add_MantExp( ratio_ism_loc[i], ratio_ism_e, negate( temp1_16 ), sub( 15, temp1_n ), &tmp ); // tmp_e + dist2_e = BASOP_Util_Add_MantExp( dist2, dist2_e, mult_sat( tmp, tmp ), add( tmp_e, tmp_e ), &dist2 ); // dist_e + } + + BASOP_Util_Add_MantExp( dist2, dist2_e, negate( best_dist ), best_dist_e, &tmp ); + test(); + IF( tmp < 0 ) + { + best_i2 = best_i; + best_i = i; + best_dist = dist2; + best_dist_e = dist2_e; + move16(); + move16(); + move16(); + move16(); + } + idx[i] = sub( idx[i], 1 ); + move16(); + } + + test(); + IF( GT_16( best_i, -1 ) ) + { + idx[best_i] = add( idx[best_i], 1 ); + move16(); + part_idx_sum = add( part_idx_sum, 1 ); + } + ELSE + { + test(); + IF( GT_16( best_i2, -1 ) ) + { + idx[best_i2] = add( idx[best_i2], 1 ); + move16(); + part_idx_sum = add( part_idx_sum, 1 ); + } + ELSE + { + idx[no_ism_loc - 1] = add( idx[no_ism_loc - 1], sub( max_sum_idx, part_idx_sum ) ); + move16(); + part_idx_sum = max_sum_idx; + move16(); + } + } + } + assert( sum_s( idx, no_ism_loc ) == max_sum_idx ); + } + ELSE + { + idx[0] = max_sum_idx; + move16(); + } + + test(); + IF( LT_16( no_ism_loc, nchan_ism ) ) + { + /* insert back the ratio of the separated object */ + FOR( i = nchan_ism - 1; i > idx_sep_object; i-- ) + { + idx[i] = idx[i - 1]; + move16(); + } + idx[idx_sep_object] = 0; + move16(); + } + } + } + ELSE + { + // idx[0] = (int16_t) ( ( ratio_ism[0] ) * ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) + 0.5f ); + tmp = imult1616( ratio_ism[0], sub( shl( 1, PARAM_ISM_POW_RATIO_NBITS ), 1 ) ); // tmp_e + tmp_e = ratio_ism_e; + move16(); + idx_e = BASOP_Util_Add_MantExp( tmp, tmp_e, 16384 /* 0.5 in Q15 */, 0, &idx[0] ); // idx_e + idx[0] = shl( idx[0], sub( idx_e, 15 ) ); // Q0 + move16(); + } + + return; +} +#else static void quantize_ratio_ism_vector( const float *ratio_ism, @@ -3338,7 +3629,7 @@ static void quantize_ratio_ism_vector( return; } - +#endif static int16_t index_slice_enum( const int16_t *ratio_ism_idx, @@ -3404,6 +3695,29 @@ static void transform_difference_index( return; } +static void transform_difference_index_ivas_fx( + const Word16 *diff_idx, + Word16 *idx, + const Word16 len ) +{ + Word16 i; + FOR( i = 0; i < len; i++ ) + { + IF( diff_idx[i] <= 0 ) + { + idx[i] = negate( shl( diff_idx[i], 1 ) ); + move16(); + } + ELSE + { + idx[i] = sub( shl( diff_idx[i], 1 ), 1 ); + move16(); + } + } + + return; +} + static void transform_index_and_GR_encode( int16_t *diff_idx, /* i : differenc eindex to encode */ @@ -3427,6 +3741,28 @@ static void transform_index_and_GR_encode( return; } +static void transform_index_and_GR_encode_ivas_fx( + Word16 *diff_idx, /* i : differenc eindex to encode */ + const Word16 len, /* i : input length */ + const Word16 GR_order, /* i : GR order */ + BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ +) +{ + Word16 i; + Word16 idx[IVAS_MAX_NUM_OBJECTS]; + + /* transform difference index into positive */ + transform_difference_index_ivas_fx( diff_idx, idx, len ); + + /* GR encoding */ + FOR( i = 0; i < len; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, idx[i], 100, GR_order ); + } + + return; +} + static int16_t try_differential( const int16_t numCodingBands, @@ -3478,7 +3814,7 @@ static int16_t try_differential( return nbits0; } - +#ifndef IVAS_FLOAT_FIXED static void differential_coding_first_subframe( BSTR_ENC_HANDLE hMetaData, const float *masa_to_total_energy_ratio, @@ -3517,7 +3853,46 @@ static void differential_coding_first_subframe( return; } +#else +static void differential_coding_first_subframe_ivas_fx( + BSTR_ENC_HANDLE hMetaData, + const Word32 *masa_to_total_energy_ratio, // Q30 + const Word16 b_signif, + Word16 ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], + const Word16 nchan_ism, + const Word16 numCodingBands, + const Word16 bits_index ) +{ + Word16 index, b; + Word16 ratio_ism_idx_ref[MAX_NUM_OBJECTS]; + Word16 diff_idx[MAX_NUM_OBJECTS]; + + /* differential encoding*/ + push_next_indice( hMetaData, 0, 1 ); + + IF( LT_16( b_signif, numCodingBands ) ) + { + index = index_slice_enum( ratio_ism_idx[b_signif], nchan_ism ); + push_next_indice( hMetaData, index, bits_index ); + + Copy( ratio_ism_idx[b_signif], ratio_ism_idx_ref, nchan_ism ); + + FOR( b = b_signif + 1; b < numCodingBands; b++ ) + { + IF( LT_32( masa_to_total_energy_ratio[b], MASA2TOTAL_THR_Q30 ) ) + { + v_sub_s16_fx( ratio_ism_idx[b], ratio_ism_idx_ref, diff_idx, nchan_ism ); + Copy( ratio_ism_idx[b], ratio_ism_idx_ref, nchan_ism ); + /* transform difference index into positive */ + transform_index_and_GR_encode_ivas_fx( diff_idx, sub( nchan_ism, 1 ), 0, hMetaData ); + } + } + } + + return; +} +#endif static void independent_coding_ratio_ism_idx( int16_t ratio_ism_idx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], /* i : ISM ratios */ @@ -3608,7 +3983,8 @@ static int16_t encode_ratio_ism_subframe( const int16_t sf, int16_t ratio_ism_idx_prev_sf[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS], BSTR_ENC_HANDLE hMetaData, - const float *masa_to_total_energy_ratio, + // const float *masa_to_total_energy_ratio, + float *masa_to_total_energy_ratio, const int16_t shift_one, const int16_t idx_separated_obj ) { @@ -3667,7 +4043,15 @@ static int16_t encode_ratio_ism_subframe( { if ( nbits > 0 ) { +#ifndef IVAS_FLOAT_FIXED differential_coding_first_subframe( hMetaData, masa_to_total_energy_ratio, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 masa_to_total_energy_ratio_fx[MASA_FREQUENCY_BANDS]; + floatToFixed_arrL( masa_to_total_energy_ratio, masa_to_total_energy_ratio_fx, 30, MASA_FREQUENCY_BANDS ); +#endif + differential_coding_first_subframe_ivas_fx( hMetaData, masa_to_total_energy_ratio_fx, b_signif, ratio_ism_idx, nchan_ism, numCodingBands, bits_index ); +#endif nbits = nbits0 + 1; } } @@ -4031,7 +4415,31 @@ static void ivas_encode_masaism_metadata( } /* Quantize ISM ratios */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ratio_ism_fx[MASA_FREQUENCY_BANDS][MAX_NUM_OBJECTS]; + + Word16 ratio_ism_fx_q = Q_factor_arr( ratio_ism[band], nchan_ism ); + + floatToFixed_arr( ratio_ism[band], ratio_ism_fx[band], ratio_ism_fx_q, nchan_ism ); + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + floatToFixed_arrL( hOmasaData->masa_to_total_energy_ratio[i], hOmasaData->masa_to_total_energy_ratio_fx[i], Q30, MASA_FREQUENCY_BANDS ); + } +#endif + quantize_ratio_ism_vector_ivas_fx( ratio_ism_fx[band], sub( Q15, ratio_ism_fx_q ), ratio_ism_idx[band], nchan_ism, hOmasaData->masa_to_total_energy_ratio_fx[sf][band], idx_separated_object ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( ratio_ism_fx[band], ratio_ism[band], ratio_ism_fx_q, nchan_ism ); + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + fixedToFloat_arrL( hOmasaData->masa_to_total_energy_ratio_fx[i], hOmasaData->masa_to_total_energy_ratio[i], Q30, MASA_FREQUENCY_BANDS ); + } +#endif +#else quantize_ratio_ism_vector( ratio_ism[band], ratio_ism_idx[band], nchan_ism, hOmasaData->masa_to_total_energy_ratio[sf][band], idx_separated_object ); +#endif if ( n_ism_tmp == numCodingBands && ratio_ism_idx[band][idx_separated_object] != 0 && hOmasaData->masa_to_total_energy_ratio[sf][band] < MASA2TOTAL_THR ) { i = 0; diff --git a/lib_enc/ivas_mc_param_enc.c b/lib_enc/ivas_mc_param_enc.c index ed2cc5a68ef7067addd4aaca52cd89e6335e70cd..12eded9c0870f383e95151e6c9de18d70422d46b 100644 --- a/lib_enc/ivas_mc_param_enc.c +++ b/lib_enc/ivas_mc_param_enc.c @@ -38,23 +38,27 @@ #include "ivas_rom_enc.h" #include "rom_com.h" #include "prot.h" +#include "prot_fx.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#endif /*------------------------------------------------------------------------- * Local function prototypes *------------------------------------------------------------------------*/ -static void ivas_param_mc_dmx( PARAM_MC_ENC_HANDLE hParamMC, float *data_f[], float data_dmx[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_input, const int16_t nchan_transport ); static void ivas_param_mc_param_est_enc( PARAM_MC_ENC_HANDLE hParamMC, float *data_f[], float Cy_sum[][MAX_CICP_CHANNELS][MAX_CICP_CHANNELS], float Cx_sum[][PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_TRANSPORT_CHANS], const int16_t input_frame, const int16_t nchan_input, const int16_t nchan_transport ); static void ivas_param_mc_parameter_quantizer( const float *x, const int16_t L, const int16_t sz_quantizer, const float *quantizer, int16_t *quant_idx, float *y ); -static void ivas_param_mc_transient_detection( PARAM_MC_ENC_HANDLE hParamMC, TRAN_DET_HANDLE hTranDet, int16_t *bAttackPresent, int16_t *attackIdx ); #ifndef FIX_901_PARAMMC_DEAD_CODE static void ivas_param_mc_enc_find_icc_map( PARAM_MC_ENC_HANDLE hParamMC, float Cx_sum[][PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_TRANSPORT_CHANS], float Cy_sum[][MAX_CICP_CHANNELS][MAX_CICP_CHANNELS], float ILD_q[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_SZ_ILD_MAP], const int16_t nchan_input, const int16_t nchan_transport ); @@ -72,6 +76,22 @@ static void ivas_param_mc_encode_parameter( int16_t *idx_in, HANDLE_IVAS_PARAM_M static void ivas_param_mc_range_encoder( const int16_t *seq_in, const int16_t num_symbols, const uint16_t *cum_freq, const uint16_t *sym_freq, const uint16_t tot_shift, const int16_t max_nb_bits, uint16_t *bit_buffer, int16_t *bit_pos ); +#ifdef IVAS_FLOAT_FIXED + +#define ATTACKTHRESHOLD_E 4 + +static void ivas_param_mc_dmx_fx( PARAM_MC_ENC_HANDLE hParamMC, Word32 *data_f_fx[], Word32 data_dmx_fx[][L_FRAME48k], const Word16 input_frame, const Word16 nchan_input, const Word16 nchan_transport ); + +static void ivas_param_mc_transient_detection_fx( PARAM_MC_ENC_HANDLE hParamMC, TRAN_DET_HANDLE hTranDet, Word16 *bAttackPresent, Word16 *attackIdx ); + +#else + +static void ivas_param_mc_dmx( PARAM_MC_ENC_HANDLE hParamMC, float *data_f[], float data_dmx[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_input, const int16_t nchan_transport ); + +static void ivas_param_mc_transient_detection( PARAM_MC_ENC_HANDLE hParamMC, TRAN_DET_HANDLE hTranDet, int16_t *bAttackPresent, int16_t *attackIdx ); + +#endif + /*------------------------------------------------------------------------- * ivas_param_mc_enc_open() * @@ -133,6 +153,9 @@ ivas_error ivas_param_mc_enc_open( /* get dmx factors */ hParamMC->dmx_factors = ivas_param_mc_conf[config_index].dmx_fac; +#ifdef IVAS_FLOAT_FIXED + hParamMC->dmx_factors_fx = ivas_param_mc_conf[config_index].dmx_fac_fx; +#endif /* set FB config. */ if ( ( error = ivas_fb_set_cfg( &fb_cfg, MC_FORMAT, nchan_inp, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) @@ -278,6 +301,9 @@ ivas_error ivas_param_mc_enc_reconfig( /* get dmx factors */ hParamMC->dmx_factors = ivas_param_mc_conf[config_index].dmx_fac; +#ifdef IVAS_FLOAT_FIXED + hParamMC->dmx_factors_fx = ivas_param_mc_conf[config_index].dmx_fac_fx; +#endif #ifndef FIX_901_PARAMMC_DEAD_CODE /* deallocate the full icc map, gets newly allocated in the metadata open function */ @@ -397,6 +423,215 @@ void ivas_param_mc_enc_close( * Parametric MC Encoder main encoding function *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_param_mc_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ + BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ + float *data_f[], /* i/o: input/transport MC data */ + const int16_t input_frame /* i : input frame length */ +) +{ + int16_t k; +#ifdef IVAS_FLOAT_FIXED + Word32 *data_f_fx[12]; + for ( k = 0; k < 12; k++ ) + { + data_f_fx[k] = (Word32 *) malloc( input_frame * sizeof( Word32 ) ); + } +#endif + float Cy_sum[PARAM_MC_MAX_PARAMETER_BANDS][MAX_CICP_CHANNELS][MAX_CICP_CHANNELS]; + float Cx_sum[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_MAX_TRANSPORT_CHANS][PARAM_MC_MAX_TRANSPORT_CHANS]; + float ILD_q[PARAM_MC_MAX_PARAMETER_BANDS][PARAM_MC_SZ_ILD_MAP]; + int16_t ILD_idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP]; + int16_t ICC_idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ICC_MAP]; + uint16_t bit_buffer[PARAM_MC_MAX_BITS]; + int16_t bit_pos; + int16_t band_step; + float data_dmx[PARAM_MC_MAX_TRANSPORT_CHANS][L_FRAME48k]; +#ifdef IVAS_FLOAT_FIXED + Word32 data_dmx_fx[PARAM_MC_MAX_TRANSPORT_CHANS][L_FRAME48k]; +#endif + int16_t ch; + int16_t band; + PARAM_MC_ENC_HANDLE hParamMC; + int16_t nchan_inp; + + push_wmops( "param_mc_enc" ); + + /* initializations */ + hParamMC = st_ivas->hParamMC; + bit_pos = 0; + band_step = 1; + nchan_inp = st_ivas->hEncoderConfig->nchan_inp; + + for ( band = 0; band < PARAM_MC_MAX_PARAMETER_BANDS; band++ ) + { + for ( ch = 0; ch < MAX_CICP_CHANNELS; ch++ ) + { + set_zero( Cy_sum[band][ch], MAX_CICP_CHANNELS ); + } + for ( ch = 0; ch < PARAM_MC_MAX_TRANSPORT_CHANS; ch++ ) + { + set_zero( Cx_sum[band][ch], PARAM_MC_MAX_TRANSPORT_CHANS ); + } + } + + for ( band = 0; band < PARAM_MC_MAX_PARAMETER_BANDS; band++ ) + { + set_zero( ILD_q[band], PARAM_MC_SZ_ILD_MAP ); + } + set_s( ILD_idx, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP ); + set_s( ICC_idx, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ICC_MAP ); + + /* update parameter frame index */ + hParamMC->hMetadataPMC.param_frame_idx = ( hParamMC->hMetadataPMC.param_frame_idx + 1 ) % PARAM_MC_PARAMETER_FRAMES; + + /* DMX generation*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < nchan_inp; i++ ) + { + floatToFixed_arrL( data_f[i], data_f_fx[i], 11, input_frame ); + } +#endif + ivas_param_mc_dmx_fx( hParamMC, data_f_fx, data_dmx_fx, input_frame, nchan_inp, st_ivas->nchan_transport ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < 3; i++ ) + { + fixedToFloat_arrL( data_dmx_fx[i], data_dmx[i], 11, input_frame ); + } +#endif +#else + ivas_param_mc_dmx( hParamMC, data_f, data_dmx, input_frame, nchan_inp, st_ivas->nchan_transport ); +#endif + + /* Transient Detector */ + switch ( st_ivas->nchan_transport ) + { + case 2: + case 3: + case 4: + { + int16_t bAttackPresent[PARAM_MC_MAX_TRANSPORT_CHANS]; + int16_t attackIdx[PARAM_MC_MAX_TRANSPORT_CHANS]; + + set16_fx( attackIdx, -1, PARAM_MC_MAX_TRANSPORT_CHANS ); + set16_fx( bAttackPresent, 0, PARAM_MC_MAX_TRANSPORT_CHANS ); + + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + Word16 cpe_idx = ch / 2; + + RunTransientDetection( data_dmx[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_flt, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg, &st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_e, NSUBBLOCKS + MAX_TD_DELAY ); + f2me_buf( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_flt, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg, &st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_e, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold = float_to_fix16( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold_flt, Q15 - ATTACKTHRESHOLD_E ); +#endif + ivas_param_mc_transient_detection_fx( hParamMC, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet, &bAttackPresent[ch], &attackIdx[ch] ); +#else + ivas_param_mc_transient_detection( hParamMC, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet, &bAttackPresent[ch], &attackIdx[ch] ); +#endif + } + + /* if more than one attack, use the earlier */ + hParamMC->hMetadataPMC.bAttackPresent = 0; + hParamMC->hMetadataPMC.attackIndex = 16; + + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + hParamMC->hMetadataPMC.bAttackPresent = max( hParamMC->hMetadataPMC.bAttackPresent, bAttackPresent[ch] ); + } + + if ( hParamMC->hMetadataPMC.bAttackPresent ) + { + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + hParamMC->hMetadataPMC.attackIndex = min( hParamMC->hMetadataPMC.attackIndex, attackIdx[ch] ); + } + } + else + { + hParamMC->hMetadataPMC.attackIndex = 0; + } + } + break; + } + + /* Encoding */ + /* parameter estimation*/ + ivas_param_mc_param_est_enc( hParamMC, data_f, Cy_sum, Cx_sum, input_frame, nchan_inp, st_ivas->nchan_transport ); + + band_step = hParamMC->hMetadataPMC.bAttackPresent ? PARAM_MC_TRANSIENT_BAND_STEP : 1; + + + /* ILD parameter quantization */ + for ( k = 0; k < hParamMC->hMetadataPMC.nbands_coded; k += band_step ) + { + ivas_param_mc_quantize_ilds( hParamMC, Cy_sum[k], Cx_sum[k], k, nchan_inp, st_ivas->nchan_transport, ILD_idx, ILD_q[k] ); + } + +#ifndef FIX_901_PARAMMC_DEAD_CODE + /* get icc map */ + if ( hParamMC->hMetadataPMC.flag_use_adaptive_icc_map == 1 ) + { + ivas_param_mc_enc_find_icc_map( hParamMC, Cx_sum, Cy_sum, ILD_q, nchan_inp, st_ivas->nchan_transport ); + } + else + { + ivas_param_mc_default_icc_map( hParamMC->hMetadataPMC.icc_mapping_conf, hParamMC->hMetadataPMC.icc_mapping[hParamMC->hMetadataPMC.param_frame_idx] ); + } + +#endif + /* ICC parameter quantization */ + for ( k = 0; k < hParamMC->hMetadataPMC.nbands_coded; k += band_step ) + { + ivas_param_mc_quantize_iccs( hParamMC, Cy_sum[k], k, nchan_inp, ICC_idx ); + } + + /* time domain DMX generation*/ + /* just copy data_dmx generated above, contains already the downmix */ + for ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + mvr2r( data_dmx[ch], data_f[ch], input_frame ); + } + + /* we have to run the transient detector on the second channel of the last CPE if we + have an odd number of transport channels */ + if ( st_ivas->nchan_transport > 2 ) + { + for ( ; ch < st_ivas->nCPE * CPE_CHANNELS; ch++ ) + { + int16_t cpe_idx = ch / 2; + + set_zero( data_f[ch], input_frame ); + + RunTransientDetection( data_f[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); + } + } + + /* write Parametric MC side info bitstream into temporary buffer*/ + ivas_param_mc_write_bs( hParamMC, ILD_idx, ICC_idx, bit_buffer, &bit_pos ); + + /* push the Parametric MC side info from the temporary buffer into the medatdata bitstream*/ + push_next_bits( hMetaData, bit_buffer, bit_pos ); + + /* updates */ + hParamMC->hMetadataPMC.last_coded_bwidth = hParamMC->hMetadataPMC.coded_bwidth; + +#ifdef IVAS_FLOAT_FIXED + for ( k = 0; k < 12; k++ ) + { + free( data_f_fx[k] ); + } +#endif + + pop_wmops(); + + return; +} +#else void ivas_param_mc_enc( Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ BSTR_ENC_HANDLE hMetaData, /* i/o: IVAS Metadata bitstream handle */ @@ -419,6 +654,10 @@ void ivas_param_mc_enc( PARAM_MC_ENC_HANDLE hParamMC; int16_t nchan_inp; +#ifdef IVAS_FLOAT_FIXED + Word16 data_dmx_fx[PARAM_MC_MAX_TRANSPORT_CHANS][L_FRAME48k]; +#endif + push_wmops( "param_mc_enc" ); /* initializations */ @@ -469,8 +708,61 @@ void ivas_param_mc_enc( { int16_t cpe_idx = ch / 2; - RunTransientDetection( data_dmx[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1 = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1_flt, -1 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2 = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2_flt, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg[i] = floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_flt[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg[i] = floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_flt[i], 7 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange[i] = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange_flt[i], 7 ); + } + + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer[i] = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer_flt[i], 7 ); + } + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold_flt, 11 ); + floatToFixed_arr16( data_dmx[ch], data_dmx_fx[ch], -1, input_frame ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.facAccSubblockNrg = float_to_fix16( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.facAccSubblockNrg_flt, 15 ); + +#endif + + RunTransientDetection_ivas_fx( data_dmx_fx[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1_flt = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1, -1 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2_flt = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2, -1 ); + + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_flt[i] = fixedToFloat( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg[i], 7 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange_flt[i] = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_flt[i] = fixedToFloat( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg[i], 7 ); + } + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer_flt[i] = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer[i], -1 ); + } +#endif +#else + RunTransientDetection( data_dmx[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); +#endif ivas_param_mc_transient_detection( hParamMC, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet, &bAttackPresent[ch], &attackIdx[ch] ); } @@ -544,9 +836,68 @@ void ivas_param_mc_enc( { int16_t cpe_idx = ch / 2; - set_zero( data_f[ch], input_frame ); + set_zero( data_f[ch], input_frame ); + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 data_fx[L_FRAME48k]; + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1 = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1_flt, -1 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2 = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2_flt, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg[i] = floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_flt[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg[i] = floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_flt[i], 7 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange[i] = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange_flt[i], 7 ); + } + + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer[i] = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer_flt[i], -1 ); + } + + + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold = (Word16) floatToFixed( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->transientDetector.attackRatioThreshold_flt, 11 ); + + floatToFixed_arr16( data_f[ch], data_fx, -1, input_frame ); + + + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.facAccSubblockNrg = float_to_fix16( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.facAccSubblockNrg_flt, 15 ); + +#endif + + RunTransientDetection_ivas_fx( data_fx, input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1_flt = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState1, -1 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2_flt = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.firState2, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg_flt[i] = fixedToFloat( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrg[i], 7 ); + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange_flt[i] = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.subblockNrgChange[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg_flt[i] = fixedToFloat( st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->subblockEnergies.accSubblockNrg[i], 7 ); + } + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer_flt[i] = fixedToFloat( (Word32) st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet->delayBuffer.buffer[i], -1 ); + } +#endif +#else RunTransientDetection( data_f[ch], input_frame, st_ivas->hCPE[cpe_idx]->hCoreCoder[ch - cpe_idx * CPE_CHANNELS]->hTranDet ); +#endif } } @@ -563,6 +914,7 @@ void ivas_param_mc_enc( return; } +#endif /*****************************************************************************************/ @@ -575,6 +927,7 @@ void ivas_param_mc_enc( * Computes the time domain down mix signal *------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void ivas_param_mc_dmx( PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder handle */ float *data_f[], /* i : Input frame */ @@ -607,6 +960,42 @@ static void ivas_param_mc_dmx( return; } +#else +static void ivas_param_mc_dmx_fx( + PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder handle */ + Word32 *data_f_fx[], /* i : Input frame Q_x */ + Word32 data_dmx_fx[][L_FRAME48k], /* o : Down mixed frame Q_x - 11 */ + const Word16 input_frame, /* i : Input frame length */ + const Word16 nchan_input, /* i : number of input channels */ + const Word16 nchan_transport /* i : number of transport channels */ +) +{ + Word16 i; + const Word16 *idx; + Word16 dmx_ch; + Word16 inp_ch; + const Word32 *p_dmx_fac_fx; + + idx = Param_MC_index; + FOR( i = 0; i < input_frame; i++ ) + { + p_dmx_fac_fx = hParamMC->dmx_factors_fx; + FOR( dmx_ch = 0; dmx_ch < nchan_transport; dmx_ch++ ) + { + Word32 *dmx_sample_fx = &data_dmx_fx[idx[dmx_ch]][i]; + *dmx_sample_fx = 0; + move16(); + FOR( inp_ch = 0; inp_ch < nchan_input; inp_ch++ ) + { + ( *dmx_sample_fx ) = Madd_32_32( ( *dmx_sample_fx ), data_f_fx[idx[inp_ch]][i], ( *( p_dmx_fac_fx++ ) ) ); + move16(); + } + } + } + + return; +} +#endif /*------------------------------------------------------------------------- @@ -1518,6 +1907,7 @@ static void ivas_param_mc_parameter_quantizer( * Detect if the current frame has a transient *------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void ivas_param_mc_transient_detection( PARAM_MC_ENC_HANDLE hParamMC, /* i : Parametric MC encoder handle */ TRAN_DET_HANDLE hTranDet, /* i : Transient detector handle from core coder for a transport channel */ @@ -1566,7 +1956,70 @@ static void ivas_param_mc_transient_detection( return; } +#else +static void ivas_param_mc_transient_detection_fx( + PARAM_MC_ENC_HANDLE hParamMC, /* i : Parametric MC encoder handle */ + TRAN_DET_HANDLE hTranDet, /* i : Transient detector handle from core coder for a transport channel */ + Word16 *pbIsAttackPresent, /* o : Flag for indicating a found transient */ + Word16 *pAttackIndex /* o : Attack position (0 if no attack) */ +) +{ + Word16 i; + Word16 bIsAttackPresent, attackIndex; + Word32 *pSubblockNrg_fx; + Word16 pSubblockNrg_e; + Word32 *pAccSubblockNrg_fx; + Word16 pAccSubblockNrg_e; + Word16 attackRatioThreshold_fx; + + push_wmops( "param_mc_trn_det" ); + + attackRatioThreshold_fx = hTranDet->transientDetector.attackRatioThreshold; + pSubblockNrg_fx = &hTranDet->subblockEnergies.subblockNrg[hParamMC->transient_detector_delay]; + pSubblockNrg_e = hTranDet->subblockEnergies.subblockNrg_e; + move16(); + pAccSubblockNrg_fx = &hTranDet->subblockEnergies.accSubblockNrg[hParamMC->transient_detector_delay]; + pAccSubblockNrg_e = hTranDet->subblockEnergies.accSubblockNrg_e; + move16(); + + bIsAttackPresent = FALSE; + move16(); + attackIndex = 16; + move16(); + + /* Search for the last attack in the subblocks, + * if we had an attack very late in the last frame, + * make the current frame also a transient one... */ + test(); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg_fx[-1], pSubblockNrg_e, Mpy_32_16_1( pAccSubblockNrg_fx[-1], attackRatioThreshold_fx ), add( pAccSubblockNrg_e, ATTACKTHRESHOLD_E ) ), 1 ) || + EQ_16( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg_fx[-2], pSubblockNrg_e, Mpy_32_16_1( pAccSubblockNrg_fx[-2], attackRatioThreshold_fx ), add( pAccSubblockNrg_e, ATTACKTHRESHOLD_E ) ), 1 ) ) + { + bIsAttackPresent = TRUE; + move16(); + attackIndex = 0; + move16(); + } + + FOR( i = 0; i < NSUBBLOCKS; i++ ){ + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg_fx[i], pSubblockNrg_e, Mpy_32_16_1( pAccSubblockNrg_fx[i], attackRatioThreshold_fx ), add( pAccSubblockNrg_e, ATTACKTHRESHOLD_E ) ), 1 ) ){ + bIsAttackPresent = TRUE; + move16(); + attackIndex = i; + move16(); +} +} + +/* avoid post-echos on click sounds (very short transients) due to TNS aliasing */ +*pAttackIndex = attackIndex; +move16(); +*pbIsAttackPresent = bIsAttackPresent; +move16(); +pop_wmops(); + +return; +} +#endif /*------------------------------------------------------------------------- * ivas_param_mc_entropy_encoder() @@ -1574,6 +2027,119 @@ static void ivas_param_mc_transient_detection( * Write the metadata bitstream *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_param_mc_write_bs( + const PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder Handle */ + Word16 *ILD_idx, /* i : ILD quantizer indices sequence */ + Word16 *ICC_idx, /* i : ICC quantizer indices sequence */ + UWord16 bit_buffer[PARAM_MC_MAX_BITS], /* o : Output bit buffer */ + Word16 *bit_pos /* o : Number of bits used */ +) +{ + Word16 i, pos; + Word16 nbands; + Word16 band_step; + /*buffers are not getting used in the function*/ + // Word16 seq_tmp[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP]; + // float seq_tmp_uni[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP]; + Word16 icc_map_size_wo_lfe; + Word16 icc_map_size; + Word16 ild_map_size_wo_lfe; + Word16 ild_map_size; + + push_wmops( "param_mc_prm_enc" ); + + /* Init */ + /*buffers are not getting used in the function */ + // set_zero( seq_tmp_uni, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP ); + // set_s( seq_tmp, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_SZ_ILD_MAP ); + nbands = hParamMC->hMetadataPMC.nbands_in_param_frame[hParamMC->hMetadataPMC.param_frame_idx]; + move16(); + icc_map_size_wo_lfe = hParamMC->hMetadataPMC.icc_mapping_conf->icc_map_size_wo_lfe; + move16(); + icc_map_size = hParamMC->hMetadataPMC.icc_mapping_conf->icc_map_size_lfe; + move16(); + ild_map_size_wo_lfe = hParamMC->hMetadataPMC.ild_mapping_conf->ild_map_size_wo_lfe; + move16(); + ild_map_size = hParamMC->hMetadataPMC.ild_mapping_conf->ild_map_size_lfe; + move16(); + + /*-----------------------------------------------------------------* + * Signaling bits + *-----------------------------------------------------------------*/ + + /* reserved bit */ + bit_buffer[( *bit_pos )++] = hParamMC->hMetadataPMC.lfe_on; + move16(); + + /* write coded band width */ + i = hParamMC->hMetadataPMC.coded_bwidth; + move16(); + FOR( pos = 0; pos < 2; pos++ ) + { + bit_buffer[( *bit_pos )++] = (UWord16) s_and( shr( i, pos ), 1 ); + move16(); + } + + /* write param frame indicator */ + bit_buffer[( *bit_pos )++] = hParamMC->hMetadataPMC.param_frame_idx; + move16(); + + /* write transient frame indicator */ + bit_buffer[( *bit_pos )++] = hParamMC->hMetadataPMC.bAttackPresent; + move16(); + + band_step = 1; + move16(); + IF( hParamMC->hMetadataPMC.bAttackPresent ) + { + band_step = PARAM_MC_TRANSIENT_BAND_STEP; + move16(); + FOR( pos = 2; pos >= 0; --pos ) + { + bit_buffer[( *bit_pos )++] = (UWord16) s_and( shr( hParamMC->hMetadataPMC.attackIndex, pos ), 1 ); + move16(); + } + IF( ( hParamMC->hMetadataPMC.nbands_coded % band_step ) ) + { + nbands = add( idiv1616( hParamMC->hMetadataPMC.nbands_coded, band_step ), 1 ); + } + ELSE + { + nbands = add( idiv1616( hParamMC->hMetadataPMC.nbands_coded, band_step ), 0 ); + } + } + +#ifndef FIX_901_PARAMMC_DEAD_CODE + /* Encoding of the ICC mapping done as simple bitmap */ + if ( hParamMC->hMetadataPMC.flag_use_adaptive_icc_map == 1 ) + { + uint16_t *bit_buffer_icc_mapping = &bit_buffer[*bit_pos]; + + for ( i = 0; i < hParamMC->hMetadataPMC.icc_map_size_full - 1; i++ ) + { + bit_buffer_icc_mapping[i] = 0; + } + + for ( i = 0; i < icc_map_size_wo_lfe; i++ ) + { + bit_buffer_icc_mapping[hParamMC->icc_map_index[hParamMC->hMetadataPMC.param_frame_idx][i]] = 1; + } + + *bit_pos += hParamMC->hMetadataPMC.icc_map_size_full - 1; + } + +#endif + ivas_param_mc_encode_parameter( ICC_idx, &hParamMC->hMetadataPMC, &hParamMC->hMetadataPMC.icc_coding, + nbands, band_step, icc_map_size_wo_lfe, icc_map_size, bit_buffer, bit_pos ); + + ivas_param_mc_encode_parameter( ILD_idx, &hParamMC->hMetadataPMC, &hParamMC->hMetadataPMC.ild_coding, + nbands, band_step, ild_map_size_wo_lfe, ild_map_size, bit_buffer, bit_pos ); + pop_wmops(); + + return; +} +#else static void ivas_param_mc_write_bs( const PARAM_MC_ENC_HANDLE hParamMC, /* i/o: Parametric MC encoder Handle */ int16_t *ILD_idx, /* i : ILD quantizer indices sequence */ @@ -1663,6 +2229,7 @@ static void ivas_param_mc_write_bs( return; } +#endif /*------------------------------------------------------------------------- @@ -1671,6 +2238,148 @@ static void ivas_param_mc_write_bs( * (entropy) encode a sequence of parameter indices *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_param_mc_encode_parameter( + int16_t *quant_idx, /* i : indices sequence to encode */ + HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, /* i : Parametric MC metadata handle */ + HANDLE_PARAM_MC_PARAMETER_CODING_INFO hParameterCodingInfo, /* i : parameter quantization and coding info */ + const Word16 nbands, /* i : number of parameter bands to encode */ + const Word16 band_step, /* i : parameter band step */ + const Word16 map_size_wo_lfe, /* i : number of parameters per band (w/o LFE) */ + const Word16 map_size, /* i : number of parameters per band */ + UWord16 bit_buffer[PARAM_MC_MAX_BITS], /* o : Output bit buffer */ + Word16 *bit_pos /* o : Number of bits used */ +) +{ + Word16 sz_seq; + Word16 idx_prev; + Word16 idx_offset; + Word16 bit_cnt_uni; + Word16 bit_cnt_range; + Word16 bit_cnt_range_diff; + Word16 bit_cnt_range_min; + Word16 bit_pos_tmp; + Word16 i, j; + Word16 idx; + Word16 seq_delta[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + Word16 seq[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + UWord16 tmp_bit_buffer[PARAM_MC_MAX_BITS]; + UWord16 tmp_bit_buffer_diff[PARAM_MC_MAX_BITS]; + + /* Inits */ + sz_seq = i_mult( nbands, ( map_size_wo_lfe ) ); + + /* Computing Delta Sequence */ + idx_prev = sub( add( shr( hParameterCodingInfo->quantizer_size, 1 ), hParameterCodingInfo->quantizer_size % 2 ), 1 ); + idx_offset = sub( hParameterCodingInfo->quantizer_size, 1 ); + + FOR( j = 0; j < map_size_wo_lfe; ++j ) + { + Word16 coding_band = 0; + move16(); + + FOR( i = 0; i < hMetadataPMC->nbands_coded; i += band_step ) + { + test(); + IF( hMetadataPMC->bAttackPresent || EQ_16( hMetadataPMC->param_frame_idx, hMetadataPMC->coding_band_mapping[i] ) ) + { + idx = quant_idx[i * map_size + j]; + move16(); + seq[coding_band + j * nbands] = idx; + move16(); + seq_delta[coding_band + j * nbands] = add( sub( idx, idx_prev ), idx_offset ); + move16(); + idx_prev = idx; + move16(); + coding_band = add( coding_band, 1 ); + } + } + } + + /* LFE */ + IF( hMetadataPMC->lfe_on ) + { + FOR( i = 0; i < PARAM_MC_MAX_BAND_LFE; i += band_step ) + { + test(); + IF( hMetadataPMC->bAttackPresent || EQ_16( hMetadataPMC->param_frame_idx, hMetadataPMC->coding_band_mapping[i] ) ) + { + /* LFE ICC/ILDs are always the last ones in coding band 0 */ + Word16 n_lfe_idx, k; + n_lfe_idx = sub( map_size, map_size_wo_lfe ); + FOR( k = 0; k < n_lfe_idx; k++ ) + { + idx = quant_idx[( i + 1 ) * map_size - n_lfe_idx + k]; + move16(); + seq[sz_seq] = idx; + move16(); + seq_delta[sz_seq] = add( sub( idx, idx_prev ), idx_offset ); + move16(); + idx_prev = idx; + move16(); + sz_seq = add( sz_seq, 1 ); + } + } + } + } + + + bit_cnt_uni = sub( i_mult( sz_seq, hParameterCodingInfo->uni_bits ), 1 ); /* -1 for the additional diff/direct signaling bit for the range encoder*/ + + /* code the direct index sequence */ + ivas_param_mc_range_encoder( seq, sz_seq, hParameterCodingInfo->cum_freq, hParameterCodingInfo->sym_freq, PARAM_MC_RANGE_CODER_TOT_SHIFT, bit_cnt_uni, &tmp_bit_buffer[0], &bit_cnt_range ); + + /* Coding the delta index sequence */ + ivas_param_mc_range_encoder( seq_delta, sz_seq, hParameterCodingInfo->cum_freq_delta, hParameterCodingInfo->sym_freq_delta, PARAM_MC_RANGE_CODER_TOT_SHIFT, bit_cnt_uni, &tmp_bit_buffer_diff[0], &bit_cnt_range_diff ); + + bit_cnt_range_min = s_min( bit_cnt_range, bit_cnt_range_diff ); + + /* uniform fallback */ + IF( GT_16( bit_cnt_range_min, bit_cnt_uni ) ) + { + /* Uniform coding is used */ + bit_buffer[( *bit_pos )++] = 0; + move16(); + bit_pos_tmp = 0; + move16(); + + FOR( i = 0; i < sz_seq; ++i ) + { + ivas_param_mc_dec2bin( seq[i], hParameterCodingInfo->uni_bits, &bit_buffer[*( bit_pos ) + bit_pos_tmp] ); + bit_pos_tmp = add( bit_pos_tmp, hParameterCodingInfo->uni_bits ); + } + *bit_pos = add( *bit_pos, bit_pos_tmp ); + } + ELSE + { + /* Range Coding is used */ + bit_buffer[( *bit_pos )++] = 1; + move16(); + IF( bit_cnt_range_diff < bit_cnt_range ) + { + bit_buffer[( *bit_pos )++] = 1; + move16(); + FOR( i = 0; i < bit_cnt_range_diff; i++ ) + { + bit_buffer[( *bit_pos )++] = tmp_bit_buffer_diff[i]; + move16(); + } + } + ELSE + { + bit_buffer[( *bit_pos )++] = 0; + move16(); + FOR( i = 0; i < bit_cnt_range; i++ ) + { + bit_buffer[( *bit_pos )++] = tmp_bit_buffer[i]; + move16(); + } + } + } + + return; +} +#else static void ivas_param_mc_encode_parameter( int16_t *quant_idx, /* i : indices sequence to encode */ HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, /* i : Parametric MC metadata handle */ @@ -1793,6 +2502,7 @@ static void ivas_param_mc_encode_parameter( return; } +#endif /*------------------------------------------------------------------------- @@ -1801,6 +2511,26 @@ static void ivas_param_mc_encode_parameter( * Decimal to binary routine *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_param_mc_dec2bin( + const Word16 val, /* i : value to encode */ + const Word16 N, /* i : number of bits for encoding the value */ + UWord16 bits[PARAM_MC_MAX_BITS] ) /* o : encoded bits buffer */ +{ + Word16 idx; + + idx = 0; + move16(); + /* convert value to bitstream, MSB first */ + FOR( idx = 0; idx < N; idx++ ) + { + bits[idx] = (UWord16) s_and( shr( val, sub( N, sub( 1, idx ) ) ), 1 ); + move16(); + } + + return; +} +#else static void ivas_param_mc_dec2bin( const int16_t val, /* i : value to encode */ const int16_t N, /* i : number of bits for encoding the value */ @@ -1817,6 +2547,7 @@ static void ivas_param_mc_dec2bin( return; } +#endif /*-------------------------------------------------------------------* @@ -1825,6 +2556,95 @@ static void ivas_param_mc_dec2bin( * Parametric MC Range encoder *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_param_mc_range_encoder( + const Word16 *seq_in, /* i : input sequence */ + const Word16 num_symbols, /* i : Number of symbole to encode */ + const UWord16 *cum_freq, /* i : cumulated frequencies */ + const UWord16 *sym_freq, /* i : symbol frequencies */ + const UWord16 tot_shift, /* i : max cumulative freq as power of 2 */ + const Word16 max_nb_bits, /* i : Maximum number of bits allowed */ + UWord16 *bit_buffer, /* o : output bit buffer */ + Word16 *bit_pos /* o : number of bits used */ +) +{ + RangeUniEncState rc_st_enc; + Word16 rc_tot_bits; /* No. of bits returned by range coder */ + Word16 i; + UWord8 k, byte; + UWord16 *bits; + + /* Initialize range encoder */ + rc_uni_enc_init( &rc_st_enc ); + + /* Main loop over the length of the sequence */ + FOR( i = 0; i < num_symbols; ++i ) + { + rc_uni_enc_encode_symbol_fastS( &rc_st_enc, (UWord16) seq_in[i], cum_freq, sym_freq, tot_shift ); + + IF( GT_16( rc_uni_enc_virtual_finish( &rc_st_enc ), max_nb_bits ) ) + { + /* we alread have exceeded the maximum number of bits allowed, i.e. the uniform fallback */ + *bit_pos = MAX_BITS_PER_FRAME; + return; + } + } + + /* Finish range encoder */ + rc_tot_bits = rc_uni_enc_finish( &rc_st_enc ); /* No. of bits consumed by range coder */ + + /* Push range coded bits from byte_buffer to bitstream */ + + /* 1) Push all complete bytes, one byte at a time */ + FOR( i = 0; i < shr( rc_tot_bits, 3 ); ++i ) + { + /* use rc_st_enc.byte_buffer */ + bits = &bit_buffer[shl( i, 3 )]; + + byte = rc_st_enc.byte_buffer[i]; + move16(); + + bits[0] = (UWord16) s_and( shr( (Word16) byte, 7 ), 1 ); + move16(); + bits[1] = (UWord16) s_and( shr( (Word16) byte, 6 ), 1 ); + move16(); + bits[2] = (UWord16) s_and( shr( (Word16) byte, 5 ), 1 ); + move16(); + bits[3] = (UWord16) s_and( shr( (Word16) byte, 4 ), 1 ); + move16(); + bits[4] = (UWord16) s_and( shr( (Word16) byte, 3 ), 1 ); + move16(); + bits[5] = (UWord16) s_and( shr( (Word16) byte, 2 ), 1 ); + move16(); + bits[6] = (UWord16) s_and( shr( (Word16) byte, 1 ), 1 ); + move16(); + bits[7] = (UWord16) s_and( (Word16) byte, 1 ); + move16(); + } + + /* 2) Push remaining bits */ + IF( s_and( rc_tot_bits, 7 ) != 0 ) + { + UWord8 rem_bits = (UWord8) s_and( rc_tot_bits, 7 ); + + bits = &bit_buffer[shl( i, 3 )]; + byte = rc_st_enc.byte_buffer[i]; + move16(); + + FOR( k = 0; k < rem_bits; k++ ) + { + bits[k] = (UWord16) s_and( shr( (Word16) byte, sub( 7, k ) ), 1 ); + move16(); + } + } + + /* Update output number of bits */ + *bit_pos = rc_tot_bits; + move16(); + + return; +} +#else static void ivas_param_mc_range_encoder( const int16_t *seq_in, /* i : input sequence */ const int16_t num_symbols, /* i : Number of symbole to encode */ @@ -1900,3 +2720,4 @@ static void ivas_param_mc_range_encoder( return; } +#endif diff --git a/lib_enc/ivas_mc_paramupmix_enc.c b/lib_enc/ivas_mc_paramupmix_enc.c index 06c9dde4d4464ddcf5f7345ba92b68b30eea4bbf..c547a60bd175e0dbb2844f18bab4536c7043f516 100644 --- a/lib_enc/ivas_mc_paramupmix_enc.c +++ b/lib_enc/ivas_mc_paramupmix_enc.c @@ -41,6 +41,7 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #include "prot_fx.h" +#include "basop_util.h" #endif #include "ivas_cnst.h" #include "ivas_rom_com.h" @@ -54,10 +55,14 @@ * Local function prototypes *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_mc_paramupmix_dmx_fx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, Word32 *data_f[], const Word16 input_frame ); +#else static void ivas_mc_paramupmix_dmx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, float *data_f[], const int16_t input_frame ); +#endif #ifdef IVAS_FLOAT_FIXED -static ivas_error ivas_mc_paramupmix_param_est_enc( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, float *input_frame_t[], const int16_t input_frame, float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] ); +static ivas_error ivas_mc_paramupmix_param_est_enc_fx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, Word32 *input_frame_t_fx[], Word16 Q_input_frame_t, const Word16 input_frame, Word32 alphas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], Word16 *exp_alphas, Word32 betas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], Word16 *exp_betas ); #else static void ivas_mc_paramupmix_param_est_enc( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, float *input_frame_t[], const int16_t input_frame, float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] ); #endif @@ -80,6 +85,124 @@ static void quantize_pars( const float *v, const int16_t nq, const float *data, * MC ParamUpmix Encoder main encoding function *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_mc_paramupmix_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ + BSTR_ENC_HANDLE hBStr, /* i/o: IVAS Metadata bitstream handle */ + float *data_f[], /* i/o: input/transport MC data */ + Word32 *data_fx[], + const int16_t input_frame /* i : input frame length */ +) +{ + MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix; + int16_t i; + float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; + float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; + uint16_t bit_buffer[MC_PARAMUPMIX_MAX_BITS]; + int16_t bit_pos; + + push_wmops( "mc_paramupmix_enc" ); + + hMCParamUpmix = st_ivas->hMCParamUpmix; + bit_pos = 0; + + /* Parameter estimation */ +#ifdef IVAS_FLOAT_FIXED + Word32 alphas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; + Word32 betas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; + Word16 exp_alphas = 31, exp_betas = 31; + move16(); + move16(); + + ivas_mc_paramupmix_param_est_enc_fx( hMCParamUpmix, data_fx, st_ivas->q_data_fx, input_frame, alphas_fx, &exp_alphas, betas_fx, &exp_betas ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + for ( int ch_idx = 0; ch_idx < hMCParamUpmix->hFbMixer->fb_cfg->num_in_chans; ch_idx++ ) + { + fixedToFloat_arrL( hMCParamUpmix->hFbMixer->ppFilterbank_prior_input_fx[ch_idx], hMCParamUpmix->hFbMixer->ppFilterbank_prior_input[ch_idx], Q14, input_frame / MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + + for ( int b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ ) + { + for ( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) + { + for ( int j = 0; j < MC_PARAMUPMIX_NCH; j++ ) + { + for ( int k = 0; k < hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands; k++ ) + { + hMCParamUpmix->cov_real[b][i][j][k] = me2f( hMCParamUpmix->cov_real_fx[b][i][j][k], sub( Q31, hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[i][j][k] ) ); + hMCParamUpmix->cov_dtx_real[b][i][j][k] = me2f( hMCParamUpmix->cov_dtx_real_fx[b][i][j][k], sub( Q31, hMCParamUpmix->hCovEnc[b]->pCov_dtx_state->q_cov_real_per_band[i][j][k] ) ); + } + } + } + } + + Word16 len = hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands; + if ( len < IVAS_MAX_NUM_BANDS ) + { + len = IVAS_MAX_NUM_BANDS; + } + for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + for ( int j = 0; j < len; j++ ) + { + alphas[i][j] = me2f( alphas_fx[i][j], exp_alphas ); + betas[i][j] = me2f( betas_fx[i][j], exp_betas ); + } + } +#endif +#else + ivas_mc_paramupmix_param_est_enc( hMCParamUpmix, data_f, input_frame, alphas, betas ); +#endif + + for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + put_ec_data( hMCParamUpmix, i, alphas[i], NULL, ALPHA, bit_buffer, &bit_pos ); + put_ec_data( hMCParamUpmix, i, betas[i], alphas[i], BETA, bit_buffer, &bit_pos ); + } + + /* push the PARAM UPMIX MC side info from the temporary buffer into the medatdata bitstream*/ + push_next_bits( hBStr, bit_buffer, bit_pos ); + + /* DMX generation*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 4; i < 12; i++ ) + { + for ( int l = 0; l < input_frame; l++ ) + { + data_fx[i][l] = floatToFixed( data_f[i][l], st_ivas->q_data_fx ); + } + } +#endif + ivas_mc_paramupmix_dmx_fx( hMCParamUpmix, data_fx, input_frame ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + for ( int k = 0; k < MC_PARAMUPMIX_NCH; k++ ) + { + fixedToFloat_arrL( hMCParamUpmix->midside_fx[i][k], hMCParamUpmix->midside[i][k], st_ivas->q_data_fx, input_frame ); + } + } + for ( i = 4; i < 12; i++ ) + { + for ( int l = 0; l < input_frame; l++ ) + { + data_f[i][l] = fixedToFloat( data_fx[i][l], st_ivas->q_data_fx ); + } + } +#endif +#else + ivas_mc_paramupmix_dmx( hMCParamUpmix, data_f, input_frame ); +#endif + pop_wmops(); + + return; +} +#else void ivas_mc_paramupmix_enc( Encoder_Struct *st_ivas, /* i/o: IVAS Encoder handle */ BSTR_ENC_HANDLE hBStr, /* i/o: IVAS Metadata bitstream handle */ @@ -118,6 +241,7 @@ void ivas_mc_paramupmix_enc( return; } +#endif /*------------------------------------------------------------------------- @@ -155,6 +279,14 @@ ivas_error ivas_mc_paramupmix_enc_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MC_MODE_PARAMUPMIX\n" ) ); } set_zero( hMCParamUpmix->midside[i][k], (int16_t) input_frame ); + +#ifdef IVAS_FLOAT_FIXED + if ( ( hMCParamUpmix->midside_fx[i][k] = (Word32 *) malloc( sizeof( Word32 ) * input_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MC_MODE_PARAMUPMIX\n" ) ); + } + set_zero_fx( hMCParamUpmix->midside_fx[i][k], (Word16) input_frame ); +#endif } } hMCParamUpmix->first_frame = 1; @@ -258,6 +390,48 @@ ivas_error ivas_mc_paramupmix_enc_open( } } } +#ifdef IVAS_FLOAT_FIXED + FOR( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ ) + { + IF( ( hMCParamUpmix->cov_real_fx[b] = (Word32 ***) malloc( MC_PARAMUPMIX_NCH * sizeof( Word32 ** ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); + } + FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) + { + IF( ( hMCParamUpmix->cov_real_fx[b][i] = (Word32 **) malloc( MC_PARAMUPMIX_NCH * sizeof( Word32 * ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); + } + FOR( j = 0; j < MC_PARAMUPMIX_NCH; j++ ) + { + IF( ( hMCParamUpmix->cov_real_fx[b][i][j] = (Word32 *) malloc( IVAS_MAX_NUM_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov real matrix" ); + } + } + } + + IF( ( hMCParamUpmix->cov_dtx_real_fx[b] = (Word32 ***) malloc( MC_PARAMUPMIX_NCH * sizeof( Word32 ** ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); + } + FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) + { + IF( ( hMCParamUpmix->cov_dtx_real_fx[b][i] = (Word32 **) malloc( MC_PARAMUPMIX_NCH * sizeof( Word32 * ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); + } + FOR( j = 0; j < MC_PARAMUPMIX_NCH; j++ ) + { + IF( ( hMCParamUpmix->cov_dtx_real_fx[b][i][j] = (Word32 *) malloc( IVAS_MAX_NUM_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR cov dtx real matrix" ); + } + } + } + } +#endif st_ivas->hMCParamUpmix = hMCParamUpmix; @@ -329,6 +503,9 @@ void ivas_mc_paramupmix_enc_close( { for ( k = 0; k < MC_PARAMUPMIX_NCH; k++ ) { +#ifdef IVAS_FLOAT_FIXED + free( ( *hMCParamUpmix )->midside_fx[i][k] ); +#endif free( ( *hMCParamUpmix )->midside[i][k] ); } } @@ -638,6 +815,66 @@ static void put_ec_data( * Computes the time domain down mix signal *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + +static void ivas_mc_paramupmix_dmx_fx( + MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC ParamUpmix encoder handle */ + Word32 *data_fx[], + /* i/o: Input, downmix out */ // st_ivas->q_data_fx + const Word16 input_frame /* i : Input frame length */ +) +{ + Word16 i, l; + const Word16 chan1s[4] = { 4, 5, 8, 9 }; + const Word16 chan2s[4] = { 6, 7, 10, 11 }; + const Word16 chanOut[4] = { 4, 5, 6, 7 }; + const Word16 chanZero[4] = { 8, 9, 10, 11 }; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + /* boxes = { 0 1 2 3 [4 6] [5 7] [8 10] [9 11] }; */ + /* 9+11 -> 7 */ + /* 8+10 -> 6 */ + /* 5+7 -> 5 */ + /* 4+6 -> 4 */ + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + FOR( l = 0; l < input_frame; l++ ) + { + /* mid */ + hMCParamUpmix->midside_fx[i][0][l] = L_shr( L_add( data_fx[chan1s[i]][l], data_fx[chan2s[i]][l] ), 1 ); // st_ivas->q_data_fx + move32(); + /* side */ + hMCParamUpmix->midside_fx[i][1][l] = L_shr( L_sub( data_fx[chan1s[i]][l], data_fx[chan2s[i]][l] ), 1 ); // st_ivas->q_data_fx + move32(); + data_fx[chanOut[i]][l] = hMCParamUpmix->midside_fx[i][0][l]; + move32(); + } + } + + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + set_zero_fx( data_fx[chanZero[i]], input_frame ); + } + + return; +} + +#else static void ivas_mc_paramupmix_dmx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC ParamUpmix encoder handle */ float *data_f[], /* i/o: Input, downmix out */ @@ -675,6 +912,7 @@ static void ivas_mc_paramupmix_dmx( return; } +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * ivas_mc_paramupmix_param_est_enc() @@ -684,12 +922,280 @@ static void ivas_mc_paramupmix_dmx( *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static ivas_error ivas_mc_paramupmix_param_est_enc( +static ivas_error ivas_mc_paramupmix_param_est_enc_fx( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */ - float *data_f[], /* i : Input frame in the time domain */ - const int16_t input_frame, /* i : Input frame length */ - float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], - float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] ) + Word32 *data_f_fx[], + Word16 Q_data_f, + const Word16 input_frame, /* i : Input frame length */ + Word32 alphas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], + Word16 *exp_alphas, + Word32 betas_fx[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], + Word16 *exp_betas ) +{ + + Word32 *pcm_in_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + Word32 FR_Real_Mid_fx[L_FRAME48k], FR_Imag_Mid_fx[L_FRAME48k]; + Word32 fr_realbuffer_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k]; + Word32 fr_imagbuffer_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k]; + Word32 *p_fr_realbuffer_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + Word32 *p_fr_imagbuffer_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + Word32 *cov_real_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; + Word32 *cov_dtx_real_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; + Word16 *q_cov_real[IVAS_SPAR_MAX_CH]; + Word16 *q_cov_dtx_real[IVAS_SPAR_MAX_CH]; + Word32 *pp_in_fr_real_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH], *pp_in_fr_imag_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + Word16 q_ppIn_FR[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + + Word32 rxy_fx, ryy_fx; + Word32 rxx_fx; + Word32 rxxest_fx, drxx_fx; + Word16 exp_drxx; + Word16 wetaux_fx, exp_wetaux; + Word16 cmat_fx, exp_cmat; + + Word16 l_ts; + Word16 b, i, j, ts, bnd; + Word16 maxbands; + Word16 transient_det[MC_PARAMUPMIX_COMBINATIONS][2]; + Word16 transient_det_l[2], transient_det_r[2]; + const Word16 chan1s[MC_PARAMUPMIX_COMBINATIONS] = { 4, 5, 8, 9 }; + const Word16 chan2s[MC_PARAMUPMIX_COMBINATIONS] = { 6, 7, 10, 11 }; + const Word16 HOA_md_ind[IVAS_SPAR_MAX_CH] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + move16(); + move16(); + move16(); + + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + pcm_in_fx[2 * i] = data_f_fx[chan1s[i]]; + pcm_in_fx[2 * i + 1] = data_f_fx[chan2s[i]]; + move16(); + move16(); + + Scale_sig32( pcm_in_fx[2 * i], input_frame, Q14 - Q_data_f ); + Scale_sig32( pcm_in_fx[2 * i + 1], input_frame, Q14 - Q_data_f ); + } + + /*-----------------------------------------------------------------------------------------* + * Transient detector + *-----------------------------------------------------------------------------------------*/ + + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i], pcm_in_fx[2 * i], input_frame, transient_det_l ); + ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in_fx[2 * i + 1], input_frame, transient_det_r ); + transient_det[i][0] = transient_det_l[0] || transient_det_r[0]; + move16(); + transient_det[i][1] = transient_det_l[0] || transient_det_r[0]; + move16(); + /* should probably be transient_det_l[1] || transient_det_r[1] , but choosing 0 reproduces the before merge state */ + } + + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) + { + p_fr_realbuffer_fx[i] = fr_realbuffer_fx[i]; + p_fr_imagbuffer_fx[i] = fr_imagbuffer_fx[i]; + move32(); + move32(); + } + + /* prepare Parameter MDFT analysis */ + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) + { + pp_in_fr_real_fx[i] = p_fr_realbuffer_fx[i]; + pp_in_fr_imag_fx[i] = p_fr_imagbuffer_fx[i]; + move32(); + move32(); + } + + l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + + Word16 gb = find_guarded_bits_fx( l_ts ); + + FOR( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + ivas_fb_mixer_get_windowed_fr_fx( hMCParamUpmix->hFbMixer, pcm_in_fx, pp_in_fr_real_fx, pp_in_fr_imag_fx, l_ts, l_ts, hMCParamUpmix->hFbMixer->fb_cfg->num_in_chans, gb ); + + ivas_fb_mixer_update_prior_input_fx( hMCParamUpmix->hFbMixer, pcm_in_fx, l_ts, hMCParamUpmix->hFbMixer->fb_cfg->num_in_chans ); + + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) + { + pcm_in_fx[i] += l_ts; + pp_in_fr_real_fx[i] += l_ts; + pp_in_fr_imag_fx[i] += l_ts; + } + } + + /*-----------------------------------------------------------------------------------------* + * Covariance process + *-----------------------------------------------------------------------------------------*/ + + FOR( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ ) + { + pp_in_fr_real_fx[0] = p_fr_realbuffer_fx[2 * b]; + pp_in_fr_imag_fx[0] = p_fr_imagbuffer_fx[2 * b]; + pp_in_fr_real_fx[1] = FR_Real_Mid_fx; + pp_in_fr_imag_fx[1] = FR_Imag_Mid_fx; + + v_add_fx( pp_in_fr_real_fx[0], p_fr_realbuffer_fx[2 * b + 1], pp_in_fr_real_fx[1], L_FRAME48k ); + v_add_fx( pp_in_fr_imag_fx[0], p_fr_imagbuffer_fx[2 * b + 1], pp_in_fr_imag_fx[1], L_FRAME48k ); + + FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) + { + FOR( j = 0; j < MC_PARAMUPMIX_NCH; j++ ) + { + cov_real_fx[i][j] = hMCParamUpmix->cov_real_fx[b][i][j]; + move32(); + cov_dtx_real_fx[i][j] = hMCParamUpmix->cov_dtx_real_fx[b][i][j]; + move32(); + } + IF( ( q_cov_real[i] = (Word16 *) malloc( sizeof( Word16 ) * MC_PARAMUPMIX_NCH ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder Fixed" ); + } + set_s( q_cov_real[i], Q31, MC_PARAMUPMIX_NCH ); + IF( ( q_cov_dtx_real[i] = (Word16 *) malloc( sizeof( Word16 ) * MC_PARAMUPMIX_NCH ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder Fixed" ); + } + set_s( q_cov_dtx_real[i], Q31, MC_PARAMUPMIX_NCH ); + } + + set_s( q_ppIn_FR, Q14 - gb, MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH ); + ivas_enc_cov_handler_process_fx( hMCParamUpmix->hCovEnc[b], pp_in_fr_real_fx, pp_in_fr_imag_fx, q_ppIn_FR, cov_real_fx, q_cov_real, cov_dtx_real_fx, q_cov_dtx_real, hMCParamUpmix->hFbMixer->pFb, 0, hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands, MC_PARAMUPMIX_NCH, 0 /*dtx_vad*/, transient_det[b], HOA_md_ind, NULL, NULL, NULL, 0, 0 ); + + FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) + { + free( q_cov_real[i] ); + q_cov_real[i] = NULL; + free( q_cov_dtx_real[i] ); + q_cov_dtx_real[i] = NULL; + } + } + + maxbands = hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands; + Word16 exp_alpha_buff[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] = { { 0 }, { 0 } }; + Word16 exp_beta_buff[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] = { { 0 }, { 0 } }; + move16(); + move16(); + + FOR( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ ) + { + FOR( bnd = 0; bnd < maxbands; bnd++ ) + { + rxy_fx = hMCParamUpmix->cov_real_fx[b][1][0][bnd]; + ryy_fx = hMCParamUpmix->cov_real_fx[b][1][1][bnd]; + + Word16 exp_tmp = 0; + move16(); + Word32 tmp = BASOP_Util_Add_Mant32Exp( ryy_fx, 31 - ( hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[1][1][bnd] ), EPSILON_FX_M, EPSILON_FX_E, &exp_tmp ); + exp_cmat = 0; + move16(); + cmat_fx = BASOP_Util_Divide3232_Scale( rxy_fx, tmp, &exp_cmat ); + exp_cmat = sub( add( exp_cmat, sub( 31, ( hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[1][0][bnd] ) ) ), exp_tmp ); + + Word16 alpha_fx = 0, exp_alpha_var = 0; + move16(); + move16(); + exp_alpha_var = BASOP_Util_Add_MantExp( cmat_fx, exp_cmat + 1, negate( ONE_IN_Q14 ), 1, &alpha_fx ); + + rxx_fx = hMCParamUpmix->cov_real_fx[b][0][0][bnd]; + Word32 tmp_2 = L_mult( cmat_fx, cmat_fx ); // exp_cmat * 2 + rxxest_fx = Mpy_32_32( tmp_2, ryy_fx ); + + exp_drxx = 0; + move16(); + drxx_fx = BASOP_Util_Add_Mant32Exp( rxx_fx, sub( 31, ( hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[0][0][bnd] ) ), L_negate( rxxest_fx ), + add( add( exp_cmat, exp_cmat ), sub( 31, ( hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[1][1][bnd] ) ) ), &exp_drxx ); + drxx_fx = L_max( drxx_fx, 0 ); + + exp_wetaux = 0; + move16(); + wetaux_fx = BASOP_Util_Divide3232_Scale( drxx_fx, tmp, &exp_wetaux ); + exp_wetaux = sub( add( exp_wetaux, exp_drxx ), exp_tmp ); + + Word16 sqrt_wetaux_fx = 0, exp_sqrt_wetaux = 0; + move16(); + move16(); + + IF( wetaux_fx != 0 ) + { + Word16 tmp_4 = 0, exp_tmp4 = 0; + move16(); + move16(); + BASOP_Util_Sqrt_InvSqrt_MantExp( wetaux_fx, exp_wetaux, &sqrt_wetaux_fx, &exp_sqrt_wetaux, &tmp_4, &exp_tmp4 ); + tmp_4 = tmp_4; + exp_tmp4 = exp_tmp4; + move16(); + move16(); + } + ELSE + { + exp_sqrt_wetaux = -1; + move16(); + } + + Word16 exp_betas_var = add( exp_sqrt_wetaux, 1 ); + move16(); + + alphas_fx[b][bnd] = L_deposit_h( alpha_fx ); + move16(); + betas_fx[b][bnd] = L_deposit_h( sqrt_wetaux_fx ); + move16(); + exp_alpha_buff[b][bnd] = exp_alpha_var; + move16(); + exp_beta_buff[b][bnd] = exp_betas_var; + move16(); + } + } + + Word16 max_exp_alpha_buff = 0, max_exp_beta_buff = 0; + move16(); + move16(); + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + FOR( j = 0; j < maxbands; j++ ) + { + max_exp_alpha_buff = s_max( max_exp_alpha_buff, exp_alpha_buff[i][j] ); + max_exp_beta_buff = s_max( max_exp_beta_buff, exp_beta_buff[i][j] ); + } + } + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) + { + FOR( j = 0; j < maxbands; j++ ) + { + alphas_fx[i][j] = L_shr( alphas_fx[i][j], max_exp_alpha_buff - exp_alpha_buff[i][j] ); + move16(); + betas_fx[i][j] = L_shr( betas_fx[i][j], max_exp_beta_buff - exp_beta_buff[i][j] ); + move16(); + } + } + *exp_alphas = max_exp_alpha_buff; + *exp_betas = max_exp_beta_buff; + move16(); + move16(); + + IF( LT_16( maxbands, IVAS_MAX_NUM_BANDS ) ) + { + *exp_alphas = 0; + move16(); + *exp_betas = 0; + move16(); + FOR( b = 0; b < MC_PARAMUPMIX_COMBINATIONS; b++ ) + { + FOR( bnd = maxbands; bnd < IVAS_MAX_NUM_BANDS; bnd++ ) + { + alphas_fx[b][bnd] = 0; + move16(); + betas_fx[b][bnd] = 0; + move16(); + } + } + } + + return IVAS_ERR_OK; +} #else static void ivas_mc_paramupmix_param_est_enc( MC_PARAMUPMIX_ENC_HANDLE hMCParamUpmix, /* i/o: MC Param-Upmix encoder handle */ @@ -697,7 +1203,6 @@ static void ivas_mc_paramupmix_param_est_enc( const int16_t input_frame, /* i : Input frame length */ float alphas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS], float betas[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS] ) -#endif { float *pcm_in[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; float fr_realbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k]; @@ -707,19 +1212,8 @@ static void ivas_mc_paramupmix_param_est_enc( float *p_fr_imagbuffer[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; float *pp_in_fr_real[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; float *pp_in_fr_imag[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; -#ifdef IVAS_FLOAT_FIXED - Word32 *cov_real_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - Word32 *cov_dtx_real_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; - Word16 *q_cov_real[IVAS_SPAR_MAX_CH]; - Word16 *q_cov_dtx_real[IVAS_SPAR_MAX_CH]; - Word32 cov_real_buf_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; - Word32 cov_dtx_real_buf_fx[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH][IVAS_MAX_NUM_BANDS]; - Word32 *pp_in_fr_real_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH], *pp_in_fr_imag_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; - Word16 q_ppIn_FR[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; -#else float *cov_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; float *cov_dtx_real[IVAS_SPAR_MAX_CH][IVAS_SPAR_MAX_CH]; -#endif float rxx, rxy, ryy, cmat, rxxest, drxx, wetaux; int16_t l_ts; int16_t b, i, j, ts, bnd; @@ -739,40 +1233,11 @@ static void ivas_mc_paramupmix_param_est_enc( /*-----------------------------------------------------------------------------------------* * Transient detector *-----------------------------------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED - Word32 *pcm_in_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; - Word32 arr_pcm_in[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k]; - Word32 k; - FOR( j = 0; j < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; j++ ) - { - pcm_in_fx[j] = arr_pcm_in[j]; - FOR( k = 0; k < input_frame; k++ ) - { - pcm_in_fx[j][k] = (Word32) ( pcm_in[j][k] * ( 1 << Q14 ) ); - } - } -#endif for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) { -#ifndef IVAS_FLOAT_FIXED ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i], pcm_in[2 * i], input_frame, transient_det_l ); ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in[2 * i + 1], input_frame, transient_det_r ); -#else - ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i], pcm_in_fx[2 * i], input_frame, transient_det_l ); -#ifdef DEBUGGING - float a[2]; - a[0] = transient_det_l[0]; - a[1] = transient_det_l[1]; - dbgwrite_txt( a, 2, "fixed.txt", NULL ); -#endif - ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in_fx[2 * i + 1], input_frame, transient_det_r ); -#ifdef DEBUGGING - a[0] = transient_det_r[0]; - a[1] = transient_det_r[1]; - dbgwrite_txt( a, 2, "fixed.txt", NULL ); -#endif -#endif transient_det[i][0] = transient_det_l[0] || transient_det_r[0]; transient_det[i][1] = transient_det_l[0] || transient_det_r[0]; /* should probably be transient_det_l[1] || transient_det_r[1] , but choosing 0 reproduces the before merge state */ @@ -824,89 +1289,12 @@ static void ivas_mc_paramupmix_param_est_enc( { for ( j = 0; j < MC_PARAMUPMIX_NCH; j++ ) { -#ifdef IVAS_FLOAT_FIXED - cov_real_fx[i][j] = cov_real_buf_fx[i][j]; - cov_dtx_real_fx[i][j] = cov_dtx_real_buf_fx[i][j]; -#else cov_real[i][j] = hMCParamUpmix->cov_real[b][i][j]; cov_dtx_real[i][j] = hMCParamUpmix->cov_dtx_real[b][i][j]; -#endif - } -#ifdef IVAS_FLOAT_FIXED - IF( ( q_cov_real[i] = (Word16 *) malloc( sizeof( Word16 ) * MC_PARAMUPMIX_NCH ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder Fixed" ); - } - set_s( q_cov_real[i], Q31, MC_PARAMUPMIX_NCH ); - IF( ( q_cov_dtx_real[i] = (Word16 *) malloc( sizeof( Word16 ) * MC_PARAMUPMIX_NCH ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR COV encoder Fixed" ); - } - set_s( q_cov_dtx_real[i], Q31, MC_PARAMUPMIX_NCH ); -#endif - } - -#ifdef IVAS_FLOAT_FIXED - FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) - { - IF( ( pp_in_fr_real_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * input_frame ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR encoder Fixed" ); } - set_zero_fx( pp_in_fr_real_fx[i], input_frame ); - IF( ( pp_in_fr_imag_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * input_frame ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR encoder Fixed" ); - } - set_zero_fx( pp_in_fr_imag_fx[i], input_frame ); - } - set_s( q_ppIn_FR, Q31, MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH ); - -#ifdef MSAN_FIX - FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) -#else - FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) -#endif - { - q_ppIn_FR[i] = L_get_q_buf1( pp_in_fr_real[i], input_frame ); - q_ppIn_FR[i] = min( q_ppIn_FR[i], L_get_q_buf1( pp_in_fr_imag[i], input_frame ) ); - floatToFixed_arrL( pp_in_fr_real[i], pp_in_fr_real_fx[i], q_ppIn_FR[i], input_frame ); - floatToFixed_arrL( pp_in_fr_imag[i], pp_in_fr_imag_fx[i], q_ppIn_FR[i], input_frame ); } -#endif -#ifdef IVAS_FLOAT_FIXED - ivas_enc_cov_handler_process_fx( hMCParamUpmix->hCovEnc[b], pp_in_fr_real_fx, pp_in_fr_imag_fx, q_ppIn_FR, cov_real_fx, q_cov_real, cov_dtx_real_fx, q_cov_dtx_real, hMCParamUpmix->hFbMixer->pFb, 0, hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands, MC_PARAMUPMIX_NCH, 0 /*dtx_vad*/, transient_det[b], HOA_md_ind, NULL, NULL, NULL, 0, 0 ); -#else ivas_enc_cov_handler_process( hMCParamUpmix->hCovEnc[b], pp_in_fr_real, pp_in_fr_imag, cov_real, cov_dtx_real, hMCParamUpmix->hFbMixer->pFb, 0, hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands, MC_PARAMUPMIX_NCH, 0 /*dtx_vad*/, transient_det[b], HOA_md_ind, NULL, NULL, NULL, 0, 0 ); -#endif - -#ifdef IVAS_FLOAT_FIXED - FOR( i = 0; i < MC_PARAMUPMIX_NCH; i++ ) - { - FOR( j = 0; j < MC_PARAMUPMIX_NCH; j++ ) - { - FOR( k = 0; k < hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands; k++ ) - { - hMCParamUpmix->cov_real[b][i][j][k] = me2f( cov_real_fx[i][j][k], sub( Q31, hMCParamUpmix->hCovEnc[b]->pCov_state->q_cov_real_per_band[i][j][k] ) ); - hMCParamUpmix->cov_dtx_real[b][i][j][k] = me2f( cov_dtx_real_fx[i][j][k], sub( Q31, hMCParamUpmix->hCovEnc[b]->pCov_dtx_state->q_cov_real_per_band[i][j][k] ) ); - } - } - free( q_cov_real[i] ); - q_cov_real[i] = NULL; - free( q_cov_dtx_real[i] ); - q_cov_dtx_real[i] = NULL; - } - // Note: No need to convert pp_in_fr_real_fx and pp_in_fr_imag_fx back to float as they are not used after ivas_mc_paramupmix_param_est_enc() - - FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH; i++ ) - { - free( pp_in_fr_real_fx[i] ); - pp_in_fr_real_fx[i] = NULL; - free( pp_in_fr_imag_fx[i] ); - pp_in_fr_imag_fx[i] = NULL; - } -#endif } maxbands = hMCParamUpmix->hFbMixer->pFb->filterbank_num_bands; @@ -940,9 +1328,6 @@ static void ivas_mc_paramupmix_param_est_enc( } } -#ifdef IVAS_FLOAT_FIXED - return IVAS_ERR_OK; -#else return; -#endif } +#endif diff --git a/lib_enc/ivas_mcmasa_enc.c b/lib_enc/ivas_mcmasa_enc.c index 3a49e4aae9573acc0c63caa782918fa80a519610..00f8197c451e41dd248a0fc08c90842883842aa4 100644 --- a/lib_enc/ivas_mcmasa_enc.c +++ b/lib_enc/ivas_mcmasa_enc.c @@ -41,6 +41,9 @@ #include "prot.h" #include "prot_fx.h" #include "ivas_rom_com.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_rom_com_fx.h" +#endif #include "ivas_rom_enc.h" #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED @@ -54,13 +57,17 @@ #define NEAR_HORIZONTAL_PLANE_ELEVATION 17.5f #define VERTICAL_ENERGY_RATIO_OFFSET 0.15f - +#ifdef IVAS_FLOAT_FIXED +#define NEAR_HORIZONTAL_PLANE_ELEVATION_FX 73400320 /*Q22*/ +#define VERTICAL_ENERGY_RATIO_OFFSET_FX 4915 /*Q15*/ +#endif /*------------------------------------------------------------------------- * Local function prototypes *------------------------------------------------------------------------*/ /* Structure for covariance matrix */ +#ifndef IVAS_FLOAT_FIXED typedef struct { float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; @@ -78,63 +85,142 @@ static void computeVerticalDiffuseness( float **buffer_intensity, const float *b static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, const int16_t numChannels ); static void computeLfeEnergy( MCMASA_ENC_HANDLE hMcMasa, float *data_f[], const int16_t input_frame ); +#else +typedef struct +{ + Word32 xr_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word32 xi_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word16 xr_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xr_fx*/ + Word16 xi_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; /*Stores exponent for xi_fx*/ +} CovarianceMatrix; + +static void ivas_mcmasa_dmx_fx( + MCMASA_ENC_HANDLE hMcMasa, + Word32 *data_fx[], + Word16 data_e, + const Word16 input_frame, + const Word16 nchan_transport, + const Word16 nchan_inp ); + +static void compute_cov_mtx_fx( + Word32 sr[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Input matrix, real, s[ch][freq] */ + Word32 si[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Input matrix, imag, s[ch][freq] */ + const Word16 freq, /* i : Freq to process */ + const Word16 N, /* i : Number of channels */ + CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ + Word16 inp_exp /*Stores exponent for temp*/ +); +static void computeIntensityVector_enc_fx( const Word16 *band_grouping, Word32 Cldfb_RealBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX], Word32 Cldfb_ImagBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX], const Word16 enc_param_start_band, const Word16 num_frequency_bands, Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ); + +static void computeVerticalDiffuseness_fx( + Word32 **buffer_intensity, /* i : Intensity vectors */ + const Word32 *buffer_energy, /* i : Energy */ + const Word16 averaging_length, /* i : Averaging length */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + Word32 *diffuseness, /* o : Estimated diffuseness */ + Word16 *buffer_intensity_q, + Word16 *buffer_energy_q ); + +static void computeEvenLayout_fx( + const Word32 *ls_azimuth, + Word32 *ls_azimuth_even, + const Word16 numChannels ); + +static void computeLfeEnergy_fx( MCMASA_ENC_HANDLE hMcMasa, Word32 *data_fx[], const Word16 input_frame, Word16 q_fac ); + +static Word16 ivas_getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ + const Word32 *x, /* i: array containing 32-bit data */ + const Word16 len_x ) /* i: length of the array to scan */ +{ + Word16 i, i_min, i_max; + Word32 x_min, x_max; + + + x_max = 0; + move32(); + x_min = 0; + move32(); + FOR( i = 0; i < len_x; i++ ) + { + IF( x[i] >= 0 ) + x_max = L_max( x_max, x[i] ); + IF( x[i] < 0 ) + x_min = L_min( x_min, x[i] ); + } + + i_max = 0x1f; + move16(); + i_min = 0x1f; + move16(); + + IF( x_max != 0 ) + i_max = norm_l( x_max ); + + IF( x_min != 0 ) + i_min = norm_l( x_min ); + i = s_and( s_min( i_max, i_min ), 0x1F ); + + + return i; +} +#endif +#ifdef IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* * ivas_mcmasa_enc_open() * * *--------------------------------------------------------------------------*/ -ivas_error ivas_mcmasa_enc_open( +ivas_error ivas_mcmasa_enc_open_fx( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ) { - int16_t i, j; - float tmp_f; + Word16 i, j; + Word16 tmp_f; MCMASA_ENC_HANDLE hMcMasa; MASA_ENCODER_HANDLE hMasa; - float ls_azimuth[MCMASA_MAX_ANA_CHANS]; - float ls_elevation[MCMASA_MAX_ANA_CHANS]; - float ls_azimuth_even[MCMASA_MAX_ANA_CHANS]; - int16_t numAnalysisChannels; - float left_min, right_min, azi_diff; - const int16_t *band_mapping; - int16_t maxBin, input_frame; - int16_t nchan_inp; - int32_t input_Fs; - int32_t dirac_slot_ns; + Word32 ls_azimuth[MCMASA_MAX_ANA_CHANS]; + Word32 ls_elevation[MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_even[MCMASA_MAX_ANA_CHANS]; + Word16 numAnalysisChannels; + Word32 left_min, right_min, azi_diff; + const Word16 *band_mapping; + Word16 maxBin, input_frame; + Word16 nchan_inp; + Word32 input_Fs; + Word32 dirac_slot_ns; IVAS_FB_CFG *fb_cfg, *fb_cfgLfe; ivas_error error; error = IVAS_ERR_OK; + move32(); assert( st_ivas->hMasa != NULL && "MASA encoder handle is not present" ); hMasa = st_ivas->hMasa; - if ( ( hMcMasa = (MCMASA_ENC_HANDLE) malloc( sizeof( MCMASA_ENC_DATA ) ) ) == NULL ) + IF( ( hMcMasa = (MCMASA_ENC_HANDLE) malloc( sizeof( MCMASA_ENC_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } nchan_inp = st_ivas->hEncoderConfig->nchan_inp; + move16(); input_Fs = st_ivas->hEncoderConfig->input_Fs; + move32(); /* Determine if to separate some channels from the analysis */ -#ifndef IVAS_FLOAT_FIXED - ivas_mcmasa_set_separate_channel_mode( &( hMcMasa->separateChannelEnabled ), &( hMcMasa->separateChannelIndex ), st_ivas->hEncoderConfig->ivas_total_brate ); -#else ivas_mcmasa_set_separate_channel_mode_fx( &( hMcMasa->separateChannelEnabled ), &( hMcMasa->separateChannelIndex ), st_ivas->hEncoderConfig->ivas_total_brate ); -#endif - numAnalysisChannels = nchan_inp - 1; - if ( hMcMasa->separateChannelEnabled ) + numAnalysisChannels = sub( nchan_inp, 1 ); + IF( hMcMasa->separateChannelEnabled ) { - numAnalysisChannels = nchan_inp - 2; + numAnalysisChannels = sub( nchan_inp, 2 ); } /* With McMASA, we config MASA encoder only in init as we know the input and there are no frame-by-frame changes currently. */ - if ( ( error = ivas_masa_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_masa_enc_config( st_ivas ) ), IVAS_ERR_OK ) ) { return error; } @@ -142,95 +228,116 @@ ivas_error ivas_mcmasa_enc_open( /* Determine the number of bands */ hMcMasa->nbands = st_ivas->hMasa->config.numCodingBands; + move16(); hMcMasa->nCodingBands = st_ivas->hMasa->config.numCodingBands; + move16(); /* Determine band grouping */ - if ( hMcMasa->nbands == 24 ) + IF( EQ_16( hMcMasa->nbands, 24 ) ) { - for ( i = 0; i < hMcMasa->nbands + 1; i++ ) + FOR( i = 0; i < hMcMasa->nbands + 1; i++ ) { - hMcMasa->band_grouping[i] = MASA_band_grouping_24[i] * CLDFB_TO_MDFT_FAC; + hMcMasa->band_grouping[i] = i_mult( MASA_band_grouping_24[i], CLDFB_TO_MDFT_FAC ); + move16(); } } - else + ELSE { band_mapping = hMasa->data.band_mapping; - for ( i = 0; i < hMcMasa->nbands + 1; i++ ) + FOR( i = 0; i < hMcMasa->nbands + 1; i++ ) { - hMcMasa->band_grouping[i] = MASA_band_grouping_24[band_mapping[i]] * CLDFB_TO_MDFT_FAC; + hMcMasa->band_grouping[i] = i_mult( MASA_band_grouping_24[band_mapping[i]], CLDFB_TO_MDFT_FAC ); + move16(); } } - maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH * CLDFB_TO_MDFT_FAC + 0.5f ); + maxBin = extract_l( W_extract_h( W_add( W_mult_32_32( input_Fs, INV_CLDFB_BANDWIDTH_MDFT_FAC_Q31 ), ONE_IN_Q31 /*0.5f in Q32*/ ) ) ); // Q0 - for ( i = 1; i < hMcMasa->nbands + 1; i++ ) + FOR( i = 1; i < hMcMasa->nbands + 1; i++ ) { - if ( hMcMasa->band_grouping[i] >= maxBin ) + IF( GE_32( hMcMasa->band_grouping[i], maxBin ) ) { hMcMasa->band_grouping[i] = maxBin; + move16(); hMcMasa->nbands = i; - break; + move16(); + BREAK; } } /* initialize delay compensation */ hMcMasa->num_samples_delay_comp = NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS ); + move16(); #ifdef DISABLE_DIRAC_DELAY_COMP hMcMasa->num_samples_delay_comp = 0; /* disable delay compensation by setting to 0 */ #endif - tmp_f = (float) hMcMasa->num_samples_delay_comp / (float) ( NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ) ); - hMcMasa->num_slots_delay_comp = (int16_t) ( tmp_f ); + tmp_f = idiv1616( hMcMasa->num_samples_delay_comp, ( NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ) ) ); + hMcMasa->num_slots_delay_comp = tmp_f; + move16(); - if ( tmp_f > (float) hMcMasa->num_slots_delay_comp ) + IF( GT_16( hMcMasa->num_samples_delay_comp, ( NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ) ) ) ) { - hMcMasa->num_slots_delay_comp++; - hMcMasa->offset_comp = -hMcMasa->num_samples_delay_comp; - hMcMasa->num_samples_delay_comp = hMcMasa->num_slots_delay_comp * NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ); - hMcMasa->offset_comp += hMcMasa->num_samples_delay_comp; + hMcMasa->num_slots_delay_comp = add( hMcMasa->num_slots_delay_comp, 1 ); + move16(); + hMcMasa->offset_comp = negate( hMcMasa->num_samples_delay_comp ); + move16(); + hMcMasa->num_samples_delay_comp = i_mult( hMcMasa->num_slots_delay_comp, NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ) ); + move16(); + hMcMasa->offset_comp = add( hMcMasa->offset_comp, hMcMasa->num_samples_delay_comp ); + move16(); } - else + ELSE { hMcMasa->offset_comp = 0; + move16(); } /* set FB config. */ - if ( ( error = ivas_fb_set_cfg( &fb_cfg, MASA_FORMAT, numAnalysisChannels, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_fb_set_cfg( &fb_cfg, MASA_FORMAT, numAnalysisChannels, 0, 0, input_Fs, 0 ) ), IVAS_ERR_OK ) ) { return error; } /* Allocate and initialize FB mixer handle */ - if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + /* Allocate and initialize FB mixer handle */ + IF( NE_32( ( error = ivas_FB_mixer_open_fx( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg, 0 ) ), IVAS_ERR_OK ) ) { return error; } - - if ( hMcMasa->separateChannelEnabled ) + IF( hMcMasa->separateChannelEnabled ) { /* TD Energy calculation with LP */ - if ( ( hMcMasa->delay_buffer_lfe[0] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->delay_buffer_lfe[0] = (Word32 *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->delay_buffer_lfe[0], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); + set_zero_fx( hMcMasa->delay_buffer_lfe[0], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); - if ( ( hMcMasa->delay_buffer_lfe[1] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->delay_buffer_lfe[1] = (Word32 *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->delay_buffer_lfe[1], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); + set_zero_fx( hMcMasa->delay_buffer_lfe[1], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); hMcMasa->hFbMixerLfe = NULL; } - else + ELSE { /* Allocate and initialize FB mixer handle for LFE channel */ - if ( ( error = ivas_fb_set_cfg( &fb_cfgLfe, MASA_FORMAT, 1, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_fb_set_cfg( &fb_cfgLfe, MASA_FORMAT, 1, 0, 0, input_Fs, 0 ) ), IVAS_ERR_OK ) ) { return error; } - if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe, 0 ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = ivas_FB_mixer_open_fx( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe, 0 ) ), IVAS_ERR_OK ) ) { return error; } @@ -239,249 +346,789 @@ ivas_error ivas_mcmasa_enc_open( hMcMasa->delay_buffer_lfe[1] = NULL; } - if ( hMcMasa->separateChannelEnabled ) + IF( hMcMasa->separateChannelEnabled ) { - int16_t bufferSize; + Word16 bufferSize; /* Ring buffer for the filterbank of the LFE analysis. * The filterbank is using moving average lowpass filter with the crossover of 120 Hz. */ - bufferSize = (int16_t) ( ( input_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); - for ( i = 0; i < 2; i++ ) + bufferSize = (Word16) ( ( input_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); + FOR( i = 0; i < 2; i++ ) { - if ( ( hMcMasa->lfeAnaRingBuffer[i] = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->lfeAnaRingBuffer[i] = (Word32 *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->lfeAnaRingBuffer[i], bufferSize ); - hMcMasa->lowpassSum[i] = 0.0f; + set_zero_fx( hMcMasa->lfeAnaRingBuffer[i], bufferSize ); + hMcMasa->lowpassSum[i] = 0; + move32(); } hMcMasa->ringBufferPointer = 0; + move16(); hMcMasa->ringBufferSize = bufferSize; + move16(); } dirac_slot_ns = DIRAC_SLOT_ENC_NS; + move32(); /* intensity 3-dim */ - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL ) + IF( ( hMcMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( hMcMasa->nbands * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } } } - hMcMasa->no_col_avg_diff = (int8_t) ( DIRAC_NO_COL_AVG_DIFF_NS / dirac_slot_ns ); - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - if ( ( hMcMasa->buffer_intensity_real[i] = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + IF( ( hMcMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { - if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->direction_vector_e[i][j] = (Word16 *) malloc( hMcMasa->nbands * sizeof( Word16 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->buffer_intensity_real[i][j], hMcMasa->nbands ); } } - if ( ( hMcMasa->buffer_intensity_real_vert = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + hMcMasa->no_col_avg_diff = (Word8) ( DIRAC_NO_COL_AVG_DIFF_NS / dirac_slot_ns ); + move16(); + + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + IF( ( hMcMasa->buffer_intensity_real_fx[i] = (Word32 **) malloc( hMcMasa->no_col_avg_diff * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + FOR( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + { + IF( ( hMcMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( hMcMasa->nbands * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero_fx( hMcMasa->buffer_intensity_real_fx[i][j], hMcMasa->nbands ); + } + } + set16_fx( hMcMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF ); + + IF( ( hMcMasa->buffer_intensity_real_vert_fx = (Word32 **) malloc( hMcMasa->no_col_avg_diff * sizeof( Word32 * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + FOR( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) { - if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->buffer_intensity_real_vert_fx[j] = (Word32 *) malloc( hMcMasa->nbands * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->buffer_intensity_real_vert[j], hMcMasa->nbands ); + set_zero_fx( hMcMasa->buffer_intensity_real_vert_fx[j], hMcMasa->nbands ); } - if ( ( hMcMasa->buffer_energy = (float *) malloc( hMcMasa->nbands * hMcMasa->no_col_avg_diff * sizeof( float ) ) ) == NULL ) + IF( ( hMcMasa->buffer_energy_fx = (Word32 *) malloc( hMcMasa->nbands * hMcMasa->no_col_avg_diff * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); } - set_zero( hMcMasa->buffer_energy, hMcMasa->nbands * hMcMasa->no_col_avg_diff ); + set_zero_fx( hMcMasa->buffer_energy_fx, hMcMasa->nbands * hMcMasa->no_col_avg_diff ); + set16_fx( hMcMasa->buffer_intensity_real_vert_q, 31, DIRAC_NO_COL_AVG_DIFF ); + set16_fx( hMcMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF ); - if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1 ) + IF( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1 ) { - mvr2r( ls_azimuth_CICP6, ls_azimuth, nchan_inp - 1 ); - mvr2r( ls_elevation_CICP6, ls_elevation, nchan_inp - 1 ); + Copy32( ls_azimuth_CICP6_fx, ls_azimuth, nchan_inp - 1 ); + Copy32( ls_elevation_CICP6_fx, ls_elevation, nchan_inp - 1 ); hMcMasa->numHorizontalChannels = 5; + move16(); hMcMasa->isHorizontalSetup = 1; + move16(); } - else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_7_1 ) + ELSE IF( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_7_1 ) { - mvr2r( ls_azimuth_CICP12, ls_azimuth, nchan_inp - 1 ); - mvr2r( ls_elevation_CICP12, ls_elevation, nchan_inp - 1 ); + Copy32( ls_azimuth_CICP12_fx, ls_azimuth, nchan_inp - 1 ); + Copy32( ls_elevation_CICP12_fx, ls_elevation, nchan_inp - 1 ); hMcMasa->numHorizontalChannels = 7; + move16(); hMcMasa->isHorizontalSetup = 1; + move16(); } - else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_2 ) + ELSE IF( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_2 ) { - mvr2r( ls_azimuth_CICP14, ls_azimuth, nchan_inp - 1 ); - mvr2r( ls_elevation_CICP14, ls_elevation, nchan_inp - 1 ); + Copy32( ls_azimuth_CICP14_fx, ls_azimuth, nchan_inp - 1 ); + Copy32( ls_elevation_CICP14_fx, ls_elevation, nchan_inp - 1 ); hMcMasa->numHorizontalChannels = 5; + move16(); hMcMasa->isHorizontalSetup = 0; + move16(); } - else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_4 ) + ELSE IF( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_4 ) { - mvr2r( ls_azimuth_CICP16, ls_azimuth, nchan_inp - 1 ); - mvr2r( ls_elevation_CICP16, ls_elevation, nchan_inp - 1 ); + Copy32( ls_azimuth_CICP16_fx, ls_azimuth, nchan_inp - 1 ); + Copy32( ls_elevation_CICP16_fx, ls_elevation, nchan_inp - 1 ); hMcMasa->numHorizontalChannels = 5; + move16(); hMcMasa->isHorizontalSetup = 0; + move16(); } - else + ELSE { - mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 ); - mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 ); + Copy32( ls_azimuth_CICP19_fx, ls_azimuth, nchan_inp - 1 ); + Copy32( ls_elevation_CICP19_fx, ls_elevation, nchan_inp - 1 ); hMcMasa->numHorizontalChannels = 7; + move16(); hMcMasa->isHorizontalSetup = 0; + move16(); } - if ( hMcMasa->separateChannelEnabled ) + IF( hMcMasa->separateChannelEnabled ) { - mvr2r( &ls_azimuth[hMcMasa->separateChannelIndex + 1], &ls_azimuth[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); - mvr2r( &ls_elevation[hMcMasa->separateChannelIndex + 1], &ls_elevation[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); - hMcMasa->numHorizontalChannels--; + Copy32( &ls_azimuth[hMcMasa->separateChannelIndex + 1], &ls_azimuth[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); + Copy32( &ls_elevation[hMcMasa->separateChannelIndex + 1], &ls_elevation[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); + hMcMasa->numHorizontalChannels = sub( hMcMasa->numHorizontalChannels, 1 ); + move16(); } - computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels ); - if ( !hMcMasa->isHorizontalSetup ) + computeEvenLayout_fx( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels ); + IF( !hMcMasa->isHorizontalSetup ) { - computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels ); + computeEvenLayout_fx( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels ); } - for ( i = 0; i < numAnalysisChannels; i++ ) + FOR( i = 0; i < numAnalysisChannels; i++ ) { - hMcMasa->chnlToFoaMtx[0][i] = 1.0f; - hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 ); - hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 ); - hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 ); + hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; + move32(); + hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation[i], 91 ), 7 ) ) ) ); + move32(); + hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation[i], 91 ), 7 ) ) ), 16 ); + move32(); + hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation[i], 91 ), 7 ) ) ) ); + move32(); - hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f; - hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 ); - hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f; - hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 ); + hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; + move32(); + hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even[i], 91 ), 7 ) ) ), 16 ); + move32(); + hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; + move32(); + hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even[i], 91 ), 7 ) ) ), 16 ); + move32(); } hMcMasa->combineRatios = hMasa->config.mergeRatiosOverSubframes; + move16(); - mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels ); + Copy32( ls_azimuth, hMcMasa->ls_azimuth_fx, numAnalysisChannels ); - for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) + FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) { - left_min = 360.0f; - right_min = -360.0f; + left_min = L_shl( 360, 22 ); + right_min = L_negate( L_shl( 360, 22 ) ); - for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ ) + FOR( j = 0; j < hMcMasa->numHorizontalChannels; j++ ) { - azi_diff = ls_azimuth[j] - ls_azimuth[i]; + azi_diff = L_sub( ls_azimuth[j], ls_azimuth[i] ); - if ( azi_diff > 180.0f ) + IF( GT_32( azi_diff, ( 180 << 22 ) ) ) { - azi_diff -= 360.0f; + azi_diff = L_sub( azi_diff, 360 << 22 ); } - else if ( azi_diff < -180.0f ) + ELSE IF( LT_32( azi_diff, -( 180 << 22 ) ) ) { - azi_diff += 360.0f; + azi_diff = L_add( azi_diff, 360 << 22 ); } - - if ( azi_diff < left_min && azi_diff > 0.0f ) + test(); + IF( LT_32( azi_diff, left_min ) && GT_32( azi_diff, 0 ) ) { hMcMasa->leftNearest[i] = j; + move16(); left_min = azi_diff; + move32(); } - - if ( azi_diff > right_min && azi_diff < 0.0f ) + test(); + IF( GT_32( azi_diff, right_min ) && LT_32( azi_diff, 0 ) ) { hMcMasa->rightNearest[i] = j; + move16(); right_min = azi_diff; + move32(); } } } - hMcMasa->prevMultiChEne = 0.0f; - hMcMasa->prevDownmixEne = 0.0f; - hMcMasa->prevEQ = 1.0f; - input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); - for ( i = 0; i < input_frame; i++ ) + hMcMasa->prevMultiChEne_fx = 0; + move32(); + hMcMasa->prevDownmixEne_fx = 0; + move32(); + hMcMasa->prevMultiChEne_e = 0; + move16(); + hMcMasa->prevDownmixEne_e = 0; + move16(); + hMcMasa->prevEQ_e = 1; + move16(); + hMcMasa->prevEQ_fx = 1073741824; + move32(); + input_frame = (Word16) Mpy_32_32( input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ); + FOR( i = 0; i < input_frame; i++ ) { - hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame ); + hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); + move16(); } mvs2s( DirAC_block_grouping_5ms_MDFT, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); hMcMasa->index_buffer_intensity = 0; - + move16(); st_ivas->hMcMasa = hMcMasa; return error; } - - -/*------------------------------------------------------------------------- - * ivas_mcmasa_enc_reconfig() - * - * Reconfigure McMASA encoder - *------------------------------------------------------------------------*/ - -ivas_error ivas_mcmasa_enc_reconfig( - Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +#else +ivas_error ivas_mcmasa_enc_open( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ) { - int32_t ivas_total_brate; + int16_t i, j; + float tmp_f; + MCMASA_ENC_HANDLE hMcMasa; + MASA_ENCODER_HANDLE hMasa; + float ls_azimuth[MCMASA_MAX_ANA_CHANS]; + float ls_elevation[MCMASA_MAX_ANA_CHANS]; + float ls_azimuth_even[MCMASA_MAX_ANA_CHANS]; + int16_t numAnalysisChannels; + float left_min, right_min, azi_diff; + const int16_t *band_mapping; + int16_t maxBin, input_frame; + int16_t nchan_inp; + int32_t input_Fs; + int32_t dirac_slot_ns; + IVAS_FB_CFG *fb_cfg, *fb_cfgLfe; ivas_error error; error = IVAS_ERR_OK; - ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + assert( st_ivas->hMasa != NULL && "MASA encoder handle is not present" ); + hMasa = st_ivas->hMasa; - if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) + if ( ( hMcMasa = (MCMASA_ENC_HANDLE) malloc( sizeof( MCMASA_ENC_DATA ) ) ) == NULL ) { - /* bitrate changed, may need to do something */ + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } - /* brute-force solution: close McMASA and re-instantiate with new settings */ - ivas_masa_enc_close( &( st_ivas->hMasa ) ); - ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); + nchan_inp = st_ivas->hEncoderConfig->nchan_inp; + input_Fs = st_ivas->hEncoderConfig->input_Fs; - /* Determine if to separate some channels from the analysis */ -#ifndef IVAS_FLOAT_FIXED - ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); -#else - ivas_mcmasa_setNumTransportChannels_fx( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); -#endif + /* Determine if to separate some channels from the analysis */ + ivas_mcmasa_set_separate_channel_mode( &( hMcMasa->separateChannelEnabled ), &( hMcMasa->separateChannelIndex ), st_ivas->hEncoderConfig->ivas_total_brate ); + + numAnalysisChannels = nchan_inp - 1; + if ( hMcMasa->separateChannelEnabled ) + { + numAnalysisChannels = nchan_inp - 2; + } + + /* With McMASA, we config MASA encoder only in init as we know the input and there are no frame-by-frame changes currently. */ + if ( ( error = ivas_masa_enc_config( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( ( error = ivas_masa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + + /* Determine the number of bands */ + hMcMasa->nbands = st_ivas->hMasa->config.numCodingBands; + hMcMasa->nCodingBands = st_ivas->hMasa->config.numCodingBands; + + /* Determine band grouping */ + if ( hMcMasa->nbands == 24 ) + { + for ( i = 0; i < hMcMasa->nbands + 1; i++ ) { - return error; + hMcMasa->band_grouping[i] = MASA_band_grouping_24[i] * CLDFB_TO_MDFT_FAC; } - - if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) + } + else + { + band_mapping = hMasa->data.band_mapping; + for ( i = 0; i < hMcMasa->nbands + 1; i++ ) { - return error; + hMcMasa->band_grouping[i] = MASA_band_grouping_24[band_mapping[i]] * CLDFB_TO_MDFT_FAC; } - - /* core SCE, CPE reconfiguration happens later */ } - return error; -} + maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH * CLDFB_TO_MDFT_FAC + 0.5f ); + + for ( i = 1; i < hMcMasa->nbands + 1; i++ ) + { + if ( hMcMasa->band_grouping[i] >= maxBin ) + { + hMcMasa->band_grouping[i] = maxBin; + hMcMasa->nbands = i; + break; + } + } + + /* initialize delay compensation */ + hMcMasa->num_samples_delay_comp = NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS ); +#ifdef DISABLE_DIRAC_DELAY_COMP + hMcMasa->num_samples_delay_comp = 0; /* disable delay compensation by setting to 0 */ +#endif + tmp_f = (float) hMcMasa->num_samples_delay_comp / (float) ( NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ) ); + hMcMasa->num_slots_delay_comp = (int16_t) ( tmp_f ); + + if ( tmp_f > (float) hMcMasa->num_slots_delay_comp ) + { + hMcMasa->num_slots_delay_comp++; + hMcMasa->offset_comp = -hMcMasa->num_samples_delay_comp; + hMcMasa->num_samples_delay_comp = hMcMasa->num_slots_delay_comp * NS2SA( input_Fs, DIRAC_SLOT_ENC_NS ); + hMcMasa->offset_comp += hMcMasa->num_samples_delay_comp; + } + else + { + hMcMasa->offset_comp = 0; + } + + /* set FB config. */ + if ( ( error = ivas_fb_set_cfg( &fb_cfg, MASA_FORMAT, numAnalysisChannels, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Allocate and initialize FB mixer handle */ + if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixer ), input_Fs, fb_cfg, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + + if ( hMcMasa->separateChannelEnabled ) + { + /* TD Energy calculation with LP */ + if ( ( hMcMasa->delay_buffer_lfe[0] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->delay_buffer_lfe[0], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); + + if ( ( hMcMasa->delay_buffer_lfe[1] = (float *) malloc( NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->delay_buffer_lfe[1], NS2SA( input_Fs, DELAY_DIRAC_ENC_CMP_NS + DIRAC_SLOT_ENC_NS ) ); + hMcMasa->hFbMixerLfe = NULL; + } + else + { + /* Allocate and initialize FB mixer handle for LFE channel */ + if ( ( error = ivas_fb_set_cfg( &fb_cfgLfe, MASA_FORMAT, 1, 0, 0, input_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_FB_mixer_open( &( hMcMasa->hFbMixerLfe ), input_Fs, fb_cfgLfe, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + hMcMasa->delay_buffer_lfe[0] = NULL; + hMcMasa->delay_buffer_lfe[1] = NULL; + } + + if ( hMcMasa->separateChannelEnabled ) + { + int16_t bufferSize; + + /* Ring buffer for the filterbank of the LFE analysis. + * The filterbank is using moving average lowpass filter with the crossover of 120 Hz. */ + bufferSize = (int16_t) ( ( input_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES ); + for ( i = 0; i < 2; i++ ) + { + if ( ( hMcMasa->lfeAnaRingBuffer[i] = (float *) malloc( bufferSize * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->lfeAnaRingBuffer[i], bufferSize ); + hMcMasa->lowpassSum[i] = 0.0f; + } + hMcMasa->ringBufferPointer = 0; + hMcMasa->ringBufferSize = bufferSize; + } + + + dirac_slot_ns = DIRAC_SLOT_ENC_NS; + + /* intensity 3-dim */ + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + } + } + + hMcMasa->no_col_avg_diff = (int8_t) ( DIRAC_NO_COL_AVG_DIFF_NS / dirac_slot_ns ); + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + if ( ( hMcMasa->buffer_intensity_real[i] = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + { + if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->buffer_intensity_real[i][j], hMcMasa->nbands ); + } + } + + if ( ( hMcMasa->buffer_intensity_real_vert = (float **) malloc( hMcMasa->no_col_avg_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + for ( j = 0; j < hMcMasa->no_col_avg_diff; j++ ) + { + if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( hMcMasa->nbands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->buffer_intensity_real_vert[j], hMcMasa->nbands ); + } + + if ( ( hMcMasa->buffer_energy = (float *) malloc( hMcMasa->nbands * hMcMasa->no_col_avg_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->buffer_energy, hMcMasa->nbands * hMcMasa->no_col_avg_diff ); + + if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1 ) + { + mvr2r( ls_azimuth_CICP6, ls_azimuth, nchan_inp - 1 ); + mvr2r( ls_elevation_CICP6, ls_elevation, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 1; + } + else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_7_1 ) + { + mvr2r( ls_azimuth_CICP12, ls_azimuth, nchan_inp - 1 ); + mvr2r( ls_elevation_CICP12, ls_elevation, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 7; + hMcMasa->isHorizontalSetup = 1; + } + else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_2 ) + { + mvr2r( ls_azimuth_CICP14, ls_azimuth, nchan_inp - 1 ); + mvr2r( ls_elevation_CICP14, ls_elevation, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 0; + } + else if ( st_ivas->hEncoderConfig->mc_input_setup == MC_LS_SETUP_5_1_4 ) + { + mvr2r( ls_azimuth_CICP16, ls_azimuth, nchan_inp - 1 ); + mvr2r( ls_elevation_CICP16, ls_elevation, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 0; + } + else + { + mvr2r( ls_azimuth_CICP19, ls_azimuth, nchan_inp - 1 ); + mvr2r( ls_elevation_CICP19, ls_elevation, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 7; + hMcMasa->isHorizontalSetup = 0; + } + + if ( hMcMasa->separateChannelEnabled ) + { + mvr2r( &ls_azimuth[hMcMasa->separateChannelIndex + 1], &ls_azimuth[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); + mvr2r( &ls_elevation[hMcMasa->separateChannelIndex + 1], &ls_elevation[hMcMasa->separateChannelIndex], numAnalysisChannels - hMcMasa->separateChannelIndex ); + hMcMasa->numHorizontalChannels--; + } + + computeEvenLayout( ls_azimuth, ls_azimuth_even, hMcMasa->numHorizontalChannels ); + if ( !hMcMasa->isHorizontalSetup ) + { + computeEvenLayout( &ls_azimuth[hMcMasa->numHorizontalChannels], &ls_azimuth_even[hMcMasa->numHorizontalChannels], numAnalysisChannels - hMcMasa->numHorizontalChannels ); + } + + for ( i = 0; i < numAnalysisChannels; i++ ) + { + hMcMasa->chnlToFoaMtx[0][i] = 1.0f; + hMcMasa->chnlToFoaMtx[1][i] = sinf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 ); + hMcMasa->chnlToFoaMtx[2][i] = sinf( ls_elevation[i] * PI_OVER_180 ); + hMcMasa->chnlToFoaMtx[3][i] = cosf( ls_azimuth[i] * PI_OVER_180 ) * cosf( ls_elevation[i] * PI_OVER_180 ); + + hMcMasa->chnlToFoaEvenMtx[0][i] = 1.0f; + hMcMasa->chnlToFoaEvenMtx[1][i] = sinf( ls_azimuth_even[i] * PI_OVER_180 ); + hMcMasa->chnlToFoaEvenMtx[2][i] = 0.0f; + hMcMasa->chnlToFoaEvenMtx[3][i] = cosf( ls_azimuth_even[i] * PI_OVER_180 ); + } + + hMcMasa->combineRatios = hMasa->config.mergeRatiosOverSubframes; + + mvr2r( ls_azimuth, hMcMasa->ls_azimuth, numAnalysisChannels ); + + for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) + { + left_min = 360.0f; + right_min = -360.0f; + + for ( j = 0; j < hMcMasa->numHorizontalChannels; j++ ) + { + azi_diff = ls_azimuth[j] - ls_azimuth[i]; + + if ( azi_diff > 180.0f ) + { + azi_diff -= 360.0f; + } + else if ( azi_diff < -180.0f ) + { + azi_diff += 360.0f; + } + + if ( azi_diff < left_min && azi_diff > 0.0f ) + { + hMcMasa->leftNearest[i] = j; + left_min = azi_diff; + } + + if ( azi_diff > right_min && azi_diff < 0.0f ) + { + hMcMasa->rightNearest[i] = j; + right_min = azi_diff; + } + } + } + + hMcMasa->prevMultiChEne = 0.0f; + hMcMasa->prevDownmixEne = 0.0f; + hMcMasa->prevEQ = 1.0f; + input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); + for ( i = 0; i < input_frame; i++ ) + { + hMcMasa->interpolator[i] = ( (float) i ) / ( (float) input_frame ); + } + + mvs2s( DirAC_block_grouping_5ms_MDFT, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + + hMcMasa->index_buffer_intensity = 0; + + st_ivas->hMcMasa = hMcMasa; + + return error; +} +#endif +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * ivas_mcmasa_enc_reconfig() + * + * Reconfigure McMASA encoder + *------------------------------------------------------------------------*/ + +ivas_error ivas_mcmasa_enc_reconfig_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + int32_t ivas_total_brate; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + /* bitrate changed, may need to do something */ + + /* brute-force solution: close McMASA and re-instantiate with new settings */ + ivas_masa_enc_close( &( st_ivas->hMasa ) ); + + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); + + /* Determine if to separate some channels from the analysis */ + ivas_mcmasa_setNumTransportChannels_fx( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); + + IF( NE_32( ( error = ivas_masa_enc_open( st_ivas ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = ivas_mcmasa_enc_open_fx( st_ivas ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* core SCE, CPE reconfiguration happens later */ + } + + return error; +} +#else +/*------------------------------------------------------------------------- + * ivas_mcmasa_enc_reconfig() + * + * Reconfigure McMASA encoder + *------------------------------------------------------------------------*/ + +ivas_error ivas_mcmasa_enc_reconfig( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + int32_t ivas_total_brate; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + /* bitrate changed, may need to do something */ + + /* brute-force solution: close McMASA and re-instantiate with new settings */ + ivas_masa_enc_close( &( st_ivas->hMasa ) ); +#ifndef IVAS_FLOAT_FIXED + ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#else + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#endif + + /* Determine if to separate some channels from the analysis */ +#ifndef IVAS_FLOAT_FIXED + ivas_mcmasa_setNumTransportChannels( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); +#else + ivas_mcmasa_setNumTransportChannels_fx( &( st_ivas->nchan_transport ), &( st_ivas->hEncoderConfig->element_mode_init ), ivas_total_brate ); +#endif + + IF( NE_32( ( error = ivas_masa_enc_open( st_ivas ) ), IVAS_ERR_OK ) ) + { + return error; + } +#ifndef IVAS_FLOAT_FIXED + if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) +#else + IF( NE_32( ( error = ivas_mcmasa_enc_open_fx( st_ivas ) ), IVAS_ERR_OK ) ) +#endif + { + return error; + } + + /* core SCE, CPE reconfiguration happens later */ + } + + return error; +} +#endif +#ifdef IVAS_FLOAT_FIXED +/*--------------------------------------------------------------------------* + * ivas_mcmasa_enc_close() + * + * + *--------------------------------------------------------------------------*/ + +void ivas_mcmasa_enc_close_fx( + MCMASA_ENC_HANDLE *hMcMasa, /* i/o: encoder McMASA handle */ + const int32_t input_Fs /* i : input sampling rate */ +) +{ + Word16 i, j; + + test(); + IF( hMcMasa == NULL || *hMcMasa == NULL ) + { + return; + } + + IF( ( *hMcMasa )->separateChannelEnabled ) + { + free( ( *hMcMasa )->delay_buffer_lfe[0] ); + free( ( *hMcMasa )->delay_buffer_lfe[1] ); + + FOR( i = 0; i < 2; i++ ) + { + free( ( *hMcMasa )->lfeAnaRingBuffer[i] ); + } + } + + ivas_FB_mixer_close( &( *hMcMasa )->hFbMixer, input_Fs, 0 ); + + IF( !( *hMcMasa )->separateChannelEnabled ) + { + ivas_FB_mixer_close( &( *hMcMasa )->hFbMixerLfe, input_Fs, 0 ); + } + + /* intensity 3-dim */ + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hMcMasa )->direction_vector_m_fx[i][j] ); + ( *hMcMasa )->direction_vector_m_fx[i][j] = NULL; + } + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hMcMasa )->direction_vector_e[i][j] ); + ( *hMcMasa )->direction_vector_e[i][j] = NULL; + } + + FOR( j = 0; j < ( *hMcMasa )->no_col_avg_diff; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_fx[i][j] ); + ( *hMcMasa )->buffer_intensity_real_fx[i][j] = NULL; + } + + free( ( *hMcMasa )->buffer_intensity_real_fx[i] ); + ( *hMcMasa )->buffer_intensity_real_fx[i] = NULL; + + free( ( *hMcMasa )->direction_vector_m_fx[i] ); + ( *hMcMasa )->direction_vector_m_fx[i] = NULL; + + free( ( *hMcMasa )->direction_vector_e[i] ); + ( *hMcMasa )->direction_vector_e[i] = NULL; + } + + FOR( j = 0; j < ( *hMcMasa )->no_col_avg_diff; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_vert_fx[j] ); + ( *hMcMasa )->buffer_intensity_real_vert_fx[j] = NULL; + } + free( ( *hMcMasa )->buffer_intensity_real_vert_fx ); + ( *hMcMasa )->buffer_intensity_real_vert_fx = NULL; + + free( ( *hMcMasa )->buffer_energy_fx ); + ( *hMcMasa )->buffer_energy_fx = NULL; + + free( ( *hMcMasa ) ); + ( *hMcMasa ) = NULL; + return; +} +#else /*--------------------------------------------------------------------------* * ivas_mcmasa_enc_close() * @@ -556,8 +1203,214 @@ void ivas_mcmasa_enc_close( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +/*--------------------------------------------------------------------------* + * ivas_mcmasa_enc() + * + * Multichannel MASA encoder + *--------------------------------------------------------------------------*/ + +void ivas_mcmasa_enc_fx( + MCMASA_ENC_HANDLE hMcMasa, /* i/o: Encoder McMASA handle */ + IVAS_QMETADATA_HANDLE hQMeta, /* o : Qmetadata handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: Encoder MASA handle */ + Word32 *data_fx[], /* i : Input frame of audio */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport, /* i : Number of transport channels */ + const Word16 nchan_inp, /* i : Number of input channels */ + const Word16 q_inp /* i : Input data q-format */ +) +{ + Word16 i, j, k; + Word16 nBands = hMcMasa->nbands; + move16(); + Word16 nBlocks = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + UWord8 fixedDistance = 0; + move16(); + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 separatedChannelSignal[L_FRAME48k]; + + /* Compute low frequency energy */ + computeLfeEnergy_fx( hMcMasa, data_fx, input_frame, q_inp ); + + /* Sum center and LFE, move surround channels */ + v_add_32( data_fx[2], data_fx[3], data_fx[2], input_frame ); + FOR( i = 4; i < nchan_inp; i++ ) + { + Copy32( data_fx[i], data_fx[i - 1], input_frame ); + } + + IF( hMcMasa->separateChannelEnabled ) + { + /* Identify channel to separate */ + i = hMcMasa->separateChannelIndex; + move16(); + + /* Separate the identified channel */ + Copy32( data_fx[i], separatedChannelSignal, input_frame ); + + /* Move the remaining channels in order to perform the analysis without the separated channel */ + FOR( i = ( hMcMasa->separateChannelIndex + 1 ); i < ( nchan_inp - 1 ); i++ ) + { + Copy32( data_fx[i], data_fx[i - 1], input_frame ); + } + } + + /* Analysis */ + ivas_mcmasa_param_est_enc_fx( hMcMasa, hMasa, data_fx, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, input_frame, nchan_inp, q_inp ); + + /* Determine LFE-to-total energy ratio */ + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hMasa->data.lfeToTotalEnergyRatio_fx[i] = BASOP_Util_Divide3232_Scale( hMcMasa->lfeLfEne[i], L_add( EPSILON_FX, hMcMasa->totalLfEne[i] ), &hMasa->data.lfeToTotalEnergyRatio_e[i] ); + hMasa->data.lfeToTotalEnergyRatio_e[i] = add( sub( hMcMasa->lfeLfEne_e[i], hMcMasa->totalLfEne_e[i] ), hMasa->data.lfeToTotalEnergyRatio_e[i] ); + } + + /* Set analyzed values to the MASA struct */ + FOR( i = 0; i < nBands; i++ ) + { + FOR( j = 0; j < nBlocks; j++ ) + { + IF( hMcMasa->combineRatios ) + { + k = 0; + move16(); + } + ELSE + { + k = j; + move16(); + } + + hQMeta->q_direction[0].band_data[i].azimuth_fx[j] = azimuth_m_values_fx[j][i]; + move32(); + hQMeta->q_direction[0].band_data[i].elevation_fx[j] = elevation_m_values_fx[j][i]; + move32(); + hQMeta->q_direction[0].band_data[i].energy_ratio_fx[j] = energyRatio_fx[k][i]; + move32(); + hQMeta->q_direction[0].band_data[i].distance[j] = fixedDistance; + move16(); + + IF( hQMeta->surcoh_band_data != NULL ) + { + hQMeta->q_direction[0].coherence_band_data[i].spread_coherence[j] = (uint8_t) round_fx( Mpy_32_32( spreadCoherence_fx[j][i], L_shl( UINT8_MAX, Q16 ) ) ); + hQMeta->surcoh_band_data[i].surround_coherence[j] = (uint8_t) round_fx( Mpy_32_32( surroundingCoherence_fx[k][i], L_shl( UINT8_MAX, Q16 ) ) ); + } + } + } + + /* At lower sampling rates, set zeros for higher bands that were not analyzed */ + IF( LT_16( nBands, hMcMasa->nCodingBands ) ) + { + FOR( i = nBands; i < hMcMasa->nCodingBands; i++ ) + { + FOR( j = 0; j < nBlocks; j++ ) + { + hQMeta->q_direction[0].band_data[i].azimuth_fx[j] = 0; + move32(); + hQMeta->q_direction[0].band_data[i].elevation_fx[j] = 0; + move32(); + hQMeta->q_direction[0].band_data[i].energy_ratio_fx[j] = 0; + move32(); + hQMeta->q_direction[0].band_data[i].distance[j] = 0; + move16(); + + IF( hQMeta->surcoh_band_data != NULL ) + { + hQMeta->q_direction[0].coherence_band_data[i].spread_coherence[j] = 0; + move16(); + hQMeta->surcoh_band_data[i].surround_coherence[j] = 0; + move16(); + } + } + } + } + + /* Downmix */ + ivas_mcmasa_dmx_fx( hMcMasa, data_fx, 31 - q_inp, input_frame, nchan_transport, nchan_inp ); + + IF( hMcMasa->separateChannelEnabled ) + { + /* Put separated channel back to data_f to first empty channel after the transport audio signals for encoding */ + Copy32( separatedChannelSignal, data_fx[2], input_frame ); + } + + /* Update mcMASA-relevant coding parameters */ + /* These are reset to default values as they may be modified during later processing. */ + hMasa->config.joinedSubframes = FALSE; + hQMeta->q_direction[0].cfg.nbands = hMcMasa->nbands; + move16(); + hQMeta->q_direction[0].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + hQMeta->all_coherence_zero = 1; + + /* Check spread coherence */ + i = 0; + move16(); + test(); + WHILE( LT_16( i, nBlocks ) && hQMeta->all_coherence_zero ) + { + j = 0; + move16(); + test(); + WHILE( LT_16( j, nBands ) && hQMeta->all_coherence_zero ) + { + IF( GT_32( spreadCoherence_fx[i][j], MASA_COHERENCE_THRESHOLD_FX ) ) + { + hQMeta->all_coherence_zero = 0; + move16(); + } + j++; + } + i++; + } + /* Check surrounding coherence */ + IF( hQMeta->all_coherence_zero ) + { + Word32 diffuse_to_total_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + UWord8 cohSignificant; + Word16 nSubFrames; + + IF( hMcMasa->combineRatios ) + { + nSubFrames = 1; + move16(); + } + ELSE + { + nSubFrames = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + } + + FOR( i = 0; i < nSubFrames; i++ ) + { + FOR( j = 0; j < nBands; j++ ) + { + diffuse_to_total_ratio_fx[i][j] = L_max( 0, L_sub( ONE_IN_Q31, energyRatio_fx[i][j] ) ); + move32(); + } + } + + cohSignificant = ivas_masa_surrcoh_signicant_fx( surroundingCoherence_fx, diffuse_to_total_ratio_fx, nSubFrames, nBands ); + IF( cohSignificant ) + { + hQMeta->all_coherence_zero = 0; + move16(); + } + } + hMasa->config.coherencePresent = !hQMeta->all_coherence_zero; + move16(); + return; +} +#else /*--------------------------------------------------------------------------* * ivas_mcmasa_enc() * @@ -725,7 +1578,7 @@ void ivas_mcmasa_enc( return; } - +#endif /*--------------------------------------------------------------------------* * ivas_mcmasa_param_est_enc() @@ -734,560 +1587,837 @@ void ivas_mcmasa_enc( *--------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -void ivas_mcmasa_param_est_enc( - MCMASA_ENC_HANDLE hMcMasa, /* i : McMASA encoder structure */ - MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder structure */ - float *data_f[], /* i : Audio frame in MC-format */ - float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ - float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ - float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ - float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ - float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ - const int16_t input_frame, /* i : Input frame size */ - const int16_t nchan_inp /* i : Number of input channels */ +void ivas_mcmasa_param_est_enc_fx( + MCMASA_ENC_HANDLE hMcMasa, /* i : McMASA encoder structure */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder structure */ + Word32 *data_f[], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp, /* i : Number of input channels */ + const Word16 q_inp /* i : Number of input channels */ ) { - float reference_power[MDFT_NO_COL_MAX][DIRAC_NO_FB_BANDS_MAX]; - int16_t ts, i, j, d; - int16_t num_freq_bins, num_freq_bands, index; - float dir_v[DIRAC_NUM_DIMS]; -#ifdef IVAS_FLOAT_FIXED_ - Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 reference_power_fx[MDFT_NO_COL_MAX][DIRAC_NO_FB_BANDS_MAX]; + Word16 ts, i, j, d; + Word16 num_freq_bins, num_freq_bands, index; Word32 dir_v_fx[DIRAC_NUM_DIMS]; -#endif - int16_t l_ts; - float *pcm_in[MCMASA_MAX_ANA_CHANS]; - float Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX]; - float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX]; - float *p_Chnl_RealBuffer[MCMASA_MAX_ANA_CHANS]; - float *p_Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS]; - float Foa_RealBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; - float Foa_ImagBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; - float FoaEven_RealBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; - float FoaEven_ImagBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; - float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; - float intensity_even_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; - float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; - float diffuseness_vector[MASA_FREQUENCY_BANDS]; - float vertical_diffuseness_vector[MASA_FREQUENCY_BANDS]; - float diffuseness_m[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float coherentEnergyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - int16_t band_m_idx, block_m_idx; - float renormalization_factor_diff[MASA_FREQUENCY_BANDS]; - float norm_tmp; - int16_t mrange[2], brange[2]; - int16_t numSubFramesForRatio; + Word16 out_exp[MASA_FREQUENCY_BANDS]; + Word16 q_vdv[MASA_FREQUENCY_BANDS]; + Word16 l_ts; + Word32 *pcm_in[MCMASA_MAX_ANA_CHANS]; + Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX]; + Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX]; + Word32 *p_Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS]; + Word32 *p_Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS]; + Word32 Foa_RealBuffer_fx[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; + Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; + Word32 FoaEven_RealBuffer_fx[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; + Word32 FoaEven_ImagBuffer_fx[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX]; + Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 intensity_even_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS]; + Word32 vertical_diffuseness_vector_fx[MASA_FREQUENCY_BANDS]; + Word32 diffuseness_m_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 diffuseness_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 coherentEnergyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 coherentEnergyRatio_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 band_m_idx, block_m_idx; + Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS]; + Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS]; + Word32 norm_tmp_fx; + Word16 mrange[2], brange[2]; + Word16 numSubFramesForRatio; CovarianceMatrix COVls[MASA_FREQUENCY_BANDS]; - float absCOVls[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; - float lsEnergy[MCMASA_MAX_ANA_CHANS]; - float lsEnergySum, maxEne; - int16_t loudestCh; - float surrCoh, tempCoh, tempCoh2; - int16_t i1, i2, i3; - float angleDist, minAngleDist; - float currentAzi; - float lsEnergyRelation; - float tempLsEnergyRelation; - float stereoness, cohwideness, spreadCoh; - float stereoRatio, cohPanRatio; - float stereoCoh, cohPanCoh, cohRatio; - float renormalization_factor_coh[MASA_FREQUENCY_BANDS]; - int16_t numAnalysisChannels; - - num_freq_bins = input_frame / MDFT_NO_COL_MAX; + Word32 absCOVls_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word16 absCOVls_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word32 lsEnergy_fx[MCMASA_MAX_ANA_CHANS]; + Word16 lsEnergy_e[MCMASA_MAX_ANA_CHANS]; + Word32 lsEnergySum_fx, maxEne_fx; + Word16 lsEnergySum_e = 0, maxEne_e; + move16(); + Word16 loudestCh; + Word32 surrCoh_fx, tempCoh_fx, tempCoh2_fx; + Word16 surrCoh_e, tempCoh_e, tempCoh2_e; + Word16 i1, i2, i3; + Word32 angleDist_fx, minAngleDist_fx; + Word32 currentAzi_fx; + Word32 lsEnergyRelation_fx; + Word16 lsEnergyRelation_e; + Word32 tempLsEnergyRelation_fx; + Word16 tempLsEnergyRelation_e; + Word32 stereoness_fx, cohwideness_fx, spreadCoh_fx; + Word32 stereoRatio_fx, cohPanRatio_fx; + Word32 stereoCoh_fx, cohPanCoh_fx, cohRatio_fx; + Word16 stereoCoh_e, cohPanCoh_e, spreadCoh_e, stereoness_e; + Word32 renormalization_factor_coh_fx[MASA_FREQUENCY_BANDS]; + Word16 renormalization_factor_coh_e[MASA_FREQUENCY_BANDS]; + Word16 surroundingCoherence_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 numAnalysisChannels; + + num_freq_bins = idiv1616( input_frame, MDFT_NO_COL_MAX ); num_freq_bands = hMcMasa->nbands; - l_ts = input_frame / MDFT_NO_COL_MAX; + move16(); + l_ts = idiv1616( input_frame, MDFT_NO_COL_MAX ); - numAnalysisChannels = nchan_inp - 1; - if ( hMcMasa->separateChannelEnabled ) + set16_fx( q_vdv, 31, MASA_FREQUENCY_BANDS ); + set16_fx( out_exp, 30, MASA_FREQUENCY_BANDS ); + + numAnalysisChannels = sub( nchan_inp, 1 ); + IF( hMcMasa->separateChannelEnabled ) { - numAnalysisChannels = nchan_inp - 2; + numAnalysisChannels = sub( nchan_inp, 2 ); } - if ( hMcMasa->combineRatios ) + IF( hMcMasa->combineRatios ) { /* Need to initialize renormalization_factors, and variables to be normalized */ - set_zero( renormalization_factor_diff, hMcMasa->nbands ); - set_zero( diffuseness_m[0], hMcMasa->nbands ); - set_zero( renormalization_factor_coh, hMcMasa->nbands ); - set_zero( surroundingCoherence[0], hMcMasa->nbands ); - set_zero( coherentEnergyRatio[0], hMcMasa->nbands ); + set_zero_fx( renormalization_factor_diff_fx, hMcMasa->nbands ); + set16_fx( renormalization_factor_diff_e, 0, hMcMasa->nbands ); + set_zero_fx( &diffuseness_m_fx[0][0], MASA_FREQUENCY_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES ); + set16_fx( &diffuseness_e[0][0], 31, MASA_FREQUENCY_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES ); + set_zero_fx( renormalization_factor_coh_fx, hMcMasa->nbands ); + set16_fx( renormalization_factor_coh_e, 31, hMcMasa->nbands ); + set_zero_fx( surroundingCoherence_fx[0], hMcMasa->nbands ); + set16_fx( &surroundingCoherence_e[0][0], 31, MASA_FREQUENCY_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES ); + set_zero_fx( coherentEnergyRatio_fx[0], hMcMasa->nbands ); + set16_fx( &coherentEnergyRatio_e[0][0], 0, MASA_FREQUENCY_BANDS * MAX_PARAM_SPATIAL_SUBFRAMES ); } /* Copy current frame to memory for delay compensation */ - for ( i = 0; i < numAnalysisChannels; i++ ) + FOR( i = 0; i < numAnalysisChannels; i++ ) { pcm_in[i] = data_f[i]; - p_Chnl_RealBuffer[i] = &Chnl_RealBuffer[i][0]; - p_Chnl_ImagBuffer[i] = &Chnl_ImagBuffer[i][0]; + p_Chnl_RealBuffer_fx[i] = &Chnl_RealBuffer_fx[i][0]; + p_Chnl_ImagBuffer_fx[i] = &Chnl_ImagBuffer_fx[i][0]; } /* do processing over all CLDFB time slots */ - for ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) { mrange[0] = hMcMasa->block_grouping[block_m_idx]; + move16(); mrange[1] = hMcMasa->block_grouping[block_m_idx + 1]; + move16(); - for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] = 0; - hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] = 0; - hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0; + move32(); + hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0; + move32(); + hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0; + move32(); } /* Reset variable */ - for ( i = 0; i < hMcMasa->nbands; i++ ) + FOR( i = 0; i < hMcMasa->nbands; i++ ) { - for ( j = 0; j < numAnalysisChannels; j++ ) + FOR( j = 0; j < numAnalysisChannels; j++ ) { - set_zero( COVls[i].xr[j], numAnalysisChannels ); - set_zero( COVls[i].xi[j], numAnalysisChannels ); + set_zero_fx( COVls[i].xr_fx[j], numAnalysisChannels ); + set_zero_fx( COVls[i].xi_fx[j], numAnalysisChannels ); + set16_fx( COVls[i].xr_e[j], 0, numAnalysisChannels ); + set16_fx( COVls[i].xi_e[j], 0, numAnalysisChannels ); } } - for ( ts = mrange[0]; ts < mrange[1]; ts++ ) + FOR( ts = mrange[0]; ts < mrange[1]; ts++ ) { - ivas_fb_mixer_get_windowed_fr( hMcMasa->hFbMixer, pcm_in, p_Chnl_RealBuffer, p_Chnl_ImagBuffer, l_ts, l_ts, hMcMasa->hFbMixer->fb_cfg->num_in_chans ); + Word16 cr_q = MAX_16, ci_q = MAX_16, sf, c_e; + Word16 inp_q = q_inp; + move16(); + move16(); + move16(); - ivas_fb_mixer_update_prior_input( hMcMasa->hFbMixer, pcm_in, l_ts, hMcMasa->hFbMixer->fb_cfg->num_in_chans ); + ivas_fb_mixer_get_windowed_fr_fx( hMcMasa->hFbMixer, pcm_in, p_Chnl_RealBuffer_fx, p_Chnl_ImagBuffer_fx, l_ts, l_ts, hMcMasa->hFbMixer->fb_cfg->num_in_chans, 0 ); - for ( i = 0; i < numAnalysisChannels; i++ ) + ivas_fb_mixer_update_prior_input_fx( hMcMasa->hFbMixer, pcm_in, l_ts, hMcMasa->hFbMixer->fb_cfg->num_in_chans ); + + FOR( i = 0; i < numAnalysisChannels; i++ ) { pcm_in[i] += l_ts; + cr_q = s_min( cr_q, ivas_getScaleFactor32( Chnl_ImagBuffer_fx[i], DIRAC_NO_FB_BANDS_MAX ) ); + ci_q = s_min( ci_q, ivas_getScaleFactor32( Chnl_RealBuffer_fx[i], DIRAC_NO_FB_BANDS_MAX ) ); } + sf = sub( s_min( cr_q, ci_q ), 5 ); + FOR( i = 0; i < numAnalysisChannels; i++ ) + { + scale_sig32( Chnl_RealBuffer_fx[i], DIRAC_NO_FB_BANDS_MAX, sf ); // Q-> inp_q + sf + scale_sig32( Chnl_ImagBuffer_fx[i], DIRAC_NO_FB_BANDS_MAX, sf ); // Q-> inp_q + sf + } + inp_q = add( inp_q, sf ); + c_e = sub( 31, inp_q ); + /* Compute covariance matrix */ - for ( i = 0; i < num_freq_bands; i++ ) + FOR( i = 0; i < num_freq_bands; i++ ) { brange[0] = hMcMasa->band_grouping[i]; + move16(); brange[1] = hMcMasa->band_grouping[i + 1]; - for ( j = brange[0]; j < brange[1]; j++ ) + move16(); + FOR( j = brange[0]; j < brange[1]; j++ ) { - compute_cov_mtx( Chnl_RealBuffer, Chnl_ImagBuffer, j, numAnalysisChannels, &( COVls[i] ) ); + compute_cov_mtx_fx( Chnl_RealBuffer_fx, Chnl_ImagBuffer_fx, j, numAnalysisChannels, &( COVls[i] ), sub( 31, inp_q ) ); } /* Store energies for guiding metadata encoding */ - hMasa->data.energy[block_m_idx][i] = 0.0f; - for ( j = 0; j < numAnalysisChannels; j++ ) + hMasa->data.energy_fx[block_m_idx][i] = 0; + move32(); + hMasa->data.energy_e[block_m_idx][i] = 31; + move16(); + FOR( j = 0; j < numAnalysisChannels; j++ ) { - hMasa->data.energy[block_m_idx][i] += COVls[i].xr[j][j]; + move32(); + hMasa->data.energy_fx[block_m_idx][i] = BASOP_Util_Add_Mant32Exp( hMasa->data.energy_fx[block_m_idx][i], hMasa->data.energy_e[block_m_idx][i], COVls[i].xr_fx[j][j], COVls[i].xr_e[j][j], &hMasa->data.energy_e[block_m_idx][i] ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( hMasa->data.energy_e[block_m_idx][i] < 31 ) + { + hMasa->data.energy[block_m_idx][i] = hMasa->data.energy_fx[block_m_idx][i] / (float) ( 1 << ( 31 - hMasa->data.energy_e[block_m_idx][i] ) ); + } + ELSE + { + hMasa->data.energy[block_m_idx][i] = hMasa->data.energy_fx[block_m_idx][i] * (float) ( 1 << ( hMasa->data.energy_e[block_m_idx][i] - 31 ) ); } +#endif } - if ( !hMcMasa->separateChannelEnabled ) + IF( !hMcMasa->separateChannelEnabled ) { /* Compute low frequency energy */ - for ( i = 0; i < numAnalysisChannels; i++ ) + FOR( i = 0; i < numAnalysisChannels; i++ ) { - for ( j = 0; j < CLDFB_TO_MDFT_FAC; j++ ) + FOR( j = 0; j < CLDFB_TO_MDFT_FAC; j++ ) { - hMcMasa->totalLfEne[block_m_idx] += Chnl_RealBuffer[i][j] * Chnl_RealBuffer[i][j] + Chnl_ImagBuffer[i][j] * Chnl_ImagBuffer[i][j]; + move32(); + hMcMasa->totalLfEne[block_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->totalLfEne[block_m_idx], hMcMasa->totalLfEne_e[block_m_idx], L_add( Mpy_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mpy_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ), sub( 31, sub( shl( inp_q, 1 ), 31 ) ), &hMcMasa->totalLfEne_e[block_m_idx] ); } } } /* Compute standard FOA */ /* W */ - v_add( Chnl_RealBuffer[0], Chnl_RealBuffer[1], Foa_RealBuffer[0], num_freq_bins ); - v_add( Chnl_ImagBuffer[0], Chnl_ImagBuffer[1], Foa_ImagBuffer[0], num_freq_bins ); - for ( i = 2; i < numAnalysisChannels; i++ ) + v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); + v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); + FOR( i = 2; i < numAnalysisChannels; i++ ) { - v_add( Chnl_RealBuffer[i], Foa_RealBuffer[0], Foa_RealBuffer[0], num_freq_bins ); - v_add( Chnl_ImagBuffer[i], Foa_ImagBuffer[0], Foa_ImagBuffer[0], num_freq_bins ); + v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); + v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); } /* Y */ - v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_RealBuffer[1], num_freq_bins ); - v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[1][0], Foa_ImagBuffer[1], num_freq_bins ); - for ( i = 1; i < numAnalysisChannels; i++ ) + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_RealBuffer[1], num_freq_bins ); - v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[1][i], Foa_ImagBuffer[1], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); } /* Z */ - if ( hMcMasa->isHorizontalSetup ) + IF( hMcMasa->isHorizontalSetup ) { /* Set zero for horizontal setups */ - set_zero( Foa_RealBuffer[2], num_freq_bins ); - set_zero( Foa_ImagBuffer[2], num_freq_bins ); + set_zero_fx( Foa_RealBuffer_fx[2], num_freq_bins ); + set_zero_fx( Foa_ImagBuffer_fx[2], num_freq_bins ); } - else + ELSE { - v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_RealBuffer[2], num_freq_bins ); - v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[2][0], Foa_ImagBuffer[2], num_freq_bins ); - for ( i = 1; i < numAnalysisChannels; i++ ) + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_RealBuffer[2], num_freq_bins ); - v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[2][i], Foa_ImagBuffer[2], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); } } /* X */ - v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_RealBuffer[3], num_freq_bins ); - v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaMtx[3][0], Foa_ImagBuffer[3], num_freq_bins ); - for ( i = 1; i < numAnalysisChannels; i++ ) + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_RealBuffer[3], num_freq_bins ); - v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaMtx[3][i], Foa_ImagBuffer[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); } /* Compute even FOA */ /* W */ - mvr2r( Foa_RealBuffer[0], FoaEven_RealBuffer[0], num_freq_bins ); - mvr2r( Foa_ImagBuffer[0], FoaEven_ImagBuffer[0], num_freq_bins ); + Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); + Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); /* Y */ - v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_RealBuffer[1], num_freq_bins ); - v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[1][0], FoaEven_ImagBuffer[1], num_freq_bins ); - for ( i = 1; i < numAnalysisChannels; i++ ) + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_RealBuffer[1], num_freq_bins ); - v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[1][i], FoaEven_ImagBuffer[1], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); } /* Z (even setups are handled as horizontal) */ - set_zero( FoaEven_RealBuffer[2], num_freq_bins ); - set_zero( FoaEven_ImagBuffer[2], num_freq_bins ); + set_zero_fx( FoaEven_RealBuffer_fx[2], num_freq_bins ); + set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins ); /* X */ - v_multc( Chnl_RealBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_RealBuffer[3], num_freq_bins ); - v_multc( Chnl_ImagBuffer[0], hMcMasa->chnlToFoaEvenMtx[3][0], FoaEven_ImagBuffer[3], num_freq_bins ); - for ( i = 1; i < numAnalysisChannels; i++ ) + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc( Chnl_RealBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_RealBuffer[3], num_freq_bins ); - v_multc_acc( Chnl_ImagBuffer[i], hMcMasa->chnlToFoaEvenMtx[3][i], FoaEven_ImagBuffer[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); } /* Direction estimation */ - computeIntensityVector_enc( + computeIntensityVector_enc_fx( hMcMasa->band_grouping, - Foa_RealBuffer, - Foa_ImagBuffer, + Foa_RealBuffer_fx, + Foa_ImagBuffer_fx, 0, num_freq_bands, - intensity_real ); + intensity_real_fx ); - computeDirectionVectors( - intensity_real[0], - intensity_real[1], - intensity_real[2], + computeDirectionVectors_fixed( + intensity_real_fx[0], + intensity_real_fx[1], + intensity_real_fx[2], 0, num_freq_bands, - direction_vector[0], - direction_vector[1], - direction_vector[2] ); + direction_vector_fx[0], + direction_vector_fx[1], + direction_vector_fx[2], c_e ); /* Power and intensity estimation for diffuseness */ - computeIntensityVector_enc( + computeIntensityVector_enc_fx( hMcMasa->band_grouping, - FoaEven_RealBuffer, - FoaEven_ImagBuffer, + FoaEven_RealBuffer_fx, + FoaEven_ImagBuffer_fx, 0, num_freq_bands, - intensity_even_real ); - - computeReferencePower_enc( hMcMasa->band_grouping, - FoaEven_RealBuffer, - FoaEven_ImagBuffer, - reference_power[ts], - 0, - num_freq_bands, - MC_FORMAT, - 0, - FOA_CHANNELS, - NULL, - NULL ); + intensity_even_real_fx ); + + computeReferencePower_enc_fx( hMcMasa->band_grouping, + FoaEven_RealBuffer_fx, + FoaEven_ImagBuffer_fx, + reference_power_fx[ts], + 0, + num_freq_bands, + MC_FORMAT, + 0, + FOA_CHANNELS ); /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % hMcMasa->no_col_avg_diff ) + 1; /* averaging_length = 32 */ + move16(); index = hMcMasa->index_buffer_intensity; - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + move16(); + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { /* only real part needed */ - mvr2r( intensity_even_real[i], &( hMcMasa->buffer_intensity_real[i][index - 1][0] ), num_freq_bands ); + Copy32( intensity_even_real_fx[i], &( hMcMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); } - mvr2r( reference_power[ts], &( hMcMasa->buffer_energy[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + hMcMasa->buffer_intensity_real_q[index - 1] = sub( shl( inp_q, 1 ), 31 ); + move16(); + Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + hMcMasa->buffer_energy_q[index - 1] = sub( shl( inp_q, 1 ), 31 ); + move16(); - computeDiffuseness_mdft( hMcMasa->buffer_intensity_real, hMcMasa->buffer_energy, num_freq_bands, hMcMasa->no_col_avg_diff, diffuseness_vector ); + computeDiffuseness_mdft_fx( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, hMcMasa->no_col_avg_diff, diffuseness_vector_fx, hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q, out_exp ); /* Compute vertical diffuseness, and tune original diffuseness if needed */ - if ( !hMcMasa->isHorizontalSetup ) + IF( !hMcMasa->isHorizontalSetup ) { - mvr2r( intensity_real[2], &( hMcMasa->buffer_intensity_real_vert[index - 1][0] ), num_freq_bands ); - computeVerticalDiffuseness( hMcMasa->buffer_intensity_real_vert, hMcMasa->buffer_energy, hMcMasa->no_col_avg_diff, num_freq_bands, vertical_diffuseness_vector ); -#ifdef IVAS_FLOAT_FIXED - //////////////////////// to be removed /////////////////////////////// - Word32 x1_fx[MASA_FREQUENCY_BANDS]; - Word32 x2_fx[MASA_FREQUENCY_BANDS]; - Word32 y_fx[MASA_FREQUENCY_BANDS]; - Word16 x1_q_fx[MASA_FREQUENCY_BANDS]; - Word16 x2_q_fx[MASA_FREQUENCY_BANDS]; - Word16 y_q_fx[MASA_FREQUENCY_BANDS]; - FOR( i = 0; i < num_freq_bands; i++ ) - { - x1_q_fx[i] = Q_factor_L( diffuseness_vector[i] ); - x1_fx[i] = (Word32) ( diffuseness_vector[i] * ( W_shl( 1, x1_q_fx[i] ) ) ); - x2_q_fx[i] = Q_factor_L( vertical_diffuseness_vector[i] ); - x2_fx[i] = (Word32) ( vertical_diffuseness_vector[i] * ( W_shl( 1, x2_q_fx[i] ) ) ); - } - ///////////////////////////////////////////////////////////////////////// - - v_min_fx( (const Word32 *) x1_fx, x1_q_fx, (const Word32 *) x2_fx, x2_q_fx, y_fx, y_q_fx, num_freq_bands ); - - //////////////////////// to be removed //////////////////////////////// - FOR( i = 0; i < num_freq_bands; i++ ) - { - diffuseness_vector[i] = (Float32) y_fx[i] / ( W_shl( 1, y_q_fx[i] ) ); - } - /////////////////////////////////////////////////////////////////////// -#else - v_min( diffuseness_vector, vertical_diffuseness_vector, diffuseness_vector, num_freq_bands ); -#endif + Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands ); + hMcMasa->buffer_intensity_real_vert_q[index - 1] = sub( shl( inp_q, 1 ), 31 ); + move16(); + computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, hMcMasa->no_col_avg_diff, num_freq_bands, vertical_diffuseness_vector_fx, hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q ); + v_min_fx( diffuseness_vector_fx, out_exp, vertical_diffuseness_vector_fx, q_vdv, diffuseness_vector_fx, out_exp, num_freq_bands ); } - for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - norm_tmp = reference_power[ts][band_m_idx] * ( 1 - diffuseness_vector[band_m_idx] ); - - hMcMasa->direction_vector_m[0][block_m_idx][band_m_idx] += norm_tmp * direction_vector[0][band_m_idx]; - hMcMasa->direction_vector_m[1][block_m_idx][band_m_idx] += norm_tmp * direction_vector[1][band_m_idx]; - hMcMasa->direction_vector_m[2][block_m_idx][band_m_idx] += norm_tmp * direction_vector[2][band_m_idx]; - - if ( hMcMasa->combineRatios ) + norm_tmp_fx = Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q31, diffuseness_vector_fx[band_m_idx] ) ); /*2q-31*/ + hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), sub( 31, sub( shl( inp_q, 1 ), 32 ) ), &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] ); + move32(); + hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), sub( 31, sub( shl( inp_q, 1 ), 32 ) ), &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] ); + move32(); + hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), sub( 31, sub( shl( inp_q, 1 ), 32 ) ), &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] ); + move32(); + IF( hMcMasa->combineRatios ) { - diffuseness_m[0][band_m_idx] += reference_power[ts][band_m_idx] * diffuseness_vector[band_m_idx]; - renormalization_factor_diff[band_m_idx] += reference_power[ts][band_m_idx]; + diffuseness_m_fx[0][band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[0][band_m_idx], diffuseness_e[0][band_m_idx], Mult_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), sub( 31, sub( shl( inp_q, 1 ), 31 ) ), &diffuseness_e[0][band_m_idx] ); + move32(); + renormalization_factor_diff_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], reference_power_fx[ts][band_m_idx], sub( 31, sub( shl( inp_q, 1 ), 31 ) ), &renormalization_factor_diff_e[band_m_idx] ); + move32(); } - else + ELSE { - diffuseness_m[block_m_idx][band_m_idx] = diffuseness_vector[band_m_idx]; + diffuseness_m_fx[block_m_idx][band_m_idx] = diffuseness_vector_fx[band_m_idx]; + diffuseness_e[block_m_idx][band_m_idx] = Q31; + move32(); } } } - for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - for ( d = 0; d < DIRAC_NUM_DIMS; d++ ) + Word16 max_e = MIN_16; + move16(); + FOR( d = 0; d < DIRAC_NUM_DIMS; d++ ) { - dir_v[d] = hMcMasa->direction_vector_m[d][block_m_idx][band_m_idx]; + max_e = s_max( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] ); } -#ifdef IVAS_FLOAT_FIXED_ - /*==========================================flt-2-fix======================================================*/ - Word16 q_dir_e = 0; - f2me_buf( dir_v, dir_v_fx, &q_dir_e, 3 ); - Scale_sig32( dir_v_fx, 3, -1 ); - /*==========================================flt-2-fix======================================================*/ - - ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, Q30, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] ); - - /*==========================================fix-2-flt======================================================*/ - azimuth_m_values[block_m_idx][band_m_idx] = fixedToFloat( azimuth_m_values_fx[block_m_idx][band_m_idx], Q22 ); - elevation_m_values[block_m_idx][band_m_idx] = fixedToFloat( elevation_m_values_fx[block_m_idx][band_m_idx], Q22 ); - /*==========================================fix-2-flt======================================================*/ -#else - ivas_qmetadata_direction_vector_to_azimuth_elevation( dir_v, &azimuth_m_values[block_m_idx][band_m_idx], &elevation_m_values[block_m_idx][band_m_idx] ); -#endif + max_e = add( max_e, 1 ); /*1 as guard bit to prevent overflow*/ + FOR( d = 0; d < DIRAC_NUM_DIMS; d++ ) + { + dir_v_fx[d] = L_shr( hMcMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], sub( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx] ) ); + move32(); + } + Word16 div_q = sub( 31, max_e ); + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx, div_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] ); + elevation_m_values_fx[block_m_idx][band_m_idx] = L_add( elevation_m_values_fx[block_m_idx][band_m_idx], L_shr( elevation_m_values_fx[block_m_idx][band_m_idx], 5 ) ); + move32(); } /* Coherence processing */ - for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { /* Compute absolute values */ - for ( i = 0; i < numAnalysisChannels; i++ ) + FOR( i = 0; i < numAnalysisChannels; i++ ) { - for ( j = i; j < numAnalysisChannels; j++ ) + FOR( j = i; j < numAnalysisChannels; j++ ) { - absCOVls[i][j] = sqrtf( ( COVls[band_m_idx].xr[i][j] * COVls[band_m_idx].xr[i][j] + COVls[band_m_idx].xi[i][j] * COVls[band_m_idx].xi[i][j] ) ); + Word32 temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( COVls[band_m_idx].xr_fx[i][j], COVls[band_m_idx].xr_fx[i][j] ), shl( COVls[band_m_idx].xr_e[i][j], 1 ), Mult_32_32( COVls[band_m_idx].xi_fx[i][j], COVls[band_m_idx].xi_fx[i][j] ), shl( COVls[band_m_idx].xi_e[i][j], 1 ), &absCOVls_e[i][j] ); + absCOVls_fx[i][j] = Sqrt32( temp, &absCOVls_e[i][j] ); + move32(); } - lsEnergy[i] = absCOVls[i][i]; + lsEnergy_fx[i] = absCOVls_fx[i][i]; + move32(); + lsEnergy_e[i] = absCOVls_e[i][i]; + move16(); } /* Find loudest channel */ - maxEne = lsEnergy[0]; + maxEne_fx = lsEnergy_fx[0]; + move32(); + maxEne_e = lsEnergy_e[0]; + move16(); loudestCh = 0; - for ( i = 1; i < numAnalysisChannels; i++ ) + move16(); + FOR( i = 1; i < numAnalysisChannels; i++ ) { - if ( lsEnergy[i] > maxEne ) + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], maxEne_fx, maxEne_e ), 1 ) ) { - maxEne = lsEnergy[i]; + maxEne_fx = lsEnergy_fx[i]; + move32(); + maxEne_e = lsEnergy_e[i]; + move16(); loudestCh = i; + move16(); } } /* Compute surrounding coherence */ - surrCoh = 1.0f; - for ( i = 0; i < numAnalysisChannels; i++ ) + surrCoh_fx = ONE_IN_Q31; + move32(); + surrCoh_e = 0; + move16(); + FOR( i = 0; i < numAnalysisChannels; i++ ) { - if ( i != loudestCh ) + IF( NE_16( i, loudestCh ) ) { - if ( i < loudestCh ) + IF( LT_16( i, loudestCh ) ) { i1 = i; + move16(); i2 = loudestCh; + move16(); } - else + ELSE { i1 = loudestCh; + move16(); i2 = i; + move16(); + } + Word16 temp_exp = add( lsEnergy_e[i1], lsEnergy_e[i2] ); + Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_exp ); + tempCoh_e = 0; + move16(); + tempCoh_fx = L_shl( BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], temp, &tempCoh_e ), 16 ); + tempCoh_e = add( sub( absCOVls_e[i1][i2], temp_exp ), tempCoh_e ); + IF( NE_16( BASOP_Util_Cmp_Mant32Exp( surrCoh_fx, surrCoh_e, tempCoh_fx, tempCoh_e ), -1 ) ) + { + surrCoh_fx = tempCoh_fx; + move32(); + surrCoh_e = tempCoh_e; + move16(); } - tempCoh = absCOVls[i1][i2] / ( sqrtf( ( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ) ); - surrCoh = ( surrCoh < tempCoh ) ? surrCoh : tempCoh; } } - surrCoh = surrCoh * surrCoh; - surrCoh = ( surrCoh < 1.0f ) ? surrCoh : 1.0f; - surrCoh = ( surrCoh > 0.0f ) ? surrCoh : 0.0f; + surrCoh_fx = L_shl( surrCoh_fx, surrCoh_e ); + surrCoh_e = 0; + move16(); + surrCoh_fx = Mult_32_32( surrCoh_fx, surrCoh_fx ); + IF( GE_32( surrCoh_fx, ONE_IN_Q31 ) ) + { + surrCoh_fx = ONE_IN_Q31; + move32(); + } + surrCoh_fx = L_max( surrCoh_fx, 0 ); /* Compute spread coherence */ - if ( elevation_m_values[block_m_idx][band_m_idx] < NEAR_HORIZONTAL_PLANE_ELEVATION ) /* Computed only near horizontal plane */ + IF( LT_32( elevation_m_values_fx[block_m_idx][band_m_idx], NEAR_HORIZONTAL_PLANE_ELEVATION_FX ) ) /* Computed only near horizontal plane */ { - minAngleDist = 180.0f; + minAngleDist_fx = 754974720; /*Q22*/ + move32(); i1 = 0; - currentAzi = azimuth_m_values[block_m_idx][band_m_idx]; - for ( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) + move16(); + currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; + move32(); + FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) { - angleDist = fabsf( currentAzi - hMcMasa->ls_azimuth[i] ); - if ( angleDist > 180.0f ) + angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); + IF( GT_32( angleDist_fx, 754974720 /*180.0f Q.22*/ ) ) { - angleDist = fabsf( angleDist - 360.0f ); + angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); } - if ( angleDist < minAngleDist ) + IF( LT_32( angleDist_fx, minAngleDist_fx ) ) { - minAngleDist = angleDist; + minAngleDist_fx = angleDist_fx; + move32(); i1 = i; + move16(); } } i2 = hMcMasa->leftNearest[i1]; + move16(); i3 = hMcMasa->rightNearest[i1]; - - if ( i2 < i3 ) + move16(); + Word16 temp_e = add( lsEnergy_e[i2], lsEnergy_e[i3] ); + Word32 temp = Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i2], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ); + IF( LT_16( i2, i3 ) ) { - stereoCoh = absCOVls[i2][i3] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) ); + stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i3], temp, &stereoCoh_e ); + stereoCoh_e = add( sub( absCOVls_e[i2][i3], temp_e ), stereoCoh_e ); } - else + ELSE { - stereoCoh = absCOVls[i3][i2] / ( sqrtf( lsEnergy[i2] * lsEnergy[i3] + EPSILON ) ); + stereoCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i2], temp, &stereoCoh_e ); + stereoCoh_e = add( sub( absCOVls_e[i3][i2], temp_e ), stereoCoh_e ); } - lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] + EPSILON ); - stereoness = stereoCoh * lsEnergyRelation; - - if ( i1 < i2 ) + stereoCoh_fx = L_shl( stereoCoh_fx, 16 ); + Word32 temp1, temp2; + Word16 temp1_e, temp2_e; + temp1 = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i2], lsEnergy_e[i2], lsEnergy_fx[i3], lsEnergy_e[i3], &temp1_e ); + temp2 = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, lsEnergy_fx[i1], lsEnergy_e[i1], &temp2_e ); + temp2 = L_add( temp2, EPSILON_FX ); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e ); + lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, temp2_e ) ); + lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); + stereoness_fx = Mult_32_32( stereoCoh_fx, lsEnergyRelation_fx ); + stereoness_e = stereoCoh_e; + move16(); + + IF( LT_16( i1, i2 ) ) { - tempCoh = absCOVls[i1][i2] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ); + temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] ); + tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i2], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e ); + tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i1][i2], temp_e ) ); } - else + ELSE { - tempCoh = absCOVls[i2][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i2] + EPSILON ) ); + temp_e = add( lsEnergy_e[i1], lsEnergy_e[i2] ); + tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e ); + tempCoh_e = add( tempCoh_e, sub( absCOVls_e[i2][i1], temp_e ) ); } - if ( i1 < i3 ) + tempCoh_fx = L_shl( tempCoh_fx, 16 ); + IF( LT_16( i1, i3 ) ) { - tempCoh2 = absCOVls[i1][i3] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) ); + temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] ); + tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i3], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e ); + tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i1][i3], temp_e ) ); } - else + ELSE { - tempCoh2 = absCOVls[i3][i1] / ( sqrtf( lsEnergy[i1] * lsEnergy[i3] + EPSILON ) ); + temp_e = add( lsEnergy_e[i1], lsEnergy_e[i3] ); + tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e ); + tempCoh2_e = add( tempCoh2_e, sub( absCOVls_e[i3][i1], temp_e ) ); } - cohPanCoh = ( tempCoh < tempCoh2 ) ? tempCoh : tempCoh2; - lsEnergyRelation = lsEnergy[i2] / ( lsEnergy[i1] + EPSILON ); - tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i2] + EPSILON ); - lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation; - tempLsEnergyRelation = lsEnergy[i3] / ( lsEnergy[i1] + EPSILON ); - lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation; - tempLsEnergyRelation = lsEnergy[i1] / ( lsEnergy[i3] + EPSILON ); - lsEnergyRelation = ( lsEnergyRelation < tempLsEnergyRelation ) ? lsEnergyRelation : tempLsEnergyRelation; - cohwideness = cohPanCoh * lsEnergyRelation; - - spreadCoh = ( cohwideness > stereoness ) ? cohwideness : stereoness; - if ( spreadCoh > 0.5f ) + tempCoh2_fx = L_shl( tempCoh2_fx, 16 ); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tempCoh_fx, tempCoh_e, tempCoh2_fx, tempCoh2_e ), -1 ) ) { - if ( cohwideness > stereoness ) + cohPanCoh_fx = tempCoh_fx; + move32(); + cohPanCoh_e = tempCoh_e; + move16(); + } + ELSE + { + cohPanCoh_fx = tempCoh2_fx; + move32(); + cohPanCoh_e = tempCoh2_e; + move16(); + } + IF( GT_32( cohPanCoh_fx, ONE_IN_Q30 ) ) + { + cohPanCoh_fx = ONE_IN_Q30; + move32(); + } + cohPanCoh_fx = L_shl_sat( cohPanCoh_fx, cohPanCoh_e ); /*Q31*/ + cohPanCoh_e = 0; + move16(); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i2], L_add( lsEnergy_fx[i1], EPSILON_FX ), &lsEnergyRelation_e ); + lsEnergyRelation_e = add( lsEnergyRelation_e, sub( lsEnergy_e[i2], lsEnergy_e[i1] ) ); + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i2], EPSILON_FX ), &tempLsEnergyRelation_e ); + tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i2] ) ); + IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + move32(); + lsEnergyRelation_e = tempLsEnergyRelation_e; + move16(); + } + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i3], L_add( lsEnergy_fx[i1], EPSILON_FX ), &tempLsEnergyRelation_e ); + tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i3], lsEnergy_e[i1] ) ); + IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + move32(); + lsEnergyRelation_e = tempLsEnergyRelation_e; + move16(); + } + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i1], L_add( lsEnergy_fx[i3], EPSILON_FX ), &tempLsEnergyRelation_e ); + tempLsEnergyRelation_e = add( tempLsEnergyRelation_e, sub( lsEnergy_e[i1], lsEnergy_e[i3] ) ); + IF( NE_16( BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ), -1 ) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + move32(); + lsEnergyRelation_e = tempLsEnergyRelation_e; + move16(); + } + lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); /*Q31*/ + cohwideness_fx = Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) ) + { + spreadCoh_fx = cohwideness_fx; + move32(); + spreadCoh_e = cohPanCoh_e; + move16(); + } + ELSE + { + spreadCoh_fx = stereoness_fx; + move32(); + spreadCoh_e = stereoness_e; + move16(); + } + IF( ( spreadCoh_e < 0 ) ) + { + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); + spreadCoh_e = 0; + move16(); + } + IF( GT_32( spreadCoh_fx, L_shl_sat( 1, sub( 30, spreadCoh_e ) /*0.5f with exp=spreadCoh_e*/ ) ) ) + { + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( cohwideness_fx, cohPanCoh_e, stereoness_fx, stereoness_e ), 1 ) ) { - tempCoh = stereoness - ( cohwideness - 0.5f ); - spreadCoh = ( tempCoh > 0.5f ) ? tempCoh : 0.5f; + tempCoh_fx = BASOP_Util_Add_Mant32Exp( stereoness_fx, stereoness_e, L_negate( L_sub( cohwideness_fx, L_shl( 1, sub( 30, cohPanCoh_e ) ) ) ), cohPanCoh_e, &tempCoh_e ); + IF( ( tempCoh_e < 0 ) ) + { + tempCoh_fx = L_shl( tempCoh_fx, tempCoh_e ); + tempCoh_e = 0; + move16(); + } + IF( GT_32( tempCoh_fx, L_shl_sat( 1, sub( 30, tempCoh_e ) ) ) ) + { + spreadCoh_fx = tempCoh_fx; + move32(); + } + ELSE + { + spreadCoh_fx = L_shl_sat( 1, sub( 30, tempCoh_e ) ); + } + spreadCoh_e = tempCoh_e; + move16(); } } - spreadCoh = ( spreadCoh < 1.0f ) ? spreadCoh : 1.0f; - spreadCoh = ( spreadCoh > 0.0f ) ? spreadCoh : 0.0f; + IF( ( spreadCoh_e < 0 ) ) + { + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); + spreadCoh_e = 0; + move16(); + } - /* Compute energy ratio tuning parameter */ - lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ) + EPSILON; - lsEnergyRelation = ( lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum; - stereoRatio = stereoCoh * lsEnergyRelation - surrCoh; + IF( ( GE_32( spreadCoh_fx, L_shl_sat( 1, sub( 31, spreadCoh_e ) ) ) ) ) + { + spreadCoh_fx = L_shl_sat( 1, sub( 31, spreadCoh_e ) ); + } + IF( ( spreadCoh_fx <= 0 ) ) + { + spreadCoh_fx = 0; + move32(); + } + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); /*Q31*/ - lsEnergyRelation = ( lsEnergy[i1] + lsEnergy[i2] + lsEnergy[i3] ) / lsEnergySum; - cohPanRatio = cohPanCoh * lsEnergyRelation - surrCoh; + /* Compute energy ratio tuning parameter */ + lsEnergySum_fx = 0; + move32(); + lsEnergySum_e = 0; + move16(); + FOR( i = 0; i < numAnalysisChannels; i++ ) + { + lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e ); + } + lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX ); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, lsEnergySum_fx, &lsEnergyRelation_e ); + lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, lsEnergySum_e ) ); + lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); + stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); + + temp2 = L_sub( temp2, EPSILLON_FX ); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e ); + lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp2_e, lsEnergySum_e ) ); + lsEnergyRelation_fx = L_shl_sat( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); + cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); + IF( GT_32( stereoRatio_fx, cohPanRatio_fx ) ) + { + cohRatio_fx = stereoRatio_fx; + move32(); + } + ELSE + { + cohRatio_fx = cohPanRatio_fx; + move32(); + } - cohRatio = ( stereoRatio > cohPanRatio ) ? stereoRatio : cohPanRatio; - cohRatio = ( cohRatio < 1.0f ) ? cohRatio : 1.0f; - cohRatio = ( cohRatio > 0.0f ) ? cohRatio : 0.0f; + IF( GE_32( cohRatio_fx, ONE_IN_Q31 ) ) + { + cohRatio_fx = ONE_IN_Q31; + move32(); + } + IF( cohRatio_fx <= 0 ) + { + cohRatio_fx = 0; + move32(); + } } - else /* Otherwise, set spread coherence to zero */ + ELSE /* Otherwise, set spread coherence to zero */ { - spreadCoh = 0.0f; - cohRatio = 0.0f; - lsEnergySum = sum_f( lsEnergy, numAnalysisChannels ); + spreadCoh_fx = 0; + move32(); + cohRatio_fx = 0; + move32(); + lsEnergySum_fx = 0; + move32(); + FOR( i = 0; i < numAnalysisChannels; i++ ) + { + lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e ); + } + lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX ); } /* Store values */ - spreadCoherence[block_m_idx][band_m_idx] = spreadCoh; - - if ( hMcMasa->combineRatios ) - { - surroundingCoherence[0][band_m_idx] += lsEnergySum * surrCoh; - coherentEnergyRatio[0][band_m_idx] += lsEnergySum * cohRatio; - renormalization_factor_coh[band_m_idx] += lsEnergySum; + spreadCoherence_fx[block_m_idx][band_m_idx] = spreadCoh_fx; /*Q31*/ + move32(); + + IF( hMcMasa->combineRatios ) + { + surroundingCoherence_fx[0][band_m_idx] = BASOP_Util_Add_Mant32Exp( surroundingCoherence_fx[0][band_m_idx], surroundingCoherence_e[0][band_m_idx], Mult_32_32( lsEnergySum_fx, surrCoh_fx ), lsEnergySum_e, &surroundingCoherence_e[0][band_m_idx] ); + move32(); + coherentEnergyRatio_fx[0][band_m_idx] = BASOP_Util_Add_Mant32Exp( coherentEnergyRatio_fx[0][band_m_idx], coherentEnergyRatio_e[0][band_m_idx], Mult_32_32( lsEnergySum_fx, cohRatio_fx ), lsEnergySum_e, &coherentEnergyRatio_e[0][band_m_idx] ); + move32(); + renormalization_factor_coh_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_coh_fx[band_m_idx], renormalization_factor_coh_e[band_m_idx], lsEnergySum_fx, lsEnergySum_e, &renormalization_factor_coh_e[band_m_idx] ); + move32(); } - else + ELSE { - surroundingCoherence[block_m_idx][band_m_idx] = surrCoh; - coherentEnergyRatio[block_m_idx][band_m_idx] = cohRatio; + surroundingCoherence_fx[block_m_idx][band_m_idx] = surrCoh_fx; + move32(); + coherentEnergyRatio_fx[block_m_idx][band_m_idx] = cohRatio_fx; + move32(); } } } - if ( hMcMasa->combineRatios ) + IF( hMcMasa->combineRatios ) { - for ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - if ( renormalization_factor_diff[band_m_idx] > EPSILON ) - { - diffuseness_m[0][band_m_idx] /= renormalization_factor_diff[band_m_idx]; - } - else - { - diffuseness_m[0][band_m_idx] = 0.f; - } - if ( renormalization_factor_coh[band_m_idx] > EPSILON ) - { - surroundingCoherence[0][band_m_idx] /= renormalization_factor_coh[band_m_idx]; - coherentEnergyRatio[0][band_m_idx] /= renormalization_factor_coh[band_m_idx]; - } - else - { - surroundingCoherence[0][band_m_idx] = 0.f; - coherentEnergyRatio[0][band_m_idx] = 0.f; + Word16 diffuseness_m_e; + IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) ) + { + diffuseness_m_fx[0][band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[0][band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e ); + move32(); + diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[0][band_m_idx], renormalization_factor_diff_e[band_m_idx] ) ); + diffuseness_m_fx[0][band_m_idx] = L_shl_sat( diffuseness_m_fx[0][band_m_idx], add( 16, diffuseness_m_e ) ); + move32(); + } + ELSE + { + diffuseness_m_fx[0][band_m_idx] = 0; + move32(); + } + IF( GT_32( renormalization_factor_coh_fx[band_m_idx], EPSILON_FX ) ) + { + Word16 cer_e = 31, sc_e = 31; + move16(); + move16(); + surroundingCoherence_fx[0][band_m_idx] = BASOP_Util_Divide3232_Scale( surroundingCoherence_fx[0][band_m_idx], renormalization_factor_coh_fx[band_m_idx], &sc_e ); + move32(); + sc_e = add( sc_e, sub( surroundingCoherence_e[0][band_m_idx], renormalization_factor_coh_e[band_m_idx] ) ); + surroundingCoherence_fx[0][band_m_idx] = L_shl_sat( surroundingCoherence_fx[0][band_m_idx], add( 16, sc_e ) ); + move32(); + coherentEnergyRatio_fx[0][band_m_idx] = BASOP_Util_Divide3232_Scale( coherentEnergyRatio_fx[0][band_m_idx], renormalization_factor_coh_fx[band_m_idx], &cer_e ); + move32(); + cer_e = add( cer_e, sub( coherentEnergyRatio_e[0][band_m_idx], renormalization_factor_coh_e[band_m_idx] ) ); + coherentEnergyRatio_fx[0][band_m_idx] = L_shl_sat( coherentEnergyRatio_fx[0][band_m_idx], add( 16, cer_e ) ); + move32(); + } + ELSE + { + surroundingCoherence_fx[0][band_m_idx] = 0; + move32(); + coherentEnergyRatio_fx[0][band_m_idx] = 0; + move32(); } } } /* Determine energy ratios */ - if ( hMcMasa->combineRatios ) + IF( hMcMasa->combineRatios ) { numSubFramesForRatio = 1; + move16(); } - else + ELSE { numSubFramesForRatio = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); } - for ( i = 0; i < numSubFramesForRatio; i++ ) + FOR( i = 0; i < numSubFramesForRatio; i++ ) { - for ( j = 0; j < hMcMasa->nbands; j++ ) + FOR( j = 0; j < hMcMasa->nbands; j++ ) { - energyRatio[i][j] = 1.0f - diffuseness_m[i][j]; - energyRatio[i][j] = ( energyRatio[i][j] > coherentEnergyRatio[i][j] ) ? energyRatio[i][j] : coherentEnergyRatio[i][j]; + energyRatio_fx[i][j] = L_sub( ONE_IN_Q31, diffuseness_m_fx[i][j] ); + move32(); + IF( GT_32( energyRatio_fx[i][j], coherentEnergyRatio_fx[i][j] ) ) + { + energyRatio_fx[i][j] = energyRatio_fx[i][j]; + move32(); + } + ELSE + { + energyRatio_fx[i][j] = coherentEnergyRatio_fx[i][j]; + move32(); + } } } @@ -1892,7 +3022,157 @@ void ivas_mcmasa_dmx_modify( /*--------------------------------------------------------------------------* * Local functions *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/* Compute downmix */ +static void ivas_mcmasa_dmx_fx( + MCMASA_ENC_HANDLE hMcMasa, + Word32 *data_fx[], + Word16 data_e, + const Word16 input_frame, + const Word16 nchan_transport, + const Word16 nchan_inp ) +{ + Word16 i, j; + Word16 numAnalysisChannels; + Word32 dmx_c_fx; + Word32 multiChEne_fx, downmixEne_fx; + Word32 prevEQ_fx, currEQ_fx, instEQ_fx; + Word32 alpha_fx, L_tmp, L_tmp1; + Word16 multiChEne_e, scale, downmixEne_e = 0, prevEQ_e, tmp, currEQ_e, instEQ_e; + move16(); + + numAnalysisChannels = sub( nchan_inp, 1 ); + IF( hMcMasa->separateChannelEnabled ) + { + numAnalysisChannels = sub( nchan_inp, 2 ); + } + + multiChEne_fx = 0; + move32(); + multiChEne_e = 0; + move16(); + FOR( j = 0; j < numAnalysisChannels; j++ ) + { + FOR( i = 0; i < input_frame; i++ ) + { + L_tmp1 = BASOP_Util_Add_Mant32Exp( data_fx[j][i], data_e, 0, 0, &scale ); + L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e + multiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, multiChEne_fx, multiChEne_e, &scale ); + multiChEne_e = scale; + move16(); + } + } + + IF( EQ_16( nchan_transport, 2 ) ) + { + Word16 numSideChannels; /* Channels other than left, right, center */ + Word16 leftIndex, rightIndex; + + numSideChannels = sub( shr( numAnalysisChannels, 1 ), 1 ); + FOR( j = 0; j < numSideChannels; j++ ) + { + IF( hMcMasa->separateChannelEnabled ) + { + leftIndex = add( shl( j, 1 ), 2 ); + rightIndex = add( shl( j, 1 ), 3 ); + } + ELSE + { + leftIndex = add( shl( j, 1 ), 3 ); + rightIndex = add( shl( j, 1 ), 4 ); + } + + FOR( i = 0; i < input_frame; i++ ) + { + data_fx[0][i] = L_add( data_fx[0][i], data_fx[leftIndex][i] ); + move32(); + data_fx[1][i] = L_add( data_fx[1][i], data_fx[rightIndex][i] ); + move32(); + } + } + + IF( !hMcMasa->separateChannelEnabled ) + { + FOR( i = 0; i < input_frame; i++ ) + { + dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_fx[2][i] ) ); + move32(); + data_fx[0][i] = L_add( dmx_c_fx, data_fx[0][i] ); + move32(); + data_fx[1][i] = L_add( dmx_c_fx, data_fx[1][i] ); + move32(); + } + } + } + ELSE IF( EQ_16( nchan_transport, 1 ) ) + { + FOR( i = 0; i < input_frame; i++ ) + { + FOR( j = 1; j < numAnalysisChannels; j++ ) + { + data_fx[0][i] = L_add( data_fx[0][i], data_fx[j][i] ); + move32(); + } + } + } + downmixEne_fx = 0; + move32(); + FOR( j = 0; j < nchan_transport; j++ ) + { + FOR( i = 0; i < input_frame; i++ ) + { + L_tmp1 = BASOP_Util_Add_Mant32Exp( data_fx[j][i], data_e, 0, 0, &scale ); + L_tmp = Mpy_32_32( L_tmp1, L_tmp1 ); // data_e + data_e + downmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, scale + scale, downmixEne_fx, downmixEne_e, &downmixEne_e ); + } + } + + alpha_fx = 214748364; // Q31 + move32(); + + L_tmp = Mpy_32_32( alpha_fx, multiChEne_fx ); + L_tmp1 = Mpy_32_32( 1932735284, hMcMasa->prevMultiChEne_fx ); + hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e ); + move32(); + + L_tmp = Mpy_32_32( alpha_fx, downmixEne_fx ); + L_tmp1 = Mpy_32_32( 1932735284, hMcMasa->prevDownmixEne_fx ); + hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e ); + move32(); + + prevEQ_fx = hMcMasa->prevEQ_fx; + move32(); + prevEQ_e = hMcMasa->prevEQ_e; + move16(); + + tmp = BASOP_Util_Divide3232_Scale( hMcMasa->prevMultiChEne_fx, L_add( hMcMasa->prevDownmixEne_fx, EPSILON_FX ), &scale ); + currEQ_e = add( scale, sub( hMcMasa->prevMultiChEne_e, hMcMasa->prevDownmixEne_e ) ); + currEQ_fx = Sqrt32( L_deposit_h( tmp ), &currEQ_e ); + + hMcMasa->prevEQ_fx = currEQ_fx; + move32(); + hMcMasa->prevEQ_e = currEQ_e; + move16(); + FOR( i = 0; i < input_frame; i++ ) + { + L_tmp = Mpy_32_32( L_deposit_h( hMcMasa->interpolator_fx[i] ), currEQ_fx ); + L_tmp1 = L_sub( 1073741824, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); + L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); + instEQ_fx = BASOP_Util_Add_Mant32Exp( L_tmp, currEQ_e, L_tmp1, add( prevEQ_e, 1 ), &instEQ_e ); + + FOR( j = 0; j < nchan_transport; j++ ) + { + data_fx[j][i] = Mpy_32_32( instEQ_fx, data_fx[j][i] ); + move32(); + move32(); + data_fx[j][i] = L_shl( data_fx[j][i], instEQ_e ); + } + } + + return; +} +#else /* Compute downmix */ static void ivas_mcmasa_dmx( MCMASA_ENC_HANDLE hMcMasa, @@ -1998,8 +3278,55 @@ static void ivas_mcmasa_dmx( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +/* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */ +static void compute_cov_mtx_fx( + Word32 sr[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Input matrix, real, s[ch][freq] */ + Word32 si[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Input matrix, imag, s[ch][freq] */ + const Word16 freq, /* i : Freq to process */ + const Word16 N, /* i : Number of channels */ + CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ + Word16 inp_exp /*Stores exponent for temp*/ +) +{ + Word16 i, j; + Word32 a, b, c, d; + Word32 temp; + Word16 norm_a, norm_b, norm_c, norm_d; + Word16 shift; + FOR( i = 0; i < N; i++ ) + { + a = sr[i][freq]; + move32(); + b = si[i][freq]; + move32(); + norm_a = norm_l( a ); + norm_b = norm_l( b ); + a = L_shl( a, norm_a ); /*inp_exp-norm_a*/ + b = L_shl( b, norm_b ); /*inp_exp-norm_b*/ + FOR( j = i; j < N; j++ ) + { + c = sr[j][freq]; + move32(); + d = si[j][freq]; + move32(); + norm_c = norm_l( c ); + norm_d = norm_l( d ); + c = L_shl( c, norm_c ); /*inp_exp-norm_c*/ + d = L_shl( d, norm_d ); /*inp_exp-norm_d*/ + temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), sub( shl( inp_exp, 1 ), add( norm_a, norm_c ) ), Mult_32_32( b, d ), sub( shl( inp_exp, 1 ), add( norm_b, norm_d ) ), &shift ); /*exp=inp_exp-norm_ab+inp_exp-norm_cd*/ + COVls->xr_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xr_fx[i][j], COVls->xr_e[i][j], temp, shift, &COVls->xr_e[i][j] ); + move32(); + temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( b, c ), sub( shl( inp_exp, 1 ), add( norm_b, norm_c ) ), L_negate( Mult_32_32( a, d ) ), sub( shl( inp_exp, 1 ), add( norm_a, norm_d ) ), &shift ); + COVls->xi_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xi_fx[i][j], COVls->xi_e[i][j], temp, shift, &COVls->xi_e[i][j] ); + move32(); + } + } - + return; +} +#else /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */ static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][DIRAC_NO_FB_BANDS_MAX], /* i : Input matrix, real, s[ch][freq] */ @@ -2027,8 +3354,8 @@ static void compute_cov_mtx( return; } - - +#endif +#ifndef IVAS_FLOAT_FIXED static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX], @@ -2066,8 +3393,138 @@ static void computeIntensityVector_enc( return; } +#else +static void computeIntensityVector_enc_fx( + const Word16 *band_grouping, + Word32 Cldfb_RealBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX], + Word32 Cldfb_ImagBuffer[FOA_CHANNELS][DIRAC_NO_FB_BANDS_MAX], + const Word16 enc_param_start_band, /* i : first band to process */ + const Word16 num_frequency_bands, + Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ) +{ + /* Reminder + * X = a + ib; Y = c + id + * X*Y = ac - bd + i(ad +bc) + */ + Word16 i, j; + Word32 real, img; + Word16 brange[2]; + + FOR( i = enc_param_start_band; i < enc_param_start_band + num_frequency_bands; i++ ) + { + brange[0] = band_grouping[i]; + move16(); + brange[1] = band_grouping[i + 1]; + move16(); + + intensity_real[0][i] = 0; + move32(); + intensity_real[1][i] = 0; + move32(); + intensity_real[2][i] = 0; + move32(); + + FOR( j = brange[0]; j < brange[1]; j++ ) + { + real = Cldfb_RealBuffer[0][j]; + move32(); + img = Cldfb_ImagBuffer[0][j]; + move32(); + /* Intensity is XYZ order, audio is WYZX order. */ + intensity_real[0][i] = L_add( intensity_real[0][i], L_add( Mpy_32_32( Cldfb_RealBuffer[3][j], real ), Mpy_32_32( Cldfb_ImagBuffer[3][j], img ) ) ); // output Q= 2* input_q -31 + move32(); + intensity_real[1][i] = L_add( intensity_real[1][i], L_add( Mpy_32_32( Cldfb_RealBuffer[1][j], real ), Mpy_32_32( Cldfb_ImagBuffer[1][j], img ) ) ); // output Q= 2* input_q -31 + move32(); + intensity_real[2][i] = L_add( intensity_real[2][i], L_add( Mpy_32_32( Cldfb_RealBuffer[2][j], real ), Mpy_32_32( Cldfb_ImagBuffer[2][j], img ) ) ); // output Q= 2* input_q -31 + move32(); + } + } + + return; +} +#endif +#ifdef IVAS_FLOAT_FIXED +static void computeVerticalDiffuseness_fx( + Word32 **buffer_intensity, /* i : Intensity vectors */ + const Word32 *buffer_energy, /* i : Energy */ + const int16_t averaging_length, /* i : Averaging length */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + Word32 *diffuseness, /* o : Estimated diffuseness */ + Word16 *buffer_intensity_q, + Word16 *buffer_energy_q ) +{ + Word32 intensity_slow[MASA_FREQUENCY_BANDS]; + Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS]; + Word32 energy_slow[MASA_FREQUENCY_BANDS]; + Word16 i, k; + Word32 tmp = 0; + move32(); + const Word32 *p_tmp_c; + Word16 intensity_slow_e[MASA_FREQUENCY_BANDS], energy_slow_e[MASA_FREQUENCY_BANDS]; + + /* Set variables to zero */ + set32_fx( intensity_slow, 0, MASA_FREQUENCY_BANDS ); + set32_fx( energy_slow, 0, MASA_FREQUENCY_BANDS ); + set16_fx( intensity_slow_e, 0, MASA_FREQUENCY_BANDS ); + set16_fx( energy_slow_e, 0, MASA_FREQUENCY_BANDS ); + + FOR( i = 0; i < averaging_length; ++i ) + { + /* Energy slow */ + p_tmp_c = buffer_energy + i_mult( i, num_freq_bands ); + FOR( k = 0; k < num_freq_bands; k++ ) + { + energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], *( p_tmp_c ), sub( 31, buffer_energy_q[i] ), &energy_slow_e[k] ); /*q=min_q*/ + move32(); + p_tmp_c++; + } + /* Intensity slow */ + FOR( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow[k] = BASOP_Util_Add_Mant32Exp( intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k], sub( 31, buffer_intensity_q[i] ), &intensity_slow_e[k] ); /*q=min_q*/ + move32(); + } + } + + /* Compute absolute value */ + FOR( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow_abs[k] = L_abs( intensity_slow[k] ); /*min_q*/ + move32(); + } + + /* Compute Diffuseness */ + FOR( i = 0; i < num_freq_bands; ++i ) + { + Word16 tmp_e1, tmp_e2; + tmp = BASOP_Util_Divide3232_Scale( intensity_slow_abs[i], L_add( energy_slow[i], EPSILON_FX_SMALL ), &tmp_e1 ); + tmp_e1 = add( tmp_e1, sub( intensity_slow_e[i], energy_slow_e[i] ) ); + tmp = BASOP_Util_Divide3232_Scale( L_sub( tmp, L_shr( VERTICAL_ENERGY_RATIO_OFFSET_FX, tmp_e1 ) ), L_sub( ONE_IN_Q15, VERTICAL_ENERGY_RATIO_OFFSET_FX ), &tmp_e2 ); /* Tuned to avoid effect due to ambience of vertically un-even setups */ + tmp_e2 = add( tmp_e2, tmp_e1 ); + tmp = L_sub( L_shl( 1, sub( 15, tmp_e2 ) ), tmp ); + IF( tmp < 0 ) + { + tmp = 0; + move32(); + } + ELSE IF( GE_32( tmp, L_shl( 1, sub( 15, tmp_e2 ) ) ) ) + { + tmp = ONE_IN_Q31; + move32(); + } + ELSE + { + tmp = L_shl( tmp, add( 16, tmp_e2 ) ); + } + diffuseness[i] = tmp; + move32(); + } + return; +} +#endif // IVAS_FLOAT_FIXED +#ifndef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * computeVerticalDiffuseness() * @@ -2126,8 +3583,79 @@ static void computeVerticalDiffuseness( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +static void computeEvenLayout_fx( + const Word32 *ls_azimuth, + Word32 *ls_azimuth_even, + const Word16 numChannels ) +{ + Word16 i; + Word16 j; + Word32 ls_azimuth_temp[MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS]; + Word16 ls_azimuth_order[MCMASA_MAX_ANA_CHANS]; + Word32 smallestAzimuth; + Word16 smallestAzimuthIndex; + Word32 lsSpacing; + UWord8 oddLayout; + Word32 startAzimuth; + Word16 numChannelsHalf; + + lsSpacing = L_shl( L_mult0( 360, div_s( 1, numChannels ) ), 6 ); /*Q.21*/ + oddLayout = (UWord8) s_and( numChannels, 1 ); + move16(); + numChannelsHalf = shr( numChannels, 1 ); + + Copy32( ls_azimuth, ls_azimuth_temp, numChannels ); + Scale_sig32( ls_azimuth_temp, numChannels, -1 ); /*Q.21*/ + FOR( i = 0; i < numChannels; i++ ) + { + smallestAzimuth = 1000 << 21; /*Q21*/ + move32(); + smallestAzimuthIndex = 0; + move16(); + FOR( j = 0; j < numChannels; j++ ) + { + IF( LT_32( ls_azimuth_temp[j], smallestAzimuth ) ) + { + smallestAzimuth = ls_azimuth_temp[j]; + move32(); + smallestAzimuthIndex = j; + move16(); + } + } + ls_azimuth_order[i] = smallestAzimuthIndex; + move32(); + ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); + move32(); + } + IF( oddLayout ) + { + startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, shl( numChannelsHalf, 1 ) ) ); /*Q.22*/ + } + ELSE + { + startAzimuth = W_extract_l( W_mult0_32_32( -lsSpacing, sub( shl( numChannelsHalf, 1 ), 1 ) ) ); /*Q.22*/ + } + + FOR( i = 0; i < numChannels; i++ ) + { + ls_azimuth_even_ordered[i] = W_extract_l( W_add( W_mult_32_16( lsSpacing, i ), startAzimuth ) ); /*Q.22*/ + move32(); + } + + FOR( i = 0; i < numChannels; i++ ) + { + ls_azimuth_even[ls_azimuth_order[i]] = L_shl( L_shr( L_add( ls_azimuth_even_ordered[i], ONE_IN_Q21 ), 22 ), 22 ); /*((a+2^21)/2^22)*2^22*/ + move32(); + } + return; +} +#endif // IVAS_FLOAT_FIXED +#ifndef IVAS_FLOAT_FIXED static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, @@ -2187,7 +3715,8 @@ static void computeEvenLayout( return; } - +#endif +#ifndef IVAS_FLOAT_FIXED static void computeLfeEnergy( MCMASA_ENC_HANDLE hMcMasa, float *data_f[], @@ -2307,3 +3836,146 @@ static void computeLfeEnergy( return; } +#else +static void computeLfeEnergy_fx( + MCMASA_ENC_HANDLE hMcMasa, + Word32 *data_fx[], + const Word16 input_frame, + Word16 q_inp ) +{ + Word16 l_ts; + Word16 block_m_idx; + Word16 mrange[2]; + Word16 separateChannelIndex; + Word16 lfeChannelIndex; + Word32 *pcm_in[1]; + Word16 inp_q = q_inp; + move16(); + + l_ts = idiv1616( input_frame, MDFT_NO_COL_MAX ); + separateChannelIndex = hMcMasa->separateChannelIndex; + move16(); + lfeChannelIndex = LFE_CHANNEL; + move16(); + + IF( hMcMasa->separateChannelEnabled ) + { + Copy32( data_fx[lfeChannelIndex], &( hMcMasa->delay_buffer_lfe[0][hMcMasa->num_samples_delay_comp - hMcMasa->offset_comp] ), hMcMasa->offset_comp ); + Copy32( data_fx[separateChannelIndex], &( hMcMasa->delay_buffer_lfe[1][hMcMasa->num_samples_delay_comp - hMcMasa->offset_comp] ), hMcMasa->offset_comp ); + } + ELSE + { + pcm_in[0] = &data_fx[lfeChannelIndex][0]; + } + + /* Reset variables */ + set32_fx( hMcMasa->lfeLfEne, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set16_fx( hMcMasa->lfeLfEne_e, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set32_fx( hMcMasa->totalLfEne, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set16_fx( hMcMasa->totalLfEne_e, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + + /* Compute low-frequency energies */ + IF( hMcMasa->separateChannelEnabled ) /* Using low-pass filter */ + { + Word32 lowpassCoef; + Word16 lowPassSignal_q; + Word16 i, j; + Word32 delayedInputSignal[2][L_FRAME48k]; + Word32 lowPassSignal[2][L_FRAME48k]; + + Copy32( &( hMcMasa->delay_buffer_lfe[0][0] ), &( delayedInputSignal[0][0] ), hMcMasa->num_slots_delay_comp * l_ts ); + Copy32( data_fx[lfeChannelIndex] + hMcMasa->offset_comp, &( delayedInputSignal[0][hMcMasa->num_slots_delay_comp * l_ts] ), ( MDFT_NO_COL_MAX - hMcMasa->num_slots_delay_comp ) * l_ts ); + Copy32( &( hMcMasa->delay_buffer_lfe[1][0] ), &( delayedInputSignal[1][0] ), hMcMasa->num_slots_delay_comp * l_ts ); + Copy32( data_fx[separateChannelIndex] + hMcMasa->offset_comp, &( delayedInputSignal[1][hMcMasa->num_slots_delay_comp * l_ts] ), ( MDFT_NO_COL_MAX - hMcMasa->num_slots_delay_comp ) * l_ts ); + + lowpassCoef = L_shl( div_w( 1, (Word32) hMcMasa->ringBufferSize ), Q7 ); // Q.38 + + FOR( i = 0; i < input_frame; i++ ) + { + FOR( j = 0; j < 2; j++ ) + { + Word32 temp1, temp2; + temp1 = Mpy_32_32( delayedInputSignal[j][i], lowpassCoef ); // Q(q_inp+7-gb) + temp2 = Mpy_32_32( hMcMasa->lfeAnaRingBuffer[j][hMcMasa->ringBufferPointer], lowpassCoef ); // Q(q_inp+7-gb) + hMcMasa->lowpassSum[j] = L_add( hMcMasa->lowpassSum[j], L_sub( temp1, temp2 ) ); + move32(); + lowPassSignal[j][i] = hMcMasa->lowpassSum[j]; + move32(); + hMcMasa->lfeAnaRingBuffer[j][hMcMasa->ringBufferPointer] = delayedInputSignal[j][i]; + move32(); + } + + hMcMasa->ringBufferPointer--; + IF( hMcMasa->ringBufferPointer < 0 ) + { + hMcMasa->ringBufferPointer = sub( hMcMasa->ringBufferSize, 1 ); + } + } + lowPassSignal_q = add( q_inp, Q7 ); + FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + mrange[0] = i_mult( hMcMasa->block_grouping[block_m_idx], l_ts ); + move16(); + mrange[1] = i_mult( hMcMasa->block_grouping[block_m_idx + 1], l_ts ); + move16(); + + FOR( i = mrange[0]; i < mrange[1]; i++ ) + { + hMcMasa->lfeLfEne[block_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->lfeLfEne[block_m_idx], hMcMasa->lfeLfEne_e[block_m_idx], Mpy_32_32( lowPassSignal[0][i], lowPassSignal[0][i] ), sub( 31, sub( shl( lowPassSignal_q, 1 ), 31 ) ), &hMcMasa->lfeLfEne_e[block_m_idx] ); + move32(); + hMcMasa->totalLfEne[block_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->totalLfEne[block_m_idx], hMcMasa->totalLfEne_e[block_m_idx], Mpy_32_32( lowPassSignal[1][i], lowPassSignal[1][i] ), sub( 31, sub( shl( lowPassSignal_q, 1 ), 31 ) ), &hMcMasa->totalLfEne_e[block_m_idx] ); + move32(); + } + hMcMasa->totalLfEne[block_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->totalLfEne[block_m_idx], hMcMasa->totalLfEne_e[block_m_idx], hMcMasa->lfeLfEne[block_m_idx], hMcMasa->lfeLfEne_e[block_m_idx], &hMcMasa->totalLfEne_e[block_m_idx] ); + move32(); + } + } + ELSE /* Using CLDFB */ + { + Word16 ts; + Word16 i; + Word32 Chnl_RealBuffer[2][DIRAC_NO_FB_BANDS_MAX]; + Word32 Chnl_ImagBuffer[2][DIRAC_NO_FB_BANDS_MAX]; + Word32 *p_Chnl_RealBuffer[2]; + Word32 *p_Chnl_ImagBuffer[2]; + + p_Chnl_RealBuffer[0] = &Chnl_RealBuffer[0][0]; + p_Chnl_RealBuffer[1] = &Chnl_RealBuffer[1][0]; + p_Chnl_ImagBuffer[0] = &Chnl_ImagBuffer[0][0]; + p_Chnl_ImagBuffer[1] = &Chnl_ImagBuffer[1][0]; + + + FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + mrange[0] = hMcMasa->block_grouping[block_m_idx]; + move16(); + mrange[1] = hMcMasa->block_grouping[block_m_idx + 1]; + move16(); + + FOR( ts = mrange[0]; ts < mrange[1]; ts++ ) + { + ivas_fb_mixer_get_windowed_fr_fx( hMcMasa->hFbMixerLfe, pcm_in, p_Chnl_RealBuffer, p_Chnl_ImagBuffer, l_ts, l_ts, hMcMasa->hFbMixerLfe->fb_cfg->num_in_chans, 0 ); + + ivas_fb_mixer_update_prior_input_fx( hMcMasa->hFbMixerLfe, pcm_in, l_ts, hMcMasa->hFbMixerLfe->fb_cfg->num_in_chans ); + + pcm_in[0] += l_ts; + + /* Compute low frequency energy for LFE, for other channels it is computed in ivas_chnl_param_est_enc() */ + FOR( i = 0; i < CLDFB_TO_MDFT_FAC; i++ ) + { + hMcMasa->lfeLfEne[block_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->lfeLfEne[block_m_idx], hMcMasa->lfeLfEne_e[block_m_idx], L_add( Mpy_32_32( Chnl_RealBuffer[0][i], Chnl_RealBuffer[0][i] ), Mpy_32_32( Chnl_ImagBuffer[0][i], Chnl_ImagBuffer[0][i] ) ), sub( 31, sub( shl( inp_q, 1 ), 31 ) ), &hMcMasa->lfeLfEne_e[block_m_idx] ); + move32(); + } + } + } + } + + IF( hMcMasa->separateChannelEnabled ) + { + Copy32( data_fx[lfeChannelIndex] + ( input_frame - hMcMasa->num_samples_delay_comp + hMcMasa->offset_comp ), &( hMcMasa->delay_buffer_lfe[0][0] ), ( hMcMasa->num_samples_delay_comp - hMcMasa->offset_comp ) ); + Copy32( data_fx[separateChannelIndex] + ( input_frame - hMcMasa->num_samples_delay_comp + hMcMasa->offset_comp ), &( hMcMasa->delay_buffer_lfe[1][0] ), ( hMcMasa->num_samples_delay_comp - hMcMasa->offset_comp ) ); + } + + return; +} +#endif diff --git a/lib_enc/ivas_mct_core_enc.c b/lib_enc/ivas_mct_core_enc.c index 788eee3babaf9cbf6920859ec40480013d4cc154..a5b543d854f1a1c952f3632c1edd3bd8b83c9f7c 100644 --- a/lib_enc/ivas_mct_core_enc.c +++ b/lib_enc/ivas_mct_core_enc.c @@ -43,6 +43,7 @@ #include "prot_fx_enc.h" #include "ivas_prot_fx.h" #include "prot_fx.h" +#include #endif @@ -738,7 +739,7 @@ void ivas_mct_core_enc( return; } #else -void ivas_mct_core_enc( +void ivas_mct_core_enc_fx( const IVAS_FORMAT ivas_format, /* i : IVAS format */ MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */ @@ -752,17 +753,7 @@ void ivas_mct_core_enc( Word16 ch, ch_core, nSubframes, L_subframeTCX; Word16 i, cpe_id, n, nAvailBits; Word16 nCPE; - float *orig_spectrum[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ - float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k]; - float powerSpecMsInv_long[MCT_MAX_CHANNELS][L_FRAME48k]; /* MS inv power spectrum, also inverse MDST spectrum */ - float *powerSpecMsInv[MCT_MAX_CHANNELS][2]; - float *inv_mdst_spectrum[MCT_MAX_CHANNELS][2]; - float *inv_spectrum[MCT_MAX_CHANNELS][2]; - float *mdst_spectrum[MCT_MAX_CHANNELS][2] = { NULL }; - float inv_spectrum_long[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ -#if 0 - Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ -#endif + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k]; Word32 mdst_fx; Word32 powerSpecMsInv_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* MS inv power spectrum, also inverse MDST spectrum */ @@ -773,13 +764,14 @@ void ivas_mct_core_enc( Word32 inv_spectrum_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ Word16 total_side_bits; Word16 chBitRatios[MCT_MAX_CHANNELS]; - Word16 q_powSpec[MCT_MAX_CHANNELS], q_spec, tmp_s; + Word16 q_powSpec[MCT_MAX_CHANNELS], q_spec, q_origSpec, tmp_s; Word16 tmp_q_powSpec[L_FRAME48k], tmp_q_powSpecInv[L_FRAME48k], *tmp_q_psi[2]; Word64 W_tmp; Encoder_State *sts[MCT_MAX_CHANNELS]; Encoder_State *st; Word16 sp_aud_decision0[MCT_MAX_CHANNELS]; BSTR_ENC_HANDLE hBstr; + Word16 q_spectrum; push_wmops( "mct_encoding" ); @@ -793,7 +785,7 @@ void ivas_mct_core_enc( nCPE = shr( nChannels, 1 ); // nChannels / CPE_CHANNELS /*in case of odd number of channels*/ - if ( NE_16( ( nCPE * CPE_CHANNELS ), nChannels ) ) + IF( NE_16( ( nCPE * CPE_CHANNELS ), nChannels ) ) { nCPE = add( nCPE, 1 ); } @@ -807,13 +799,6 @@ void ivas_mct_core_enc( #endif // MSAN_FIX FOR( ch = 0; ch < nChannels; ch++ ) { -#if 1 // Float initialization to be removed - inv_mdst_spectrum[ch][0] = powerSpecMsInv[ch][0] = powerSpecMsInv_long[ch]; - inv_mdst_spectrum[ch][1] = powerSpecMsInv[ch][1] = powerSpecMsInv_long[ch] + N_TCX10_MAX; - inv_spectrum[ch][0] = inv_spectrum_long[ch]; - inv_spectrum[ch][1] = inv_spectrum_long[ch] + N_TCX10_MAX; -#endif - set32_fx( inv_spectrum_long_fx[ch], 0, L_FRAME48k ); set32_fx( powerSpec_fx[ch], 0, L_FRAME48k ); set32_fx( powerSpecMsInv_long_fx[ch], 0, L_FRAME48k ); @@ -840,18 +825,11 @@ void ivas_mct_core_enc( i = add( i, 1 ); CONTINUE; } -#if 1 // Float initialization to be removed - mdst_spectrum[i][0] = hMCT->p_mdst_spectrum_long[cpe_id][ch]; - mdst_spectrum[i][1] = hMCT->p_mdst_spectrum_long[cpe_id][ch] + N_TCX10_MAX; - orig_spectrum[i][0] = hMCT->p_orig_spectrum_long[cpe_id][ch]; - orig_spectrum[i][1] = hMCT->p_orig_spectrum_long[cpe_id][ch] + N_TCX10_MAX; -#endif + mdst_spectrum_fx[i][0] = hMCT->p_mdst_spectrum_long_fx[cpe_id][ch]; mdst_spectrum_fx[i][1] = hMCT->p_mdst_spectrum_long_fx[cpe_id][ch] + N_TCX10_MAX; -#if 0 orig_spectrum_fx[i][0] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch]; orig_spectrum_fx[i][1] = hMCT->p_orig_spectrum_long_fx[cpe_id][ch] + N_TCX10_MAX; -#endif sp_aud_decision0[i] = hCPE[cpe_id]->hCoreCoder[0]->sp_aud_decision0; move16(); @@ -864,7 +842,8 @@ void ivas_mct_core_enc( i = add( i, 1 ); } } - + q_origSpec = hMCT->q_orig_spectrum_long_fx; + move16(); hBstr = sts[0]->hBstr; FOR( ch = 0; ch < shr( hMCT->nchan_out_woLFE, 1 ); ch++ ) @@ -1132,106 +1111,86 @@ void ivas_mct_core_enc( ComputeSpectrumNoiseMeasure_fx( powerSpec_fx[ch], st->hTcxEnc->L_frameTCX, st->hTcxEnc->nmStartLine, NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), st->hTcxEnc->memQuantZeros, st->hTcxEnc->L_frameTCX ); } -#if 1 // Float initialization to be removed - st->hTcxEnc->measuredBwRatio_flt = 1.f; /* No bandwidth limit for the noise filling */ -#endif st->hTcxEnc->measuredBwRatio = ONE_IN_Q14; /* No bandwidth limit for the noise filling, Q14 */ + move16(); } -#if 1 // Fixed to float conversions, to be removed - Word16 length; - q_spec = 31; - move16(); - for ( ch = 0; ch < nChannels; ch++ ) - { - if ( sts[ch]->hTcxEnc->spectrum[0] ) - { - q_spec = 31 - sts[ch]->hTcxEnc->spectrum_e[0]; - } - length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); - if ( sts[ch]->last_core == ACELP_CORE ) - { - length += length / 4; - } - for ( Word16 k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) - { - if ( sts[ch]->hTcxEnc->spectrum[0] ) - { - fixedToFloat_arrL32( sts[ch]->hTcxEnc->spectrum_fx[k], sts[ch]->hTcxEnc->spectrum[k], q_spec, length ); - fixedToFloat_arrL32( inv_spectrum_fx[ch][k], inv_spectrum[ch][k], q_spec, length ); - } - if ( mdst_spectrum[ch][0] ) - { - fixedToFloat_arrL32( inv_mdst_spectrum_fx[ch][k], inv_mdst_spectrum[ch][k], q_spec, length ); - fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_spec, length ); - } - } - - fixedToFloat_arrL( powerSpecMsInv_fx[ch][0], powerSpecMsInv[ch][0], q_powSpec[ch], L_FRAME48k ); - fixedToFloat_arrL( powerSpec_fx[ch], powerSpec[ch], q_powSpec[ch], sts[ch]->hTcxEnc->L_frameTCX ); - } -#endif // 1 - - if ( sts[0]->igf ) + IF( sts[0]->igf ) { - if ( hMCT->currBlockDataCnt > 0 ) + IF( hMCT->currBlockDataCnt > 0 ) { - mctStereoIGF_enc( hMCT, sts, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); + mctStereoIGF_enc_fx( hMCT, sts, orig_spectrum_fx, q_origSpec, powerSpec_fx, powerSpecMsInv_fx, q_powSpec, inv_spectrum_fx, sp_aud_decision0 ); } - else + ELSE { - for ( ch = 0; ch < nChannels; ch++ ) + FOR( ch = 0; ch < nChannels; ch++ ) { st = sts[ch]; /* update the pointer to the buffer of indices of the second channel */ - if ( ch > 0 ) + IF( ch > 0 ) { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } - if ( - sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; + } + // nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + // L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + nSubframes = NB_DIV; + move16(); + L_subframeTCX = shr( st->hTcxEnc->L_frameTCX, 1 ); + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + L_subframeTCX = st->hTcxEnc->L_frameTCX; + move16(); + move16(); } - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; - L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; - if ( st->igf ) + IF( st->igf ) { - for ( n = 0; n < nSubframes; n++ ) + FOR( n = 0; n < nSubframes; n++ ) { - ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] ); + + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powSpec[ch], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + + st->hIGFEnc->spec_be_igf_e = sub( 31, q_origSpec ); + st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum ); + move16(); + move16(); } } } } /*write IGF data to bitstream*/ - for ( ch = 0; ch < nChannels; ch++ ) + FOR( ch = 0; ch < nChannels; ch++ ) { st = sts[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; } enc_prm_igf_mdct( st, hBstr ); } } /* correct side bits per channel*/ - for ( ch = 0; ch < nChannels; ch++ ) + FOR( ch = 0; ch < nChannels; ch++ ) { st = sts[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; } - st->side_bits_frame_channel -= NBBITS_MCT_RATIO; /* Subtract estimated stereo bits */ - total_side_bits += st->side_bits_frame_channel; + st->side_bits_frame_channel = sub( st->side_bits_frame_channel, NBBITS_MCT_RATIO ); /* Subtract estimated stereo bits */ + move16(); + total_side_bits = add( total_side_bits, st->side_bits_frame_channel ); } /*--------------------------------------------------------------* @@ -1316,7 +1275,6 @@ void ivas_mct_core_enc( } } - pop_wmops(); return; diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index 484abca22ffb48cbe788b4f647b26239a1e1308f..d30e12f1c3b44936357b7d6efee9412bd1fd49c4 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -42,6 +42,7 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" #include "ivas_prot_fx.h" +#include "rom_com.h" #endif @@ -58,6 +59,7 @@ static ivas_error ivas_mc_enc_reconfig( Encoder_Struct *st_ivas, const int16_t l * Set hMCT handle parameters *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void set_mct_enc_params( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ const int32_t ivas_total_brate, /* i : IVAS total bitrate */ @@ -98,6 +100,53 @@ static void set_mct_enc_params( return; } +#else +static void set_mct_enc_params( + MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + const IVAS_FORMAT ivas_format, /* i : IVAS_format */ + const UWord16 b_nchan_change /* i : flag indicating different channel count */ +) +{ + Word16 n; + + IF( b_nchan_change ) + { + hMCT->currBlockDataCnt = 0; + move16(); + + /*Initialize bits required to signal channel-pair index*/ + hMCT->bitsChannelPairIndex = s_max( 1, add( sub( 14, norm_s( sub( shr( i_mult( hMCT->nchan_out_woLFE, sub( hMCT->nchan_out_woLFE, 1 ) ), 1 ), 1 ) ) ), 1 ) ); + + set16_fx( hMCT->lowE_ch, 0, MCT_MAX_CHANNELS ); + +#if 1 // TODO: To be removed later + for ( n = 0; n < MCT_MAX_CHANNELS; n++ ) + { + set_f( hMCT->lastxCorrMatrix[n], 0, MCT_MAX_CHANNELS ); + } +#endif + FOR( n = 0; n < MCT_MAX_CHANNELS; n++ ) + { + set32_fx( hMCT->lastxCorrMatrix_fx[n], 0, MCT_MAX_CHANNELS ); + } + hMCT->lastxCorrMatrix_e = 0; + move16(); + } + + hMCT->hbr_mct = 0; + move16(); + + test(); + IF( EQ_16( ivas_format, SBA_FORMAT ) && GE_32( ivas_total_brate, IVAS_256k ) ) + { + hMCT->hbr_mct = 1; + move16(); + } + + return; +} +#endif /*-------------------------------------------------------------------* * map_input_to_cpe_channels() @@ -160,6 +209,61 @@ static void map_input_to_cpe_channels( return; } +static void map_input_to_cpe_channels_ivas_fx( + const Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + Word32 *pdata[MAX_INPUT_CHANNELS], /* o : mapped input pointers */ + Word32 *data[MCT_MAX_CHANNELS] /* i : input channel data Qx */ +) +{ + Word16 i, n; + Word16 nchan_transport; + + nchan_transport = st_ivas->nchan_transport; + test(); + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + nchan_transport = add( nchan_transport, st_ivas->hEncoderConfig->nchan_ism ); + } + i = 0; + move16(); + + FOR( n = 0; n < LFE_CHANNEL - 1; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + test(); + test(); + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MC_FORMAT ) && ( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) || EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) ) + { + FOR( n = LFE_CHANNEL + 1; n < nchan_transport; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + pdata[i] = data[LFE_CHANNEL - 1]; + } + ELSE + { + FOR( ; n < nchan_transport; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + } + + /* odd channel CPE*/ + test(); + test(); + test(); + IF( ( LT_16( nchan_transport, i_mult( st_ivas->nCPE, CPE_CHANNELS ) ) ) || ( ( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) || EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) && LT_16( st_ivas->hMCT->nchan_out_woLFE, i_mult( st_ivas->nCPE, CPE_CHANNELS ) ) ) ) + { + pdata[st_ivas->nCPE * CPE_CHANNELS - 1] = NULL; + } + + return; +} + /*-------------------------------------------------------------------* * ivas_mct_enc() @@ -336,6 +440,8 @@ ivas_error ivas_mct_enc( set_zero( mdst_spectrum_long[cpe_id][n], L_FRAME48k ); #endif #endif + set32_fx( orig_spectrum_long_fx[cpe_id][n], 0, L_FRAME48k ); + set32_fx( mdst_spectrum_long_fx[cpe_id][n], 0, L_FRAME48k ); hMCT->p_mdst_spectrum_long_fx[cpe_id][n] = mdst_spectrum_long_fx[cpe_id][n]; hMCT->p_orig_spectrum_long_fx[cpe_id][n] = orig_spectrum_long_fx[cpe_id][n]; @@ -391,7 +497,45 @@ ivas_error ivas_mct_enc( switch_bw = set_bw_mct_fx( st_ivas->hCPE, st_ivas->nCPE ); /*for MC and MCT remove pointer to LFE input that has been processed separately */ +#ifndef IVAS_FLOAT_FIXED + map_input_to_cpe_channels( st_ivas, pdata, data ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 *pdata_fx[MAX_INPUT_CHANNELS]; + Word32 data_fx_tmp[MCT_MAX_CHANNELS][960]; + Word32 *data_fx[MCT_MAX_CHANNELS]; + Word16 nchan_transport; + for ( int i = 0; i < MAX_INPUT_CHANNELS; i++ ) + { + pdata_fx[i] = NULL; + pdata[i] = NULL; + } + Word16 len = (Word16) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + nchan_transport = st_ivas->nchan_transport; + if ( st_ivas->hEncoderConfig->ivas_format == SBA_ISM_FORMAT && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + nchan_transport += st_ivas->hEncoderConfig->nchan_ism; + } + + for ( int i = 0; i < nchan_transport; i++ ) + { + data_fx[i] = data_fx_tmp[i]; + floatToFixed_arrL( data[i], data_fx[i], Q11, len ); + } map_input_to_cpe_channels( st_ivas, pdata, data ); +#endif + map_input_to_cpe_channels_ivas_fx( st_ivas, pdata_fx, data_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < MCT_MAX_CHANNELS; i++ ) + { + if ( pdata_fx[i] == NULL ) + { + continue; + } + fixedToFloat_arrL( pdata_fx[i], pdata[i], Q11, len ); + } +#endif +#endif /* pre-processing */ FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) @@ -402,8 +546,9 @@ ivas_error ivas_mct_enc( } } -#if 1 // Float to Fixed, to be removed +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Float to Fixed, to be removed Word16 q_spec = Q31; + Word16 q_origSpec = Q31; Word16 length, ch, nCPE; nCPE = ( hMCT->nchan_out_woLFE % 2 ) == 0 ? ( hMCT->nchan_out_woLFE / 2 ) : ( hMCT->nchan_out_woLFE / 2 ) + 1; @@ -431,9 +576,13 @@ ivas_error ivas_mct_enc( q_spec = s_min( q_spec, Q_factor_arrL( &hMCT->p_mdst_spectrum_long[cpe_id][ch][k * N_TCX10_MAX], length ) - 1 ); } } + if ( hMCT->p_orig_spectrum_long[cpe_id][ch] ) + { + q_origSpec = s_min( q_origSpec, Q_factor_arrL( hMCT->p_orig_spectrum_long[cpe_id][ch], L_FRAME48k ) - 1 ); + } } } - + hMCT->q_orig_spectrum_long_fx = q_origSpec; for ( cpe_id = 0; cpe_id < nCPE; cpe_id++ ) { for ( ch = 0; ch < CPE_CHANNELS; ch++ ) @@ -452,13 +601,18 @@ ivas_error ivas_mct_enc( if ( st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum[0] ) { floatToFixed_arrL32( st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum[k], st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum_fx[k], q_spec, length ); - st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum_e[k] = sub( Q31, q_spec ); + st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum_e[0] = sub( Q31, q_spec ); + st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->hTcxEnc->spectrum_e[1] = sub( Q31, q_spec ); } if ( hMCT->p_mdst_spectrum_long[cpe_id][ch] ) { floatToFixed_arrL32( &hMCT->p_mdst_spectrum_long[cpe_id][ch][k * N_TCX10_MAX], &hMCT->p_mdst_spectrum_long_fx[cpe_id][ch][k * N_TCX10_MAX], q_spec, length ); } } + if ( hMCT->p_orig_spectrum_long[cpe_id][ch] ) + { + floatToFixed_arrL32( hMCT->p_orig_spectrum_long[cpe_id][ch], hMCT->p_orig_spectrum_long_fx[cpe_id][ch], hMCT->q_orig_spectrum_long_fx, L_FRAME48k ); + } } } @@ -469,10 +623,195 @@ ivas_error ivas_mct_enc( hMCT->hBlockData[pair]->hStereoMdct->hItd->itd_fx[1] = float_to_fix( hMCT->hBlockData[pair]->hStereoMdct->hItd->itd[1], Q23 ); } } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Encoder_State *sts_tmp[MCT_MAX_CHANNELS]; + Encoder_State *st; + Word16 i; + IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS]; + nCPE = shr( hMCT->nchan_out_woLFE, 1 ); // nChannels / CPE_CHANNELS + + /*in case of odd number of channels*/ + IF( NE_16( ( nCPE * CPE_CHANNELS ), hMCT->nchan_out_woLFE ) ) + { + nCPE = add( nCPE, 1 ); + } + FOR( ( cpe_id = 0, i = 0 ); cpe_id < nCPE; cpe_id++ ) + { + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts_tmp[i] = st_ivas->hCPE[cpe_id]->hCoreCoder[ch]; + IF( EQ_32( st_ivas->hCPE[cpe_id]->hCoreCoder[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + i = add( i, 1 ); + CONTINUE; + } + i++; + } + } + FOR( int b = 0; b < hMCT->nchan_out_woLFE; b++ ) + { + st = sts_tmp[b]; + + if ( st->hIGFEnc ) + { + ch = 0; + hIGFEnc[ch] = st->hIGFEnc; + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 igfGridIdx; + IF( st->last_core == ACELP_CORE && EQ_16( st->core, TCX_20_CORE ) ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + ELSE IF( EQ_16( st->core, TCX_20_CORE ) ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + ELSE + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + hPrivateData = &hIGFEnc[ch]->igfData; + hGrid = &hPrivateData->igfInfo.grid[(Word16) igfGridIdx]; + if ( hIGFEnc[ch] ) + { + hIGFEnc[ch]->tns_predictionGain = float_to_fix16( hIGFEnc[ch]->tns_predictionGain_flt, Q23 ); + } + + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + FOR( int k = 0; k < IGF_MAX_TILES; k++ ) + { + hPrivateData->prevSFM_FIR[k] = float_to_fix( hPrivateData->prevSFM_FIR_flt[k], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[k] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[k], 13 ); /*2Q13*/ + FOR( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[k][j] = float_to_fix16( hPrivateData->igfPastSFM[k][j], 13 ); + } + } + floatToFixed_arr16( &hGrid->whiteningThreshold_flt[0][0], &hGrid->whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + } +#endif #endif // 1 /* joint MCT encoding */ - ivas_mct_core_enc( ivas_format, hMCT, st_ivas->hCPE, hMCT->nchan_out_woLFE, ivas_total_brate, switch_bw, ( ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0, st_ivas->hEncoderConfig->sba_order ); + ivas_mct_core_enc_fx( ivas_format, hMCT, st_ivas->hCPE, hMCT->nchan_out_woLFE, ivas_total_brate, switch_bw, ( ivas_format == MC_FORMAT && ( st_ivas->mc_mode == MC_MODE_MCT || st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) ) ? (int16_t) st_ivas->hLFE->lfe_bits : 0, st_ivas->hEncoderConfig->sba_order ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_spec = 31; + move16(); + for ( ch = 0; ch < hMCT->nchan_out_woLFE; ch++ ) + { + sts_tmp[ch]->hTcxEnc->measuredBwRatio_flt = 1.f; /* No bandwidth limit for the noise filling */ + + if ( sts_tmp[ch]->hTcxEnc->spectrum[0] ) + { + q_spec = 31 - sts_tmp[ch]->hTcxEnc->spectrum_e[0]; + } + length = sts_tmp[ch]->hTcxEnc->L_frameTCX / ( ( sts_tmp[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + if ( sts_tmp[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + for ( Word16 k = 0; k <= ( ( sts_tmp[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + if ( sts_tmp[ch]->hTcxEnc->spectrum[0] ) + { + fixedToFloat_arrL32( sts_tmp[ch]->hTcxEnc->spectrum_fx[k], sts_tmp[ch]->hTcxEnc->spectrum[k], q_spec, length ); + } + } + } + for ( int b = 0; b < hMCT->nchan_out_woLFE; b++ ) + { + st = sts_tmp[b]; + if ( st->hIGFEnc ) + { + ch = 0; + hIGFEnc[ch] = st->hIGFEnc; + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hIGFEnc[ch]->igfData; + + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + for ( int k = 0; k < IGF_MAX_TILES; k++ ) + { + hPrivateData->prevSFM_FIR_flt[k] = fixedToFloat( hPrivateData->prevSFM_FIR[k], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[k] = fixedToFloat( hPrivateData->prevSFM_IIR[k], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[k][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[k][j], 13 ); + } + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); + me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, N_MAX_TCX - IGF_START_MN ); + } + } +#endif /* Spectrum quantization and coding */ FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) @@ -483,16 +822,119 @@ ivas_error ivas_mct_enc( { hCPE->hCoreCoder[0]->hBstr->ind_list = st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->ind_list + st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->nb_ind_tot; } - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Encoder_State /**st,*/ **sts; + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + st->hTcxEnc->tcx_target_bits_fac = float_to_fix16( st->hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif ivas_mdct_quant_coder_fx( hCPE, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + st->hTcxEnc->tcx_target_bits_fac_flt = me2f_16( st->hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); + } +#endif /* update input samples buffer (as done in ivas_cpe_enc() for other than MCT coding) */ FOR( n = 0; n < CPE_CHANNELS; n++ ) { mvr2r( hCPE->hCoreCoder[n]->input, hCPE->hCoreCoder[n]->old_input_signal, input_frame ); /* common encoder updates */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st = hCPE->hCoreCoder[n]; + f2me_buf_16( st->buf_speech_enc_pe_flt, st->buf_speech_enc_pe, &st->exp_buf_speech_enc_pe, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_speech_enc_flt, st->buf_speech_enc, &st->exp_buf_speech_enc, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_synth_flt, st->buf_synth, &st->exp_buf_synth, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + f2me_buf_16( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, &st->exp_buf_wspeech_enc, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + f2me_buf_16( st->hTcxEnc->buf_speech_ltp_flt, st->hTcxEnc->buf_speech_ltp, &st->hTcxEnc->exp_buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, 15 ); + } +#endif + + updt_enc_common_ivas_fx( st ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf_16( st->buf_speech_enc_pe, st->exp_buf_speech_enc_pe, st->buf_speech_enc_pe_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_speech_enc, st->exp_buf_speech_enc, st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_synth, st->exp_buf_synth, st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + me2f_buf_16( st->buf_wspeech_enc, st->exp_buf_wspeech_enc, st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + me2f_buf_16( st->hTcxEnc->buf_speech_ltp, st->hTcxEnc->exp_buf_speech_ltp, st->hTcxEnc->buf_speech_ltp_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) + { + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + IF( st->hTcxEnc != NULL ) + { + IF( st->element_mode != IVAS_CPE_MDCT ) + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + } + } + + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem_flt = fixedToFloat( st->hTcxEnc->tcxltp_norm_corr_mem, 31 ); + } + + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac_flt = PREEMPH_FAC_FLT; + st->gamma_flt = GAMMA1_FLT; + } + ELSE + { + st->preemph_fac_flt = PREEMPH_FAC_16k_FLT; + st->gamma_flt = GAMMA16k_FLT; + } + } + + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + } + } +#endif +#else updt_enc_common( hCPE->hCoreCoder[n] ); +#endif } } @@ -507,6 +949,7 @@ ivas_error ivas_mct_enc( * Create, allocate and initialize IVAS encoder MCT handle *-------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED ivas_error create_mct_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) @@ -625,43 +1068,180 @@ ivas_error create_mct_enc( return IVAS_ERR_OK; } - - -/*------------------------------------------------------------------------- - * mct_enc_reconfigure() - * - * Reconfigure IVAS encoder MCT handle - *-------------------------------------------------------------------------*/ - -ivas_error mct_enc_reconfigure( - Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ - const uint16_t b_nchan_change /* i : flag indicating different channel count */ +#else +ivas_error create_mct_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ ) { MCT_ENC_HANDLE hMCT; - Encoder_State *st; - int16_t n, cpe_id, max_blocks; - int32_t ivas_total_brate, cp_bitrate; + Word16 n; + Word32 cp_bitrate; + Word16 max_blocks; + Word16 cpe_id; IVAS_FORMAT ivas_format; - ivas_error error; - - error = IVAS_ERR_OK; + Word32 ivas_total_brate; - hMCT = st_ivas->hMCT; ivas_format = st_ivas->hEncoderConfig->ivas_format; + move16(); ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + move32(); + + /*-----------------------------------------------------------------* + * Allocate MCT handle + *-----------------------------------------------------------------*/ + + IF( ( hMCT = (MCT_ENC_HANDLE) malloc( sizeof( MCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT\n" ) ); + } /*-----------------------------------------------------------------* * Allocate and initialize MCT BlockData handles *-----------------------------------------------------------------*/ - if ( b_nchan_change ) + /* Determine active channels */ + test(); + test(); + test(); + test(); + IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCT ) ) { - /* Determine active channels */ - if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) - { - hMCT->nchan_out_woLFE = st_ivas->hEncoderConfig->nchan_inp - 1; /* LFE channel is coded separately */ - } + hMCT->nchan_out_woLFE = sub( st_ivas->hEncoderConfig->nchan_inp, 1 ); /* LFE channel is coded separately */ + move16(); + } + ELSE IF( EQ_16( ivas_format, SBA_FORMAT ) || EQ_16( ivas_format, SBA_ISM_FORMAT ) ) + { + hMCT->nchan_out_woLFE = ivas_get_sba_num_TCs( ivas_total_brate, st_ivas->sba_analysis_order ); + move16(); + + test(); + IF( EQ_16( ivas_format, SBA_ISM_FORMAT ) && EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + hMCT->nchan_out_woLFE = add( hMCT->nchan_out_woLFE, st_ivas->hEncoderConfig->nchan_ism ); + move16(); + } + } + ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) + { + hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup ); + move16(); + } + ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + { + hMCT->nchan_out_woLFE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS - 1; + move16(); + } + + Word32 L_tmp; + iDiv_and_mod_32( L_shl( ivas_total_brate, 1 ), hMCT->nchan_out_woLFE, &cp_bitrate, &L_tmp, 0 ); + // cp_bitrate = ivas_total_brate / hMCT->nchan_out_woLFE * CPE_CHANNELS; + IF( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + iDiv_and_mod_32( L_shl( ivas_total_brate, 1 ), st_ivas->nchan_transport, &cp_bitrate, &L_tmp, 0 ); + // cp_bitrate = ivas_total_brate / st_ivas->nchan_transport * CPE_CHANNELS; + } + + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + } + + /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ + IF( hMCT->nchan_out_woLFE % 2 ) + { + st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + move16(); + } + + /*Initialize MCT block data */ + max_blocks = shr( hMCT->nchan_out_woLFE, 1 ); // hMCT->nchan_out_woLFE / CPE_CHANNELS + + FOR( n = 0; n < max_blocks; n++ ) + { + assert( st_ivas->hEncoderConfig->element_mode_init == IVAS_CPE_MDCT && "MCT is not supported for other stereo modes" ); + + IF( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); + } + + /*Initialize all parameters to zero*/ + hMCT->hBlockData[n]->isActive = 0; + move16(); + hMCT->hBlockData[n]->ch1 = 0; + move16(); + hMCT->hBlockData[n]->ch2 = 0; + move16(); + + /*-----------------------------------------------------------------* + * MDCT stereo initialization + *-----------------------------------------------------------------*/ + + IF( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } + + initMdctStereoEncData_fx( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, st_ivas->hEncoderConfig->max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, st_ivas->hCPE[0]->hCoreCoder[0]->igf ? st_ivas->hCPE[0]->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid : NULL, 1 ); + } + + FOR( ; n < MCT_MAX_BLOCKS; n++ ) + { + hMCT->hBlockData[n] = NULL; + } + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + set_mct_enc_params( hMCT, ivas_total_brate, ivas_format, 1 ); + + st_ivas->hMCT = hMCT; + + return IVAS_ERR_OK; +} +#endif + + +/*------------------------------------------------------------------------- + * mct_enc_reconfigure() + * + * Reconfigure IVAS encoder MCT handle + *-------------------------------------------------------------------------*/ + +#ifndef IVAS_FLOAT_FIXED +ivas_error mct_enc_reconfigure( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const uint16_t b_nchan_change /* i : flag indicating different channel count */ +) +{ + MCT_ENC_HANDLE hMCT; + Encoder_State *st; + int16_t n, cpe_id, max_blocks; + int32_t ivas_total_brate, cp_bitrate; + IVAS_FORMAT ivas_format; + ivas_error error; + + error = IVAS_ERR_OK; + + hMCT = st_ivas->hMCT; + ivas_format = st_ivas->hEncoderConfig->ivas_format; + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + + /*-----------------------------------------------------------------* + * Allocate and initialize MCT BlockData handles + *-----------------------------------------------------------------*/ + + if ( b_nchan_change ) + { + /* Determine active channels */ + if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT ) + { + hMCT->nchan_out_woLFE = st_ivas->hEncoderConfig->nchan_inp - 1; /* LFE channel is coded separately */ + } else if ( ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) { hMCT->nchan_out_woLFE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS - 1; @@ -700,7 +1280,36 @@ ivas_error mct_enc_reconfigure( { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } +#ifdef IVAS_FLOAT_FIXED + /* set correct nominal bitrates and igf config already here, otherwise we + * run into a number of problems; only do it when the bitrate changes */ + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st = st_ivas->hCPE[cpe_id]->hCoreCoder[n]; + + st->total_brate = st_ivas->hCPE[cpe_id]->element_brate; + move32(); + IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_32( st_ivas->hCPE[cpe_id]->element_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + move16(); + st->igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->bwidth, st->rf_mode ); + move16(); + + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, st->igf, 1, st_ivas->hCPE[cpe_id]->element_brate, st->bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } + } + } +#else /* set correct nominal bitrates and igf config already here, otherwise we * run into a number of problems; only do it when the bitrate changes */ if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) @@ -726,7 +1335,7 @@ ivas_error mct_enc_reconfigure( } } } - +#endif /* Initialize MCT block data */ max_blocks = hMCT->nchan_out_woLFE / CPE_CHANNELS; @@ -792,6 +1401,186 @@ ivas_error mct_enc_reconfigure( return error; } +#else +ivas_error mct_enc_reconfigure( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const UWord16 b_nchan_change /* i : flag indicating different channel count */ +) +{ + MCT_ENC_HANDLE hMCT; + Encoder_State *st; + Word16 n, cpe_id, max_blocks; + Word32 ivas_total_brate, cp_bitrate; + IVAS_FORMAT ivas_format; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + hMCT = st_ivas->hMCT; + ivas_format = st_ivas->hEncoderConfig->ivas_format; + move16(); + ivas_total_brate = st_ivas->hEncoderConfig->ivas_total_brate; + move32(); + + /*-----------------------------------------------------------------* + * Allocate and initialize MCT BlockData handles + *-----------------------------------------------------------------*/ + + IF( b_nchan_change ) + { + test(); + test(); + test(); + test(); + /* Determine active channels */ + IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_MCT ) ) + { + hMCT->nchan_out_woLFE = sub( st_ivas->hEncoderConfig->nchan_inp, 1 ); /* LFE channel is coded separately */ + } + ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + { + hMCT->nchan_out_woLFE = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS - 1; + } + ELSE IF( EQ_16( ivas_format, MC_FORMAT ) && EQ_16( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) + { + hMCT->nchan_out_woLFE = ivas_param_mc_getNumTransportChannels( ivas_total_brate, st_ivas->hEncoderConfig->mc_input_setup ); + } + ELSE IF( EQ_16( ivas_format, SBA_FORMAT ) || EQ_16( ivas_format, SBA_ISM_FORMAT ) ) + { + hMCT->nchan_out_woLFE = st_ivas->nchan_transport; + move16(); + IF( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + hMCT->nchan_out_woLFE = add( hMCT->nchan_out_woLFE, st_ivas->hEncoderConfig->nchan_ism ); + move16(); + } + } + } + + Word32 L_tmp; + iDiv_and_mod_32( L_shl( ivas_total_brate, 1 ), hMCT->nchan_out_woLFE, &cp_bitrate, &L_tmp, 0 ); + // cp_bitrate = ivas_total_brate / hMCT->nchan_out_woLFE * CPE_CHANNELS; + IF( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + iDiv_and_mod_32( L_shl( ivas_total_brate, 1 ), st_ivas->nchan_transport, &cp_bitrate, &L_tmp, 0 ); + // cp_bitrate = ivas_total_brate / st_ivas->nchan_transport * CPE_CHANNELS; + } + + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + st_ivas->hCPE[cpe_id]->element_brate = cp_bitrate; + move32(); + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st_ivas->hCPE[cpe_id]->hCoreCoder[n]->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + move16(); + } + } + + /* in case we have an uneven number of transport channels, indicate last channel ID as inactive */ + IF( hMCT->nchan_out_woLFE % 2 ) + { + st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + move16(); + } + + /* set correct nominal bitrates and igf config already here, otherwise we + * run into a number of problems; only do it when the bitrate changes */ + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st = st_ivas->hCPE[cpe_id]->hCoreCoder[n]; + + st->total_brate = st_ivas->hCPE[cpe_id]->element_brate; + move32(); + + IF( NE_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_32( st_ivas->hCPE[cpe_id]->element_brate, 42949673 ) /* 1/50 in Q31*/ ); + move16(); + st->igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->bwidth, st->rf_mode ); + move16(); + + IF( ( error = IGF_Reconfig( &st->hIGFEnc, st->igf, 1, st_ivas->hCPE[cpe_id]->element_brate, st->bwidth, st->element_mode, st->rf_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + } + } + + /* Initialize MCT block data */ + max_blocks = shr( hMCT->nchan_out_woLFE, 1 ); // hMCT->nchan_out_woLFE / CPE_CHANNELS + + FOR( n = 0; n < max_blocks; n++ ) + { + UWord16 mem_init = 0; + move16(); + assert( st_ivas->hEncoderConfig->element_mode_init == IVAS_CPE_MDCT && "MCT is not supported for other stereo modes" ); + + IF( b_nchan_change ) + { + IF( hMCT->hBlockData[n] == NULL ) + { + mem_init = 1; + move16(); + IF( ( hMCT->hBlockData[n] = (MCT_BLOCK_DATA_HANDLE) malloc( sizeof( MCT_BLOCK_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MCT block data structure\n" ) ); + } + + /*Initialize all parameters to zero*/ + hMCT->hBlockData[n]->isActive = 0; + move16(); + hMCT->hBlockData[n]->ch1 = 0; + move16(); + hMCT->hBlockData[n]->ch2 = 0; + move16(); + + /*-----------------------------------------------------------------* + * MDCT stereo initialization + *-----------------------------------------------------------------*/ + + IF( ( hMCT->hBlockData[n]->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } + } + } + + initMdctStereoEncData_fx( hMCT->hBlockData[n]->hStereoMdct, ivas_format, IVAS_CPE_MDCT, cp_bitrate, st_ivas->hEncoderConfig->max_bwidth, st_ivas->hCPE[0]->hCoreCoder[0]->igf, st_ivas->hCPE[0]->hCoreCoder[0]->igf ? st_ivas->hCPE[0]->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid : NULL, mem_init ); + } + + FOR( ; n < MCT_MAX_BLOCKS; n++ ) + { + /* deallocate no longer needed blocks */ + IF( hMCT->hBlockData[n] != NULL ) + { + IF( hMCT->hBlockData[n]->hStereoMdct != NULL ) + { + free( hMCT->hBlockData[n]->hStereoMdct ); + hMCT->hBlockData[n]->hStereoMdct = NULL; + } + + free( hMCT->hBlockData[n] ); + hMCT->hBlockData[n] = NULL; + } + } + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + set_mct_enc_params( hMCT, ivas_total_brate, ivas_format, b_nchan_change ); + + return error; +} +#endif /*------------------------------------------------------------------------- @@ -800,6 +1589,7 @@ ivas_error mct_enc_reconfigure( * Close MCT *-------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void ivas_mct_enc_close( MCT_ENC_HANDLE *hMCT /* i/o: MCT encoder structure */ ) @@ -833,6 +1623,42 @@ void ivas_mct_enc_close( return; } +#else +void ivas_mct_enc_close( + MCT_ENC_HANDLE *hMCT /* i/o: MCT encoder structure */ +) +{ + Word16 n, maxBlocks; + + test(); + IF( hMCT == NULL || *hMCT == NULL ) + { + return; + } + + maxBlocks = shr( ( *hMCT )->nchan_out_woLFE, 1 ); + + FOR( n = 0; n < maxBlocks; n++ ) + { + IF( ( *hMCT )->hBlockData[n] != NULL ) + { + IF( ( *hMCT )->hBlockData[n]->hStereoMdct != NULL ) + { + free( ( *hMCT )->hBlockData[n]->hStereoMdct ); + ( *hMCT )->hBlockData[n]->hStereoMdct = NULL; + } + + free( ( *hMCT )->hBlockData[n] ); + ( *hMCT )->hBlockData[n] = NULL; + } + } + + free( ( *hMCT ) ); + ( *hMCT ) = NULL; + + return; +} +#endif /*------------------------------------------------------------------------- @@ -934,8 +1760,12 @@ static ivas_error ivas_mc_enc_reconfig( ivas_mc_paramupmix_enc_close( &( st_ivas->hMCParamUpmix ), st_ivas->hEncoderConfig->input_Fs ); +#ifdef IVAS_FLOAT_FIXED /* De-allocate McMasa-related handles */ + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#else ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#endif ivas_masa_enc_close( &( st_ivas->hMasa ) ); @@ -975,8 +1805,11 @@ static ivas_error ivas_mc_enc_reconfig( ivas_param_mc_enc_close( &st_ivas->hParamMC, st_ivas->hEncoderConfig->input_Fs ); /* De-allocate McMasa-related handles */ +#ifdef IVAS_FLOAT_FIXED + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#else ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); - +#endif ivas_masa_enc_close( &( st_ivas->hMasa ) ); ivas_qmetadata_close( &st_ivas->hQMetaData ); @@ -999,8 +1832,11 @@ static ivas_error ivas_mc_enc_reconfig( } /* De-allocate McMasa-related handles */ +#ifdef IVAS_FLOAT_FIXED + ivas_mcmasa_enc_close_fx( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); +#else ivas_mcmasa_enc_close( &( st_ivas->hMcMasa ), st_ivas->hEncoderConfig->input_Fs ); - +#endif if ( st_ivas->hMasa != NULL ) { ivas_masa_enc_close( &( st_ivas->hMasa ) ); @@ -1048,8 +1884,11 @@ static ivas_error ivas_mc_enc_reconfig( { return error; } - +#ifdef IVAS_FLOAT_FIXED + if ( NE_32( ( error = ivas_mcmasa_enc_open_fx( st_ivas ) ), IVAS_ERR_OK ) ) +#else if ( ( error = ivas_mcmasa_enc_open( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1057,7 +1896,11 @@ static ivas_error ivas_mc_enc_reconfig( else { /* reconfigure McMASA instance */ +#ifdef IVAS_FLOAT_FIXED + if ( NE_32( ( error = ivas_mcmasa_enc_reconfig_fx( st_ivas ) ), IVAS_ERR_OK ) ) +#else if ( ( error = ivas_mcmasa_enc_reconfig( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1163,7 +2006,7 @@ static ivas_error ivas_mc_enc_reconfig( new_brate_CPE = ( st_ivas->hEncoderConfig->ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS; } - if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, new_brate_SCE, new_brate_CPE, last_mc_mode ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, new_brate_SCE, new_brate_CPE, last_mc_mode ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_enc/ivas_mct_enc_mct.c b/lib_enc/ivas_mct_enc_mct.c index a0c1435b9305a158bf22ffb401f71250f9af2e1b..0cfad1d3b97040585f7a7316d71033c5b9d434d1 100644 --- a/lib_enc/ivas_mct_enc_mct.c +++ b/lib_enc/ivas_mct_enc_mct.c @@ -38,6 +38,9 @@ #include "ivas_prot_fx.h" #include "prot.h" #include "prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif #include "wmc_auto.h" #include @@ -1601,236 +1604,182 @@ void mctStereoIGF_enc_fx( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ + Word16 q_origSpec, /* i : Q for MDCT spectrum */ Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ + Word16 q_powerSpec[MCT_MAX_CHANNELS], /* i : Q for powSpec_fx and powSpecMsInv_fx*/ Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ -#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED - float *orig_spectrum[MCT_MAX_CHANNELS][2], /* i : MDCT spectrum for ITF */ - float powerSpec[MCT_MAX_CHANNELS][L_FRAME48k], /* i/o: MDCT^2 + MDST^2 spectrum,or estimate*/ - float *powerSpecMsInv[MCT_MAX_CHANNELS][NB_DIV], /* i : same as above but for inverse spect.*/ - float *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ -#endif // IVAS_FLOAT_FIXED - const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ ) { -#ifdef IVAS_FLOAT_FIXED Word32 *p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; Word32 *p_inv_spectrum_fx[CPE_CHANNELS][NB_DIV]; Word32 *p_orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; Word32 *p_powerSpec_fx[NB_DIV]; -#endif // IVAS_FLOAT_FIXED - int16_t b, nSubframes, L_subframeTCX; - int16_t p_ch[2], n, ch, ch1, ch2; + Word16 b, nSubframes, L_subframeTCX; + Word16 p_ch[2], n, ch, ch1, ch2, s = 31; + Word16 q_pS_ch[2]; Encoder_State *p_st[NB_DIV]; Encoder_State *st; - float *p_powerSpecMsInv[CPE_CHANNELS][NB_DIV]; - float *p_orig_spectrum[CPE_CHANNELS][NB_DIV]; - float *p_powerSpec[NB_DIV]; - int16_t singleChEle[MCT_MAX_CHANNELS]; + Word16 singleChEle[MCT_MAX_CHANNELS]; + Word16 q_spectrum; L_subframeTCX = 0; /* to avoid compilation warning */ - set_s( singleChEle, 1, hMCT->nchan_out_woLFE ); + move16(); + set16_fx( singleChEle, 1, hMCT->nchan_out_woLFE ); - for ( b = 0; b < hMCT->currBlockDataCnt; b++ ) + FOR( b = 0; b < hMCT->currBlockDataCnt; b++ ) { ch1 = hMCT->hBlockData[b]->ch1; ch2 = hMCT->hBlockData[b]->ch2; + move16(); + move16(); p_ch[0] = ch1; p_ch[1] = ch2; + move16(); + move16(); singleChEle[hMCT->hBlockData[b]->ch1] = 0; singleChEle[hMCT->hBlockData[b]->ch2] = 0; + move16(); + move16(); /* point to encoder states of actual channels to write block pair bits */ p_st[0] = sts[ch1]; p_st[1] = sts[ch2]; - if ( ch1 > 0 ) + IF( ch1 > 0 ) { sts[ch1]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } - if ( ch2 > 0 ) + IF( ch2 > 0 ) { sts[ch2]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } -#if 1 p_powerSpec_fx[0] = powerSpec_fx[ch1]; p_powerSpec_fx[1] = powerSpec_fx[ch2]; -#endif - p_powerSpec[0] = powerSpec[ch1]; - p_powerSpec[1] = powerSpec[ch2]; /* Band-wise M/S for MDST */ - nSubframes = p_st[0]->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; - for ( n = 0; n < nSubframes; n++ ) + nSubframes = NB_DIV; + move16(); + if ( EQ_16( p_st[0]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + + FOR( n = 0; n < nSubframes; n++ ) { -#if 1 - p_orig_spectrum[0][n] = orig_spectrum[ch1][n]; - p_orig_spectrum[1][n] = orig_spectrum[ch2][n]; - p_powerSpecMsInv[0][n] = powerSpecMsInv[ch1][n]; - p_powerSpecMsInv[1][n] = powerSpecMsInv[ch2][n]; -#endif p_orig_spectrum_fx[0][n] = orig_spectrum_fx[ch1][n]; p_orig_spectrum_fx[1][n] = orig_spectrum_fx[ch2][n]; p_powerSpecMsInv_fx[0][n] = powerSpecMsInv_fx[ch1][n]; p_powerSpecMsInv_fx[1][n] = powerSpecMsInv_fx[ch2][n]; p_inv_spectrum_fx[0][n] = inv_spectrum_fx[ch1][n]; p_inv_spectrum_fx[1][n] = inv_spectrum_fx[ch2][n]; - if ( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n] != hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] || - hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n] == SMDCT_BW_MS ) - { + q_pS_ch[0] = q_powerSpec[ch1]; + q_pS_ch[1] = q_powerSpec[ch2]; + move16(); + move16(); -#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED - Word16 p_orig_spectrum_e[2]; - IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS]; - hIGFEnc[0] = p_st[0]->hIGFEnc; - hIGFEnc[1] = p_st[1]->hIGFEnc; + test(); + IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] ) || + EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) ) + { - Word16 igfGridIdx; - IF( p_st[0]->last_core == ACELP_CORE && EQ_16( p_st[0]->core, TCX_20_CORE ) ) - { - igfGridIdx = IGF_GRID_LB_TRAN; - } - ELSE IF( EQ_16( p_st[0]->core, TCX_20_CORE ) ) - { - igfGridIdx = IGF_GRID_LB_NORM; - } - ELSE + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - /* It is short block */ - igfGridIdx = IGF_GRID_LB_SHORT; + s = s_min( s, sub( 31, p_st[ch]->hTcxEnc->spectrum_e[n] ) ); + s = s_min( s, q_pS_ch[ch] ); } - f2me_buf( p_orig_spectrum[0][n], p_orig_spectrum_fx[0][n], &p_orig_spectrum_e[0], hIGFEnc[0]->infoStopLine ); - f2me_buf( p_orig_spectrum[1][n], p_orig_spectrum_fx[1][n], &p_orig_spectrum_e[1], hIGFEnc[1]->infoStopLine ); FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; - H_IGF_GRID hGrid; - Word16 *swb_offset; - hPrivateData = &hIGFEnc[ch]->igfData; - hGrid = &hPrivateData->igfInfo.grid[(Word16) igfGridIdx]; - swb_offset = hGrid->swb_offset; - hIGFEnc[ch]->tns_predictionGain = float_to_fix16( hIGFEnc[ch]->tns_predictionGain_flt, Q23 ); - p_st[ch]->hTcxEnc->spectrum_e[n] = 31 - Q_factor_arrL( p_st[ch]->hTcxEnc->spectrum[n], hGrid->infoGranuleLen ); - p_st[ch]->hTcxEnc->spectrum_e[n] = s_max( p_st[ch]->hTcxEnc->spectrum_e[n], 31 - Q_factor_arrL( &p_powerSpec[ch][0], hGrid->infoGranuleLen ) ); - p_st[ch]->hTcxEnc->spectrum_e[n] = s_max( p_st[ch]->hTcxEnc->spectrum_e[n], 31 - Q_factor_arrL( inv_spectrum[ch][n], swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ) ); - p_st[ch]->hTcxEnc->spectrum_e[n] = s_max( p_st[ch]->hTcxEnc->spectrum_e[n], 31 - Q_factor_arrL( p_powerSpecMsInv[ch][0], swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ) ); - floatToFixed_arr32( p_st[ch]->hTcxEnc->spectrum[n], p_st[ch]->hTcxEnc->spectrum_fx[n], 31 - p_st[ch]->hTcxEnc->spectrum_e[n], hGrid->infoGranuleLen ); - floatToFixed_arr32( &p_powerSpec[ch][0], &p_powerSpec_fx[ch][0], 31 - p_st[ch]->hTcxEnc->spectrum_e[n], hGrid->infoGranuleLen ); - floatToFixed_arr32( inv_spectrum[ch][n], inv_spectrum_fx[ch][n], 31 - p_st[ch]->hTcxEnc->spectrum_e[n], swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); - floatToFixed_arr32( p_powerSpecMsInv[ch][0], p_powerSpecMsInv_fx[ch][0], 31 - p_st[ch]->hTcxEnc->spectrum_e[n], swb_offset[hGrid->sfbWrap[hGrid->nTiles]] ); - float max_sb = 0; - float max_tb = 0; - Word16 max_sb_fx = 0; - Word16 max_tb_fx = 0; - FOR( Word16 sfb = 0; sfb < 23; sfb++ ) - { - f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); - max_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_tb ); - max_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_tb ); - max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); - max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); - max_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_sb ); - max_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_sb ); - f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); - f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); - hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); - hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); - hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); - hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); - hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); - } - FOR( int i = 0; i < IGF_MAX_TILES; i++ ) - { - hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ - hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ - FOR( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) - { - hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); - } - } - floatToFixed_arr16( &hGrid->whiteningThreshold_flt[0][0], &hGrid->whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); + scale_sig32( p_st[ch]->hTcxEnc->spectrum_fx[0], N_MAX, sub( s, sub( 31, p_st[ch]->hTcxEnc->spectrum_e[0] ) ) ); + scale_sig32( p_inv_spectrum_fx[ch][0], L_FRAME48k, sub( s, sub( 31, p_st[ch]->hTcxEnc->spectrum_e[0] ) ) ); + p_st[ch]->hTcxEnc->spectrum_e[0] = sub( 31, s ); + p_st[ch]->hTcxEnc->spectrum_e[1] = sub( 31, s ); + move16(); + move16(); + + scale_sig32( p_powerSpecMsInv_fx[ch][0], L_FRAME48k, sub( s, q_pS_ch[ch] ) ); + scale_sig32( &p_powerSpec_fx[ch][0], sts[ch]->hTcxEnc->L_frameTCX, sub( s, q_pS_ch[ch] ) ); + q_powerSpec[ch1] = s; + q_powerSpec[ch2] = s; + move16(); + move16(); } -#endif /**********************************flt to fix ends here*******************************************************/ - hIGFEnc[0]->spec_be_igf_e = p_orig_spectrum_e[0]; - hIGFEnc[1]->spec_be_igf_e = p_orig_spectrum_e[1]; + + p_st[0]->hIGFEnc->spec_be_igf_e = sub( 31, q_origSpec ); + p_st[1]->hIGFEnc->spec_be_igf_e = sub( 31, q_origSpec ); + move16(); + move16(); + ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, p_powerSpec_fx, p_powerSpecMsInv_fx, p_inv_spectrum_fx, n, sp_aud_decision0[ch1], p_st[0]->total_brate ); -#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED - FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) - { - IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; - H_IGF_GRID hGrid; - hPrivateData = &hIGFEnc[ch]->igfData; - hGrid = &hPrivateData->igfInfo.grid[(Word16) igfGridIdx]; - me2f_buf( p_st[ch]->hTcxEnc->spectrum_fx[n], p_st[ch]->hTcxEnc->spectrum_e[n], p_st[ch]->hTcxEnc->spectrum[n], hGrid->infoGranuleLen ); - me2f_buf( &p_powerSpec_fx[ch][0], p_st[ch]->hTcxEnc->spectrum_e[n], &p_powerSpec[ch][0], hGrid->infoGranuleLen ); - for ( Word16 sfb = 0; sfb < 23; sfb++ ) - { - hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); - hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); - hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); - hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); - } - for ( int i = 0; i < IGF_MAX_TILES; i++ ) - { - hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ - hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ - for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) - { - hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); - } - } - } -#endif /**********************************fix to flt ends here*******************************************************/ } - else + ELSE { - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = p_st[ch]; - L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + L_subframeTCX = shr( st->hTcxEnc->L_frameTCX, 1 ); + if ( EQ_16( nSubframes, 1 ) ) + { + L_subframeTCX = st->hTcxEnc->L_frameTCX; + move16(); + } - ProcessIGF( st, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[p_ch[ch]][n], &powerSpec[p_ch[ch]][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch1], 0 ); + q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] ); + + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[p_ch[ch]][n], &q_spectrum, &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], &q_powerSpec[p_ch[ch]], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + + st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum ); + move16(); } } } } /* channel elements that are coded separately detected */ - if ( sum_s( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 ) + IF( sum16_fx( singleChEle, ( hMCT->nchan_out_woLFE ) ) != 0 ) { - for ( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ ) + FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ ) { - if ( singleChEle[ch] ) + IF( singleChEle[ch] ) { st = sts[ch]; - if ( - st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { - continue; + CONTINUE; } - if ( ch > 0 ) + IF( ch > 0 ) { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } - nSubframes = st->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; - for ( n = 0; n < nSubframes; n++ ) + nSubframes = NB_DIV; + move16(); + if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) { - ProcessIGF( st, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + nSubframes = 1; + move16(); + } + + FOR( n = 0; n < nSubframes; n++ ) + { + q_spectrum = sub( 31, st->hTcxEnc->spectrum_e[n] ); + + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec[ch], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); + + st->hTcxEnc->spectrum_e[n] = sub( 31, q_spectrum ); + move16(); } } } @@ -1838,7 +1787,7 @@ void mctStereoIGF_enc_fx( return; } -#endif +#else void mctStereoIGF_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ @@ -1950,3 +1899,4 @@ void mctStereoIGF_enc( return; } +#endif diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index 9bf39785e2234827e1c2f5621d0bb83ab1ad4172..e148508b89374e0dd646a0c2abfc0732023c21be 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -44,6 +44,7 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx_enc.h" #include "prot_fx.h" +#include "ivas_prot_fx.h" #endif @@ -428,6 +429,77 @@ static int16_t kernel_switch_detect( #endif +#ifdef IVAS_FLOAT_FIXED +static void kernel_switch_trafo_fx( + const Word32 *x, /* Input (Q_in) */ + Word32 *y, /* Output (Q_in - 1) */ + const Word16 l, + const Word16 m, + const Word16 r, + const UWord16 kernelType ) +{ + Word16 i; + Word32 inputBuffer[N_MAX]; + Word16 tmp, exp_tmp; + Word32 factor; + + /* Init */ + FOR( i = 0; i < m / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 + i] = L_negate( x[l + m / 2 - 1 - i] ); // Q_in + move32(); + } + + IF( GE_32( kernelType, MDCT_II ) ) + { + FOR( i = 0; i < l / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 + m / 2 + i] = L_sub( L_negate( x[i] ), x[l - 1 - i] ); // Q_in + move32(); + } + } + ELSE + { + FOR( i = 0; i < l / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 + m / 2 + i] = L_sub( x[i], x[l - 1 - i] ); // Q_in + move32(); + } + } + + FOR( i = 0; i < m / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 - 1 - i] = L_negate( x[l + m / 2 + i] ); // Q_in + move32(); + } + + IF( UL_and( kernelType, 1 ) ) + { + FOR( i = 0; i < r / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 - 1 - m / 2 - i] = L_add( L_negate( x[l + m + i] ), x[l + m + r - 1 - i] ); // Q_in + move32(); + } + } + ELSE + { + FOR( i = 0; i < r / 2; i++ ) + { + inputBuffer[m / 2 + r / 2 - 1 - m / 2 - i] = L_negate( L_add( x[l + m + i], x[l + m + r - 1 - i] ) ); // Q_in + move32(); + } + } + + edxt_fx( inputBuffer, y, add( shr( l, 1 ), add( m, shr( r, 1 ) ) ), kernelType, FALSE ); // Q_in + + tmp = BASOP_Util_Divide1616_Scale( NORM_MDCT_FACTOR, add( shr( l, 1 ), add( m, shr( r, 1 ) ) ), &exp_tmp ); + tmp = Sqrt16( tmp, &exp_tmp ); + factor = L_shl( L_deposit_h( tmp ), sub( exp_tmp, 1 ) ); // Q30 + v_multc_fixed( y, factor, y, add( shr( l, 1 ), add( m, shr( r, 1 ) ) ) ); // (Q_in, Q30) -> Q_in - 1 + + return; +} +#else static void kernel_switch_trafo( const float *x, float *y, @@ -468,8 +540,237 @@ static void kernel_switch_trafo( return; } +#endif + + +#ifdef IVAS_FLOAT_FIXED +static void kernel_switch_update_transforms_fx( + Word32 *sigR, /* i/o: MDCT samples of the given channel (*q_sig) */ + Word32 *sigI, /* i/o: MDST samples of the given channel (*q_sig) */ + Word16 *q_sig, /* i/o: Common Q of MDCT and MDST samples of the given channel */ + const Word16 tcxTransType, /* i : TCX transform type, cf also above */ + TCX_CONFIG_HANDLE hTcxCfg, /* i : TCX configuration handle, pointer */ + const Word16 bwidthSwCnt, /* i : bandwidth switching counter in st */ + const UWord16 kernelType, /* i : TCX transform kernel type (0 - 3) */ + Word16 *tcxTimeSignal, /* i : hTcxEnc->new_speech_TCX buf in st */ + const Word16 *speech_TCX, /* i : hTcxEnc->speech_TCX buffer in st */ + Word32 *windowedTimeSignal, /* i/o: windowed input and scratch buffer (*q_windowedTimeSignal) */ + Word16 *q_windowedTimeSignal, /* i/o: Q of windowed input and scratch buffer */ + const Word16 L_subframe /* i : transform length (number of bins) */ +) +{ + Word16 s, nSubframes; + + s = L_subframe; + move16(); + IF( EQ_16( tcxTransType, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + } + + IF( kernelType == MDCT_IV ) /* no updates required here! */ + { + return; + } + + IF( EQ_32( kernelType, MDST_IV ) ) /* swap real and imag. parts */ + { + FOR( s = L_subframe - 1; s >= 0; s-- ) + { + const Word32 sigTemp = L_negate( sigR[s] ); + + sigR[s] = sigI[s]; + move32(); + sigI[s] = sigTemp; + move32(); + } + return; + } + + /* MDCT/MDST-II as real part, keep imag. part for speedup */ + test(); + IF( EQ_16( tcxTransType, TCX_20 ) && NE_16( hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) + { + Word16 n, q_com; + Word16 windowedTimeSignal_16[2 + L_FRAME48k]; + Word16 tmp, exp_tmp; + Word32 factor; + + n = extract_l( Mpy_32_32( s, 603979776 /* N_ZERO_MDCT_NS / FRAME_SIZE_NS in Q31 */ ) ); + Scale_sig( &tcxTimeSignal[n - s], shl( s, 1 ), -Q1 ); // Q0 -> Q-1 + wtda_ext_fx( tcxTimeSignal, windowedTimeSignal_16, extract_l( windowedTimeSignal[0] ), extract_l( windowedTimeSignal[1] ), s, kernelType ); // Q-1 + Scale_sig( &tcxTimeSignal[n - s], shl( s, 1 ), Q1 ); // Q-1 -> Q0 + + Copy_Scale_sig_16_32_no_sat( windowedTimeSignal_16, windowedTimeSignal, s, Q16 ); // Q15 + scale_sig32( windowedTimeSignal, s, -Q8 /* guard bits */ ); // Q7 + edxt_fx( windowedTimeSignal, sigR, s, kernelType, FALSE ); + + tmp = BASOP_Util_Divide1616_Scale( NORM_MDCT_FACTOR, s, &exp_tmp ); + tmp = Sqrt16( tmp, &exp_tmp ); + factor = L_shl( L_deposit_h( tmp ), sub( exp_tmp, Q1 ) ); // Q30 + v_multc_fixed( sigR, factor, sigR, s ); // (Q7, Q30) -> Q6 + + q_com = L_norm_arr( sigR, s ); + q_com = s_min( add( q_com, Q6 ), *q_sig ); + scale_sig32( sigR, s, sub( q_com, Q6 ) ); // q_com + scale_sig32( sigI, s, sub( q_com, *q_sig ) ); // q_com + *q_sig = q_com; + move16(); + } + ELSE /* 2 TCX5 subframes or 1 TCX10 or 1 transitory TCX20 */ + { + const Word16 minWindowLen = sub( hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word16 i, leftOverlap = 0, rightOverlap = 0; + PWord16 const *left_win; + PWord16 const *right_win; + move16(); + move16(); + + tcx_get_windows( hTcxCfg, extract_l( windowedTimeSignal[0] ), extract_l( windowedTimeSignal[1] ), &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + test(); + test(); + test(); + IF( speech_TCX != NULL && NE_16( tcxTransType, TCX_20 ) && windowedTimeSignal[0] == FULL_OVERLAP && GT_16( sub( s, leftOverlap ), minWindowLen ) ) + { + Word16 tmp = shr( hTcxCfg->tcx_mdct_window_min_lengthFB, 1 ); + Word32 L_tmp; + IF( GE_32( kernelType, MDCT_II ) ) + { + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( speech_TCX[-1 - i], hTcxCfg->tcx_aldo_window_1_FB[leftOverlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( *q_windowedTimeSignal, Q16 ) ); // *q_windowedTimeSignal + windowedTimeSignal[2 + leftOverlap + i] = L_add( windowedTimeSignal[2 + leftOverlap + i], L_tmp ); // *q_windowedTimeSignal + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( speech_TCX[-1 - i], hTcxCfg->tcx_aldo_window_1_FB[leftOverlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( *q_windowedTimeSignal, Q16 ) ); // *q_windowedTimeSignal + windowedTimeSignal[2 + leftOverlap + i] = L_add( windowedTimeSignal[2 + leftOverlap + i], L_tmp ); // *q_windowedTimeSignal + move32(); + } + } + ELSE + { + FOR( i = minWindowLen; i >= tmp; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( negate( speech_TCX[-1 - i] ), hTcxCfg->tcx_aldo_window_1_FB[leftOverlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i].v.im ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( *q_windowedTimeSignal, Q16 ) ); // *q_windowedTimeSignal + windowedTimeSignal[2 + leftOverlap + i] = L_add( windowedTimeSignal[2 + leftOverlap + i], L_tmp ); // *q_windowedTimeSignal + move32(); + } + FOR( i = tmp - 1; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + L_tmp = L_mult( negate( speech_TCX[-1 - i] ), hTcxCfg->tcx_aldo_window_1_FB[leftOverlap / 2 + minWindowLen - i] ); // (Q0, Q15) -> Q16 + L_tmp = Mpy_32_16_1( L_tmp, hTcxCfg->tcx_mdct_window_minimumFB[i].v.re ); // (Q16, Q15) -> Q16 + L_tmp = L_shl( L_tmp, sub( *q_windowedTimeSignal, Q16 ) ); // *q_windowedTimeSignal + windowedTimeSignal[2 + leftOverlap + i] = L_add( windowedTimeSignal[2 + leftOverlap + i], L_tmp ); // *q_windowedTimeSignal + move32(); + } + } + } + + IF( EQ_16( tcxTransType, TCX_5 ) ) + { + Word16 tcx5Win[N_TCX10_MAX / 2 + L_MDCT_OVLP_MAX]; /* temporary buffer for TCX5 windowing */ + Word32 tcx5Win_32[N_TCX10_MAX / 2 + L_MDCT_OVLP_MAX]; /* temporary buffer for TCX5 windowing */ + Word16 windowedTimeSignal_16[2 + L_FRAME48k]; + Word16 q_shift, q_com; + + assert( L_subframe == nSubframes * hTcxCfg->tcx5SizeFB ); + + /* Outer left folding */ + IF( GE_32( kernelType, MDCT_II ) ) + { + FOR( i = 0; i < leftOverlap / 2; i++ ) + { + windowedTimeSignal[2 + leftOverlap / 2 + i] = L_add( windowedTimeSignal[2 + leftOverlap / 2 + i], windowedTimeSignal[2 + leftOverlap / 2 - 1 - i] ); // *q_windowedTimeSignal + move32(); + } + } + ELSE + { + FOR( i = 0; i < leftOverlap / 2; i++ ) + { + windowedTimeSignal[2 + leftOverlap / 2 + i] = L_sub( windowedTimeSignal[2 + leftOverlap / 2 + i], windowedTimeSignal[2 + leftOverlap / 2 - 1 - i] ); // *q_windowedTimeSignal + move32(); + } + } + s = hTcxCfg->tcx5SizeFB; /* obtain 1st TCX5 again */ + move16(); + nSubframes = shl( nSubframes, 1 ); + Copy_Scale_sig_32_16( windowedTimeSignal + 2, windowedTimeSignal_16 + 2, add( s, shr( add( leftOverlap, rightOverlap ), 1 ) ), -Q16 ); // *q_windowedTimeSignal - Q16 + WindowSignal( hTcxCfg, shr( leftOverlap, 1 ), RECTANGULAR_OVERLAP, MIN_OVERLAP, &leftOverlap, &rightOverlap, windowedTimeSignal_16 + 2, &s, tcx5Win, 0, 1 ); // *q_windowedTimeSignal - Q16 + Copy_Scale_sig_16_32_no_sat( tcx5Win, tcx5Win_32, add( s, shr( add( leftOverlap, rightOverlap ), 1 ) ), Q16 ); // *q_windowedTimeSignal + + q_shift = -Q7; + move16(); + scale_sig32( tcx5Win_32, add( s /* L_subfr. */, shr( add( leftOverlap, rightOverlap ), 1 ) ), q_shift ); // *q_windowedTimeSignal + q_shift + kernel_switch_trafo_fx( tcx5Win_32, sigR, leftOverlap, sub( s /* L_subfr. */, shr( add( leftOverlap, rightOverlap ), 1 ) ), rightOverlap, kernelType ); // *q_windowedTimeSignal + q_shift + + /* Move both sigR and sigI to common Q */ + q_com = s_min( *q_sig, sub( add( *q_windowedTimeSignal, q_shift ), Q1 ) ); + scale_sig32( sigR, s, sub( q_com, sub( add( *q_windowedTimeSignal, q_shift ), Q1 ) ) ); + scale_sig32( sigR + s, sub( L_subframe, s ), sub( q_com, *q_sig ) ); + scale_sig32( sigI, L_subframe, sub( q_com, *q_sig ) ); + *q_sig = q_com; + move16(); + + IF( UL_and( kernelType, 1 ) ) /* 2nd TCX5 is kernelType 3 */ + { + FOR( i = L_subframe - 1; i >= s; i-- ) + { + const Word32 sigTemp = L_negate( sigR[i] ); + + sigR[i] = sigI[i]; + move32(); + sigI[i] = sigTemp; + move32(); + } + } + } + ELSE /* tcxTransType != TCX_5 */ + { + Word16 q_shift, q_com; + q_shift = -Q7; + move16(); + scale_sig32( windowedTimeSignal + 2, add( s /* L_subfr. */, shr( add( leftOverlap, rightOverlap ), 1 ) ), q_shift ); // *q_windowedTimeSignal + q_shift + kernel_switch_trafo_fx( windowedTimeSignal + 2, sigR, leftOverlap, sub( s /* L_subfr. */, shr( add( leftOverlap, rightOverlap ), 1 ) ), rightOverlap, kernelType ); // *q_windowedTimeSignal + q_shift + + /* Move both sigR and sigI to common Q */ + q_com = s_min( *q_sig, sub( add( *q_windowedTimeSignal, q_shift ), Q1 ) ); + scale_sig32( sigR, s, sub( q_com, sub( add( *q_windowedTimeSignal, q_shift ), Q1 ) ) ); + scale_sig32( sigR + s, sub( L_subframe, s ), sub( q_com, *q_sig ) ); + scale_sig32( sigI, L_subframe, sub( q_com, *q_sig ) ); + *q_sig = q_com; + move16(); + } + } + + /* high-band gain control, in case of bandwidth switching */ + IF( bwidthSwCnt > 0 ) + { + Word16 tmp, exp_tmp; + Word32 factor; + tmp = BASOP_Util_Divide1616_Scale( bwidthSwCnt, BWS_TRAN_PERIOD, &exp_tmp ); + factor = L_shl( L_deposit_h( tmp ), exp_tmp ); // Q31 + v_multc_fixed( sigR + L_FRAME16k / nSubframes, factor, sigR + L_FRAME16k / nSubframes, sub( s, idiv1616( L_FRAME16k, nSubframes ) ) ); // *q_sig + } + return; +} +#else static void kernel_switch_update_transforms( float *sigR, /* i/o: MDCT samples of the given channel */ float *sigI, /* i/o: MDST samples of the given channel */ @@ -573,8 +874,190 @@ static void kernel_switch_update_transforms( return; } +#endif + +#ifdef IVAS_FLOAT_FIXED +static void applyStereoPreProcessingCplx( + Word32 *mdctSample1_fx, // q_com + Word32 *mdctSample2_fx, // q_com + Word32 *mdstSample1_fx, // q_com + Word32 *mdstSample2_fx, // q_com + Word16 q_com, + const Word32 factIn_fx, // Q20 + const Word32 factDe_fx, // Q20 + const Word16 sign, // Q0 + Word16 *mdct_exp1, + Word16 *mdst_exp1, + Word16 *mdct_exp2, + Word16 *mdst_exp2 ) +{ + Word32 absR1_fx, absR2_fx; + Word32 dmxI1_fx, dmxR1_fx, dmxI2_fx, dmxR2_fx; + Word32 n_fx, d_fx, deno, sq_imp; + Word16 dmx_q, n_q, d_q, exp, temp1, temp2; + + Word32 valI1_fx = L_shr( *mdstSample1_fx, 1 ); + Word32 valI2_fx = L_shr( *mdstSample2_fx, 1 ); + Word32 valR1_fx = L_shr( *mdctSample1_fx, 1 ); + Word32 valR2_fx = L_shr( *mdctSample2_fx, 1 ); + + q_com = sub( q_com, 1 ); + + absR1_fx = L_abs( valR1_fx ); + absR2_fx = L_abs( valR2_fx ); + IF( sign < 0 ) + { + dmxR1_fx = L_sub( Mpy_32_32( valR1_fx, factDe_fx ), Mpy_32_32( valR2_fx, factIn_fx ) ); /* cross */ // Q = q_com + Q20 - 31 + dmxR2_fx = L_sub( Mpy_32_32( valR2_fx, factDe_fx ), Mpy_32_32( valR1_fx, factIn_fx ) ); /* -talk */ // Q = q_com + Q20 - 31 + } + ELSE + { + dmxR1_fx = L_add( Mpy_32_32( valR1_fx, factDe_fx ), Mpy_32_32( valR2_fx, factIn_fx ) ); /* cross */ // Q = q_com + Q20 - 31 + dmxR2_fx = L_add( Mpy_32_32( valR2_fx, factDe_fx ), Mpy_32_32( valR1_fx, factIn_fx ) ); /* -talk */ // Q = q_com + Q20 - 31 + } + dmx_q = sub( q_com, 11 ); + + IF( LT_32( L_abs( dmxR1_fx ), L_shr( L_add( absR1_fx, absR2_fx ), 11 ) ) ) /* avoid destructive summations */ + { + IF( Mpy_32_32( absR1_fx, factDe_fx ) < Mpy_32_32( absR2_fx, factIn_fx ) ) + { + IF( sign < 0 ) + { + dmxR1_fx = L_add( Mpy_32_32( valR1_fx, factDe_fx ), Mpy_32_32( valR2_fx, factIn_fx ) ); + dmxI1_fx = L_add( Mpy_32_32( valI1_fx, factDe_fx ), Mpy_32_32( valI2_fx, factIn_fx ) ); + } + ELSE + { + dmxR1_fx = L_sub( Mpy_32_32( valR2_fx, factIn_fx ), Mpy_32_32( valR1_fx, factDe_fx ) ); + dmxI1_fx = L_sub( Mpy_32_32( valI2_fx, factIn_fx ), Mpy_32_32( valI1_fx, factDe_fx ) ); + } + } + ELSE + { + IF( sign < 0 ) + { + dmxR1_fx = L_add( Mpy_32_32( valR1_fx, factDe_fx ), Mpy_32_32( valR2_fx, factIn_fx ) ); + dmxI1_fx = L_add( Mpy_32_32( valI1_fx, factDe_fx ), Mpy_32_32( valI2_fx, factIn_fx ) ); + } + ELSE + { + dmxR1_fx = L_sub( Mpy_32_32( valR1_fx, factDe_fx ), Mpy_32_32( valR2_fx, factIn_fx ) ); + dmxI1_fx = L_sub( Mpy_32_32( valI1_fx, factDe_fx ), Mpy_32_32( valI2_fx, factIn_fx ) ); + } + } + } + ELSE + { + IF( sign < 0 ) + { + dmxI1_fx = L_sub( Mpy_32_32( valI1_fx, factDe_fx ), Mpy_32_32( valI2_fx, factIn_fx ) ); + } + ELSE + { + dmxI1_fx = L_add( Mpy_32_32( valI1_fx, factDe_fx ), Mpy_32_32( valI2_fx, factIn_fx ) ); + } + } + + IF( LT_32( L_abs( dmxR2_fx ), L_shr( L_add( absR1_fx, absR2_fx ), 11 ) ) ) /* avoid destructive summations */ + { + IF( Mpy_32_32( absR1_fx, factIn_fx ) < Mpy_32_32( absR2_fx, factDe_fx ) ) + { + IF( sign < 0 ) + { + dmxR2_fx = L_add( Mpy_32_32( valR2_fx, factDe_fx ), Mpy_32_32( valR1_fx, factIn_fx ) ); + dmxI2_fx = L_add( Mpy_32_32( valI2_fx, factDe_fx ), Mpy_32_32( valI1_fx, factIn_fx ) ); + } + ELSE + { + dmxR2_fx = L_sub( Mpy_32_32( valR1_fx, factIn_fx ), Mpy_32_32( valR2_fx, factDe_fx ) ); + dmxI2_fx = L_sub( Mpy_32_32( valI1_fx, factIn_fx ), Mpy_32_32( valI2_fx, factDe_fx ) ); + } + } + ELSE + { + IF( sign < 0 ) + { + dmxR2_fx = L_add( Mpy_32_32( valR1_fx, factIn_fx ), Mpy_32_32( valR2_fx, factDe_fx ) ); + dmxI2_fx = L_add( Mpy_32_32( valI1_fx, factIn_fx ), Mpy_32_32( valI2_fx, factDe_fx ) ); + } + ELSE + { + dmxR2_fx = L_sub( Mpy_32_32( valR1_fx, factIn_fx ), Mpy_32_32( valR2_fx, factDe_fx ) ); + dmxI2_fx = L_sub( Mpy_32_32( valI1_fx, factIn_fx ), Mpy_32_32( valI2_fx, factDe_fx ) ); + } + } + } + ELSE + { + IF( sign < 0 ) + { + dmxI2_fx = L_sub( Mpy_32_32( valI2_fx, factDe_fx ), Mpy_32_32( valI1_fx, factIn_fx ) ); + } + ELSE + { + dmxI2_fx = L_add( Mpy_32_32( valI2_fx, factDe_fx ), Mpy_32_32( valI1_fx, factIn_fx ) ); + } + } + temp1 = norm_l( valR1_fx ); + valR1_fx = L_shl( valR1_fx, temp1 ); + temp2 = norm_l( valI1_fx ); + valI1_fx = L_shl( valI1_fx, temp2 ); + + n_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( valR1_fx, valR1_fx ), sub( 62, shl( add( q_com, temp1 ), 1 ) ), Mpy_32_32( valI1_fx, valI1_fx ), sub( 62, shl( add( q_com, temp2 ), 1 ) ), &n_q ); + n_q = sub( 31, n_q ); + + temp1 = norm_l( dmxR1_fx ); + dmxR1_fx = L_shl( dmxR1_fx, temp1 ); + temp2 = norm_l( dmxI1_fx ); + dmxI1_fx = L_shl( dmxI1_fx, temp2 ); + d_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( dmxR1_fx, dmxR1_fx ), sub( 62, shl( add( dmx_q, temp1 ), 1 ) ), Mpy_32_32( dmxI1_fx, dmxI1_fx ), sub( 62, shl( add( dmx_q, temp2 ), 1 ) ), &d_q ); + d_q = sub( 31, d_q ); + + deno = L_max( L_shl_sat( 1, d_q ), d_fx ); + sq_imp = BASOP_Util_Divide3232_Scale_cadence( n_fx, deno, &exp ); + exp = add( exp, sub( d_q, n_q ) ); + d_fx = Sqrt32( sq_imp, &exp ); + *mdctSample1_fx = Mpy_32_32( dmxR1_fx, d_fx ); + move32(); + *mdct_exp1 = add( sub( 31, add( dmx_q, temp1 ) ), exp ); + move16(); + *mdstSample1_fx = Mpy_32_32( dmxI1_fx, d_fx ); + move32(); + *mdst_exp1 = add( sub( 31, add( dmx_q, temp2 ) ), exp ); + move16(); + temp1 = norm_l( valR2_fx ); + valR2_fx = L_shl( valR2_fx, temp1 ); + temp2 = norm_l( valI2_fx ); + valI2_fx = L_shl( valI2_fx, temp2 ); + + n_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( valR2_fx, valR2_fx ), sub( 62, shl( add( q_com, temp1 ), 1 ) ), Mpy_32_32( valI2_fx, valI2_fx ), sub( 62, shl( add( q_com, temp2 ), 1 ) ), &n_q ); + n_q = sub( 31, n_q ); + + temp1 = norm_l( dmxR2_fx ); + dmxR2_fx = L_shl( dmxR2_fx, temp1 ); + temp2 = norm_l( dmxI2_fx ); + dmxI2_fx = L_shl( dmxI2_fx, temp2 ); + d_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( dmxR2_fx, dmxR2_fx ), sub( 62, shl( add( dmx_q, temp1 ), 1 ) ), Mpy_32_32( dmxI2_fx, dmxI2_fx ), sub( 62, shl( add( dmx_q, temp2 ), 1 ) ), &d_q ); + d_q = sub( 31, d_q ); + + deno = L_max( L_shl_sat( 1, d_q ), d_fx ); + sq_imp = BASOP_Util_Divide3232_Scale_cadence( n_fx, deno, &exp ); + exp = add( exp, sub( d_q, n_q ) ); + d_fx = Sqrt32( sq_imp, &exp ); + *mdctSample2_fx = Mpy_32_32( dmxR2_fx, d_fx ); + move32(); + *mdct_exp2 = add( sub( 31, add( dmx_q, temp1 ) ), exp ); + move16(); + *mdstSample2_fx = Mpy_32_32( dmxI2_fx, d_fx ); + move32(); + *mdst_exp2 = add( sub( 31, add( dmx_q, temp2 ) ), exp ); + move16(); + + return; +} +#else static void applyStereoPreProcessingCplx( float *mdctSample1, float *mdctSample2, @@ -647,56 +1130,343 @@ static void applyStereoPreProcessingCplx( return; } - +#endif /*--------------------------------------------------------------* * enc_ste_pre_mdct() * * encoder-side complex-valued stereo pre-processing (crosstalk) *---------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED static uint16_t enc_ste_pre_mdct( - float *sigR0, /* i/o: MDCT samples of the 1st (left) channel */ - float *sigR1, /* i/o: MDCT samples of the 2nd (right) channel */ - float *sigI0, /* i/o: MDST samples of the 1st (left) channel */ - float *sigI1, /* i/o: MDST samples of the 2nd (right) channel */ - const int16_t nSamplesCore, /* i : number of core-coded samples below IGF */ - const int16_t nSamplesMax, /* i : transform length (number of MCLT lines) */ - const int16_t limitWeight, /* i : 1 means the pre-processing is softened */ - const uint16_t corrIdxPrev, /* i : previous transform's correlation index */ - const uint32_t bitRateMode /* i : stereo bitrate mode (bps * L_frame) */ + Word32 *sigR0_fx, /* i/o: MDCT samples of the 1st (left) channel q_com*/ + Word32 *sigR1_fx, /* i/o: MDCT samples of the 2nd (right) channel q_com*/ + Word32 *sigI0_fx, /* i/o: MDST samples of the 1st (left) channel q_com*/ + Word32 *sigI1_fx, /* i/o: MDST samples of the 2nd (right) channel q_com*/ + Word16 *q_com, + const Word16 nSamplesCore, /* i : number of core-coded samples below IGF */ + const Word16 nSamplesMax, /* i : transform length (number of MCLT lines) */ + const Word16 limitWeight, /* i : 1 means the pre-processing is softened */ + const UWord16 corrIdxPrev, /* i : previous transform's correlation index */ + const UWord32 bitRateMode /* i : stereo bitrate mode (bps * L_frame) */ ) { - int16_t fadeInLen, fadeInOff, nSampProc, preproLen; - float maxSqrValue, stepWeightI, stepWeightD; - float corr, sumL, sumR, chanCorrSign, xTalkI, xTalkD; - float sumMagnL, sumMagnR, sumPrdLR, sumPrdLL, sumPrdRR; - int16_t s; - - fadeInLen = ( nSamplesMax < 512 ? ( nSamplesMax < 256 ? 10 : 20 ) : 40 ); /* 1000Hz transition */ - fadeInOff = ( ( bitRateMode * 3 ) >> 19 ) & ( nSamplesMax < 512 ? 0xFFFF : 0xFFFE ); /* offset */ - nSampProc = ( nSamplesCore > 0 && nSamplesCore < nSamplesMax ) ? nSamplesCore : nSamplesMax; - preproLen = nSampProc - fadeInOff; - maxSqrValue = 16777216.f * preproLen * preproLen; - stepWeightI = ( limitWeight > 0 ? 1.f : 2.f ); /* crosstalk weight */ - stepWeightD = 4.f - stepWeightI; /* decrement, i.e., 1 - crosstalk */ - corr = 0.f, sumL = 0.f, sumR = 0.f; - sumMagnL = 0.f, sumMagnR = 0.f, sumPrdLR = 0.f, sumPrdLL = 0.f, sumPrdRR = 0.f; + Word16 fadeInLen, fadeInOff, nSampProc, preproLen; + Word16 s; + + Word32 stepWeightI_fx, stepWeightD_fx; + Word32 corr_fx, sumL_fx, sumR_fx, xTalkI_fx, xTalkD_fx; + Word16 chanCorrSign_fx, corr_e, sumL_e, sumR_e; + Word32 sumMagnL_fx, sumMagnR_fx, sumPrdLR_fx, sumPrdLL_fx, sumPrdRR_fx; + Word32 temp1, temp2, temp3; + Word16 sumMagnL_e = 31, sumMagnR_e = 31, sumPrdLR_e = 31, sumPrdLL_e = 31, sumPrdRR_e = 31; + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 mdct_exp1[2 * 960], mdct_exp2[2 * 960]; + Word16 mdst_exp1[2 * 960], mdst_exp2[2 * 960]; + Word16 x1, x2, x3, x4, ans, tmp; + Word32 maxSqrValue_fx; - if ( fadeInOff + fadeInLen + MIN_STE_PRE_LEN >= nSampProc ) + IF( LT_16( nSamplesMax, 512 ) ) { - return 0; + IF( LT_16( nSamplesMax, 256 ) ) + { + fadeInLen = 10; + } + ELSE + { + fadeInLen = 20; + } } - - for ( s = fadeInOff; s < nSampProc; s++ ) + ELSE { - float absMagnL, absMagnR; - absMagnL = sqrtf( sigR0[s] * sigR0[s] + sigI0[s] * sigI0[s] ); - absMagnR = sqrtf( sigR1[s] * sigR1[s] + sigI1[s] * sigI1[s] ); + fadeInLen = 40; + } - corr += sigR0[s] * sigR1[s] + sigI0[s] * sigI1[s]; - sumL += sigR0[s] + sigI0[s]; - sumR += sigR1[s] + sigI1[s]; + IF( LT_16( nSamplesMax, 512 ) ) + { + fadeInOff = (Word16) L_and( (Word32) W_shr( W_mult0_32_32( bitRateMode, 3 ), 19 ), ( 0xFFFF ) ); /* offset */ + } + ELSE + { + fadeInOff = (Word16) L_and( (Word32) W_shr( W_mult0_32_32( bitRateMode, 3 ), 19 ), ( 0xFFFE ) ); /* offset */ + } + move16(); + test(); + IF( nSamplesCore > 0 && LT_16( nSamplesCore, nSamplesMax ) ) + { + nSampProc = nSamplesCore; + } + ELSE + { + nSampProc = nSamplesMax; + } + move16(); + preproLen = sub( nSampProc, fadeInOff ); + + set16_fx( mdct_exp1, sub( 31, *q_com ), 2 * 960 ); + set16_fx( mdst_exp1, sub( 31, *q_com ), 2 * 960 ); + set16_fx( mdct_exp2, sub( 31, *q_com ), 2 * 960 ); + set16_fx( mdst_exp2, sub( 31, *q_com ), 2 * 960 ); + + maxSqrValue_fx = L_mult0( shl( preproLen, 3 ), preproLen ); // Q - 21 + IF( limitWeight > 0 ) + { + stepWeightI_fx = ONE_IN_Q20; // Q20 + } + ELSE + { + stepWeightI_fx = ONE_IN_Q21; // Q21 + } + move16(); + + stepWeightD_fx = L_sub( ONE_IN_Q22, stepWeightI_fx ); // Q20 + corr_fx = 0, sumL_fx = 0, sumR_fx = 0; + move32(); + move32(); + move32(); + + sumMagnL_fx = 0, sumMagnR_fx = 0, sumPrdLR_fx = 0, sumPrdLL_fx = 0, sumPrdRR_fx = 0; + move32(); + move32(); + move32(); + move32(); + move32(); + IF( GE_16( add( add( fadeInOff, fadeInLen ), MIN_STE_PRE_LEN ), nSampProc ) ) + { + return 0; + } + + FOR( s = fadeInOff; s < nSampProc; s++ ) + { + Word32 absMagnL_fx, absMagnR_fx; + Word16 absMagnL_e, absMagnR_e; + + absMagnL_e = sub( 62, shl( *q_com, 1 ) ); + absMagnL_fx = Sqrt32( L_add( Mpy_32_32( sigR0_fx[s], sigR0_fx[s] ), Mpy_32_32( sigI0_fx[s], sigI0_fx[s] ) ), &absMagnL_e ); + + absMagnR_e = sub( 62, shl( *q_com, 1 ) ); + absMagnR_fx = Sqrt32( L_add( Mpy_32_32( sigR1_fx[s], sigR1_fx[s] ), Mpy_32_32( sigI1_fx[s], sigI1_fx[s] ) ), &absMagnR_e ); + + corr_fx = L_add( corr_fx, L_add( Mpy_32_32( sigR0_fx[s], sigR1_fx[s] ), Mpy_32_32( sigI0_fx[s], sigI1_fx[s] ) ) ); // q_com*2 - 31 + sumL_fx = L_add( sumL_fx, L_add( sigR0_fx[s], sigI0_fx[s] ) ); // q_com + sumR_fx = L_add( sumR_fx, L_add( sigR1_fx[s], sigI1_fx[s] ) ); // q_com + + sumMagnL_fx = BASOP_Util_Add_Mant32Exp( sumMagnL_fx, sumMagnL_e, absMagnL_fx, absMagnL_e, &sumMagnL_e ); + sumMagnR_fx = BASOP_Util_Add_Mant32Exp( sumMagnR_fx, sumMagnR_e, absMagnR_fx, absMagnR_e, &sumMagnR_e ); + sumPrdLR_fx = BASOP_Util_Add_Mant32Exp( sumPrdLR_fx, sumPrdLR_e, Mpy_32_32( absMagnL_fx, absMagnR_fx ), add( absMagnL_e, absMagnR_e ), &sumPrdLR_e ); + sumPrdLL_fx = BASOP_Util_Add_Mant32Exp( sumPrdLL_fx, sumPrdLL_e, Mpy_32_32( absMagnL_fx, absMagnL_fx ), shl( absMagnL_e, 1 ), &sumPrdLL_e ); + sumPrdRR_fx = BASOP_Util_Add_Mant32Exp( sumPrdRR_fx, sumPrdRR_e, Mpy_32_32( absMagnR_fx, absMagnR_fx ), shl( absMagnR_e, 1 ), &sumPrdRR_e ); + } + + x1 = norm_l( shl( preproLen, 1 ) ); + temp1 = L_shl( preproLen, x1 ); + corr_fx = Mpy_32_32( corr_fx, temp1 ); + x1 = sub( 62, add( shl( *q_com, 1 ), x1 ) ); + corr_fx = BASOP_Util_Add_Mant32Exp( corr_fx, x1, Mpy_32_32( sumL_fx, sumR_fx ), sub( 62, shl( *q_com, 1 ) ), &x1 ); + + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( corr_fx, x1, -maxSqrValue_fx, 52 ), -1 ) ) + { + chanCorrSign_fx = -1; + } + ELSE + { + chanCorrSign_fx = 1; + } + move16(); + sumL_fx = Mpy_32_16_1( sumMagnL_fx, div_s( 1, preproLen ) ); // sumMagnL_e + sumR_fx = Mpy_32_16_1( sumMagnR_fx, div_s( 1, preproLen ) ); // sumMagnR_e + + Word32 sumL_fx2 = sumMagnL_fx; + move32(); + Word32 sumR_fx2 = sumMagnR_fx; + move32(); + + temp1 = L_add( Mpy_32_32( sumMagnL_fx, sumR_fx ), Mpy_32_32( sumMagnR_fx, sumL_fx ) ); + temp2 = Mpy_32_32( sumL_fx, sumR_fx2 ); + temp3 = L_sub( temp2, temp1 ); // exp = sumMagnL_e + sumMagnR_e + corr_fx = BASOP_Util_Add_Mant32Exp( sumPrdLR_fx, sumPrdLR_e, temp3, add( sumMagnL_e, sumMagnR_e ), &corr_e ); + + temp1 = L_add( Mpy_32_32( sumMagnL_fx, sumL_fx ), Mpy_32_32( sumMagnL_fx, sumL_fx ) ); + temp2 = Mpy_32_32( sumL_fx, sumL_fx2 ); + temp3 = L_sub( temp2, temp1 ); // exp = sumMagnL_e + sumMagnL_e + sumL_fx = BASOP_Util_Add_Mant32Exp( sumPrdLL_fx, sumPrdLL_e, temp3, shl( sumMagnL_e, 1 ), &sumL_e ); + + temp1 = L_add( Mpy_32_32( sumMagnR_fx, sumR_fx ), Mpy_32_32( sumMagnR_fx, sumR_fx ) ); + temp2 = Mpy_32_32( sumR_fx, sumR_fx2 ); + temp3 = L_sub( temp2, temp1 ); // exp = sumMagnR_e + sumMagnR_e + sumR_fx = BASOP_Util_Add_Mant32Exp( sumPrdRR_fx, sumPrdRR_e, temp3, shl( sumMagnR_e, 1 ), &sumR_e ); + + test(); + IF( LE_32( corr_fx, 0 ) || LE_32( Mpy_32_32( sumL_fx, sumR_fx ), 0 ) ) + { + corr_fx = 0; + move32(); + corr_e = 31; + move16(); + } + ELSE + { + Word16 exp1; + corr_fx = BASOP_Util_Divide3232_Scale_cadence( Mpy_32_32( corr_fx, corr_fx ), Mpy_32_32( sumL_fx, sumR_fx ), &exp1 ); + corr_e = add( exp1, sub( shl( corr_e, 1 ), add( sumL_e, sumR_e ) ) ); + } + test(); + test(); + test(); + IF( ( GT_32( L_shl( corr_fx, sub( corr_e, s_max( corr_e, 0 ) ) ), L_shl( 1610612736, sub( 0, s_max( corr_e, 0 ) ) ) ) && corrIdxPrev == 0 ) || ( LE_32( L_shl( corr_fx, sub( corr_e, s_max( corr_e, 0 ) ) ), L_shl( 1610612736, sub( 0, s_max( corr_e, 0 ) ) ) ) && corrIdxPrev > 0 ) ) + { + stepWeightI_fx = ONE_IN_Q20; + move32(); + stepWeightD_fx = L_sub( ONE_IN_Q22, stepWeightI_fx ); + } + test(); + IF( LE_32( L_shl( corr_fx, sub( corr_e, s_max( corr_e, 0 ) ) ), L_shl( 1610612736, sub( 0, s_max( corr_e, 0 ) ) ) ) && corrIdxPrev == 0 ) /* bypass all processing, just return */ + { + return 0; + } + + sigR0_fx += add( fadeInOff, 1 ); /* stereo pre-processing starts with an offset of one! */ + sigR1_fx += add( fadeInOff, 1 ); + sigI0_fx += add( fadeInOff, 1 ); + sigI1_fx += add( fadeInOff, 1 ); + tmp = add( fadeInOff, 1 ); + xTalkI_fx = stepWeightI_fx; + xTalkD_fx = imult3216( stepWeightD_fx, sub( shl( fadeInLen, 1 ), 1 ) ); + + for ( s = sub( fadeInLen, 1 ); s > 0; s--, sigR0_fx++, sigR1_fx++, sigI0_fx++, sigI1_fx++, tmp++ ) + { + applyStereoPreProcessingCplx( sigR0_fx, sigR1_fx, sigI0_fx, sigI1_fx, *q_com, xTalkI_fx, xTalkD_fx, chanCorrSign_fx, &x1, &x2, &x3, &x4 ); + mdct_exp1[tmp] = x1; + move16(); + mdst_exp1[tmp] = x2; + move16(); + mdct_exp2[tmp] = x3; + move16(); + mdst_exp2[tmp] = x4; + move16(); + xTalkI_fx = L_add( xTalkI_fx, stepWeightI_fx ); + xTalkD_fx = L_sub( xTalkD_fx, stepWeightD_fx ); + } + + for ( s = preproLen - fadeInLen; s > 0; s--, sigR0_fx++, sigR1_fx++, sigI0_fx++, sigI1_fx++, tmp++ ) + { + applyStereoPreProcessingCplx( sigR0_fx, sigR1_fx, sigI0_fx, sigI1_fx, *q_com, xTalkI_fx, xTalkD_fx, chanCorrSign_fx, &x1, &x2, &x3, &x4 ); + mdct_exp1[tmp] = x1; + move16(); + mdst_exp1[tmp] = x2; + move16(); + mdct_exp2[tmp] = x3; + move16(); + mdst_exp2[tmp] = x4; + move16(); + } + + IF( LT_16( nSampProc, nSamplesMax ) ) /* fade-out of processing at start of IGF range */ + { + for ( s = s_min( fadeInLen, nSamplesMax - nSampProc ) - 1; s > 0; s--, sigR0_fx++, sigR1_fx++, sigI0_fx++, sigI1_fx++, tmp++ ) + { + xTalkI_fx = L_sub( xTalkI_fx, stepWeightI_fx ); + xTalkD_fx = L_add( xTalkD_fx, stepWeightD_fx ); + applyStereoPreProcessingCplx( sigR0_fx, sigR1_fx, sigI0_fx, sigI1_fx, *q_com, xTalkI_fx, xTalkD_fx, chanCorrSign_fx, &x1, &x2, &x3, &x4 ); + mdct_exp1[tmp] = x1; + move16(); + mdst_exp1[tmp] = x2; + move16(); + mdct_exp2[tmp] = x3; + move16(); + mdst_exp2[tmp] = x4; + move16(); + } + } + + Word16 shift_r = -1000; + move16(); + FOR( s = 0; s < s_max( nSamplesCore, nSamplesMax ); s++ ) + { + shift_r = s_max( shift_r, mdct_exp1[s] ); + shift_r = s_max( shift_r, mdst_exp1[s] ); + shift_r = s_max( shift_r, mdct_exp2[s] ); + shift_r = s_max( shift_r, mdst_exp2[s] ); + } + + sigR0_fx -= tmp; /* stereo pre-processing starts with an offset of one! */ + sigR1_fx -= tmp; + sigI0_fx -= tmp; + sigI1_fx -= tmp; + + FOR( s = 0; s < s_max( nSamplesCore, nSamplesMax ); s++ ) + { + sigR0_fx[s] = L_shl( sigR0_fx[s], sub( mdct_exp1[s], shift_r ) ); + move32(); + sigI0_fx[s] = L_shl( sigI0_fx[s], sub( mdst_exp1[s], shift_r ) ); + move32(); + sigR1_fx[s] = L_shl( sigR1_fx[s], sub( mdct_exp2[s], shift_r ) ); + move32(); + sigI1_fx[s] = L_shl( sigI1_fx[s], sub( mdst_exp2[s], shift_r ) ); + move32(); + } + *q_com = sub( 31, shift_r ); + move16(); + IF( GT_32( L_shl( corr_fx, sub( corr_e, s_max( corr_e, 0 ) ) ), L_shl( 1610612736, sub( 0, s_max( corr_e, 0 ) ) ) ) ) + { + ans = 1; + } + ELSE + { + ans = 0; + } + move16(); + + return ans; +} +#else +static uint16_t enc_ste_pre_mdct( + float *sigR0, /* i/o: MDCT samples of the 1st (left) channel */ + float *sigR1, /* i/o: MDCT samples of the 2nd (right) channel */ + float *sigI0, /* i/o: MDST samples of the 1st (left) channel */ + float *sigI1, /* i/o: MDST samples of the 2nd (right) channel */ + const int16_t nSamplesCore, /* i : number of core-coded samples below IGF */ + const int16_t nSamplesMax, /* i : transform length (number of MCLT lines) */ + const int16_t limitWeight, /* i : 1 means the pre-processing is softened */ + const uint16_t corrIdxPrev, /* i : previous transform's correlation index */ + const uint32_t bitRateMode /* i : stereo bitrate mode (bps * L_frame) */ +) +{ + int16_t fadeInLen, fadeInOff, nSampProc, preproLen; + float maxSqrValue, stepWeightI, stepWeightD; + float corr, sumL, sumR, chanCorrSign, xTalkI, xTalkD; + float sumMagnL, sumMagnR, sumPrdLR, sumPrdLL, sumPrdRR; + int16_t s; + + fadeInLen = ( nSamplesMax < 512 ? ( nSamplesMax < 256 ? 10 : 20 ) : 40 ); /* 1000Hz transition */ + fadeInOff = ( ( bitRateMode * 3 ) >> 19 ) & ( nSamplesMax < 512 ? 0xFFFF : 0xFFFE ); /* offset */ + nSampProc = ( nSamplesCore > 0 && nSamplesCore < nSamplesMax ) ? nSamplesCore : nSamplesMax; + preproLen = nSampProc - fadeInOff; + maxSqrValue = 16777216.f * preproLen * preproLen; + stepWeightI = ( limitWeight > 0 ? 1.f : 2.f ); /* crosstalk weight */ + stepWeightD = 4.f - stepWeightI; /* decrement, i.e., 1 - crosstalk */ + corr = 0.f, sumL = 0.f, sumR = 0.f; + sumMagnL = 0.f, sumMagnR = 0.f, sumPrdLR = 0.f, sumPrdLL = 0.f, sumPrdRR = 0.f; + + if ( fadeInOff + fadeInLen + MIN_STE_PRE_LEN >= nSampProc ) + { + return 0; + } + + for ( s = fadeInOff; s < nSampProc; s++ ) + { + float absMagnL, absMagnR; + absMagnL = sqrtf( sigR0[s] * sigR0[s] + sigI0[s] * sigI0[s] ); + absMagnR = sqrtf( sigR1[s] * sigR1[s] + sigI1[s] * sigI1[s] ); + + corr += sigR0[s] * sigR1[s] + sigI0[s] * sigI1[s]; + sumL += sigR0[s] + sigI0[s]; + sumR += sigR1[s] + sigI1[s]; sumMagnL += absMagnL; sumMagnR += absMagnR; @@ -758,7 +1528,7 @@ static uint16_t enc_ste_pre_mdct( return ( corr > 0.75f ? 1 : 0 ); } - +#endif /*--------------------------------------------------------------* * enc_prm_igf_mdct() @@ -827,6 +1597,7 @@ void enc_prm_igf_mdct( * MCT preprocessing up to whitening the core spectrum *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void ivas_mdct_core_whitening_enc( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ @@ -855,12 +1626,17 @@ void ivas_mdct_core_whitening_enc( float temp_buffer[15 * L_FRAME48k / 8]; float *windowedSignal[CPE_CHANNELS]; float *powerSpec = orig_spectrum_long[0]; +#ifdef IVAS_FLOAT_FIXED + Word32 powerSpec_fx[N_MAX]; +#endif float *mdst_spectrum[CPE_CHANNELS][NB_DIV]; float nrg; Encoder_State *st, **sts; float scf[CPE_CHANNELS][NB_DIV][M]; float scf_q[CPE_CHANNELS][NB_DIV][M]; #ifdef IVAS_FLOAT_FIXED + Word16 old_wsp_fx[CPE_CHANNELS][L_WSP]; + Word16 q_fac; Word32 scf_fx[CPE_CHANNELS][NB_DIV][M]; Word32 scf_q_fx[CPE_CHANNELS][NB_DIV][M]; #endif @@ -872,9 +1648,16 @@ void ivas_mdct_core_whitening_enc( int16_t zero_side_flag[NB_DIV]; #ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word16 q_com; - Word32 mdst_spectrum_fx[CPE_CHANNELS][NB_DIV][2 * L_FRAME48k]; + Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word32 mdst_spectrum_long_fx[CPE_CHANNELS][2 * L_FRAME48k]; Word16 mdst_spectrum_e[CPE_CHANNELS][NB_DIV]; #endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_new; + Word16 new_samples_fx[CPE_CHANNELS][L_INP]; + Word32 *windowedSignal_fx[CPE_CHANNELS]; + Word32 L_tmpbuf[NB_DIV * L_FRAME48k + 4], L_tmpbuf1[NB_DIV * L_FRAME48k + 4]; +#endif push_wmops( "mdct_core_whitening" ); @@ -914,10 +1697,21 @@ void ivas_mdct_core_whitening_enc( orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; mdst_spectrum[ch][0] = mdst_spectrum_long[ch]; mdst_spectrum[ch][1] = mdst_spectrum_long[ch] + N_TCX10_MAX; +#ifdef IVAS_FLOAT_FIXED + set32_fx( mdst_spectrum_long_fx[ch], 0, 1920 ); + mdst_spectrum_fx[ch][0] = mdst_spectrum_long_fx[ch]; + mdst_spectrum_fx[ch][1] = mdst_spectrum_long_fx[ch] + N_TCX10_MAX; + set_f( scf[ch][0], 0.0, M ); + set_f( scf[ch][1], 0.0, M ); +#endif } windowedSignal[0] = orig_spectrum_long[0]; /* NOTE temporarily available */ windowedSignal[1] = temp_buffer; /* orig_spectrum_long isn't long enough */ +#ifdef IVAS_FLOAT_FIXED + windowedSignal_fx[0] = L_tmpbuf; + windowedSignal_fx[1] = L_tmpbuf1; +#endif /*--------------------------------------------------------------* * TCX20/TCX10 switching decision @@ -978,55 +1772,1528 @@ void ivas_mdct_core_whitening_enc( SetCurrentPsychParams( st->core, 0, st->hTcxCfg ); /* tcx ltp analysis on the 12.8kHz weighted speech, saves preproc resampling to sr_core */ - tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); - core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( old_wsp[ch], L_WSP ); + floatToFixed_arr( old_wsp[ch], old_wsp_fx[ch], q_fac, L_WSP ); +#endif + tcx_ltp_encode_ivas_fx( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp_fx[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp_fx[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); - /* BWD in MDCT domain */ - if ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) - { - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( old_wsp_fx[ch], old_wsp[ch], q_fac, L_WSP ); + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); +#endif +#else + tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); +#endif - for ( n = 0; n < nSubframes; n++ ) +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( new_samples[ch], new_samples_fx[ch], 0, L_INP ); + Word16 leftOverlap = 0, rightOverlap = 0; + PWord16 const *left_win; + PWord16 const *right_win; + Word16 len_windowSignal; + Word16 overlap_mode[3]; + Word16 transform_type[2]; + overlap_mode[0] = st->hTcxCfg->tcx_last_overlap_mode; /* Overlap between the last and the current frame */ + IF( EQ_16( hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + transform_type[0] = TCX_20; + transform_type[1] = TCX_20; + overlap_mode[1] = st->hTcxCfg->tcx_curr_overlap_mode; /* Overlap between the current and the next frame */ + } + ELSE + { + nSubframes = 2; + IF( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) { - bw_detect( st, NULL, st->hTcxEnc->spectrum[n], NULL, MC_FORMAT /*just cannot be ISM_FORMAT*/, mct_on ); + transform_type[0] = TCX_5; + transform_type[1] = TCX_10; + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + } + } + ELSE IF( st->hTcxCfg->tcx_last_overlap_mode == FULL_OVERLAP ) + { + transform_type[0] = TCX_10; + transform_type[1] = TCX_5; + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ + if ( EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + } + } + ELSE + { + transform_type[0] = transform_type[1] = TCX_5; + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, HALF_OVERLAP ) && EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP ) ) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + overlap_mode[2] = st->hTcxCfg->tcx_curr_overlap_mode; /* Overlap between the current and the next frame */ + move16(); + } - if ( nSubframes == NB_DIV && n == 0 ) + Word16 offset; + IF( ( EQ_16( transform_type[0], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + Word16 nl = (int16_t) ( (float) hTcxEnc->L_frameTCX * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + floatToFixed_arr( &hTcxEnc->new_speech_TCX_flt[nl - hTcxEnc->L_frameTCX], + &hTcxEnc->new_speech_TCX[nl - hTcxEnc->L_frameTCX], + 0, + 2 * hTcxEnc->L_frameTCX ); + windowedSignal_fx[ch][0] = (Word16) windowedSignal[ch][0]; + windowedSignal_fx[ch][1] = (Word16) windowedSignal[ch][1]; + } + ELSE + { + tcx_get_windows( st->hTcxCfg, overlap_mode[0], overlap_mode[1], &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( st->hTcxEnc->L_frameTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + offset = st->hTcxCfg->tcx_offsetFB; + IF( EQ_16( overlap_mode[0], TRANSITION_OVERLAP ) ) + { + len_windowSignal += st->hTcxCfg->tcx5SizeFB; + /* Increase frame size for 5ms */ + offset = negate( shr( st->hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); + } + floatToFixed_arr( &hTcxEnc->speech_TCX_flt[-( leftOverlap / 2 ) + offset], + &hTcxEnc->speech_TCX[-( leftOverlap / 2 ) + offset], + 0, + len_windowSignal ); + windowedSignal_fx[ch][0] = (Word16) windowedSignal[ch][0]; + windowedSignal_fx[ch][1] = (Word16) windowedSignal[ch][1]; + floatToFixed_arrL32( windowedSignal[ch] + 2, windowedSignal_fx[ch] + 2, 0, len_windowSignal ); + } + IF( NE_16( hTcxEnc->tcxMode, TCX_20 ) ) + { + IF( ( EQ_16( transform_type[1], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + Word16 nl = (int16_t) ( (float) hTcxEnc->L_frameTCX * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + floatToFixed_arr( &hTcxEnc->new_speech_TCX_flt[nl - hTcxEnc->L_frameTCX], + &hTcxEnc->new_speech_TCX[nl - hTcxEnc->L_frameTCX], + 0, + 2 * hTcxEnc->L_frameTCX ); + windowedSignal_fx[ch][L_FRAME48k + 0] = (Word16) windowedSignal[ch][L_FRAME_MAX + 0]; + windowedSignal_fx[ch][L_FRAME48k + 1] = (Word16) windowedSignal[ch][L_FRAME_MAX + 1]; + } + ELSE + { + tcx_get_windows( st->hTcxCfg, overlap_mode[1], overlap_mode[2], &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( st->hTcxEnc->L_frameTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + offset = st->hTcxCfg->tcx_offsetFB; + IF( EQ_16( overlap_mode[1], TRANSITION_OVERLAP ) ) { - st->last_input_bwidth = st->input_bwidth; + len_windowSignal += st->hTcxCfg->tcx5SizeFB; + /* Increase frame size for 5ms */ + offset = negate( shr( st->hTcxCfg->tcx_mdct_window_trans_lengthFB, 1 ) ); } + floatToFixed_arr( &hTcxEnc->speech_TCX_flt[( 2 * st->hTcxCfg->tcx5SizeFB ) - ( leftOverlap / 2 ) + offset], + &hTcxEnc->speech_TCX[( 2 * st->hTcxCfg->tcx5SizeFB ) - ( leftOverlap / 2 ) + offset], + 0, + len_windowSignal ); + windowedSignal_fx[ch][L_FRAME48k + 0] = (Word16) windowedSignal[ch][L_FRAME_MAX + 0]; + windowedSignal_fx[ch][L_FRAME48k + 1] = (Word16) windowedSignal[ch][L_FRAME_MAX + 1]; + floatToFixed_arrL32( windowedSignal[ch] + L_FRAME48k + 2, windowedSignal_fx[ch] + L_FRAME48k + 2, 0, len_windowSignal ); } } - if ( st->last_core == ACELP_CORE ) /* reset past kernel info */ + if ( st->element_mode == IVAS_CPE_DFT ) { - st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; - st->hTcxEnc->kernel_symmetry_past = 0; + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + floatToFixed_arr( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + st->exp_buf_wspeech_enc = 15 - q_fac; + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + floatToFixed_arr( st->buf_speech_enc_flt, st->buf_speech_enc, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + st->exp_buf_speech_enc = 15 - q_fac; + floatToFixed_arr( st->hTcxEnc->buf_speech_ltp_flt, st->hTcxEnc->buf_speech_ltp, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + st->hTcxEnc->exp_buf_speech_ltp = 15 - q_fac; } - } - /*--------------------------------------------------------------* - * Transform Kernel Switching, Stereo Pre-Processing, and TNS - *---------------------------------------------------------------*/ + floatToFixed_arrL( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg, 7, 24 ); + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, 24 ); - sts[0]->hTcxEnc->fUseTns[1] = 0; + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) && st->igf ) + { + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } - if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on && !hCPE->hStereoMdct->isSBAStereoMode ) - { - int16_t nSampCore; - int32_t totalRate; - TCX_ENC_HANDLE hTcxEnc0, hTcxEnc1; + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } - nSampCore = ( sts[0]->igf ) ? max( sts[0]->hIGFEnc->infoStartLine, sts[1]->hIGFEnc->infoStartLine ) : 0; - totalRate = sts[0]->element_brate; - hTcxEnc0 = sts[0]->hTcxEnc; - hTcxEnc1 = sts[1]->hTcxEnc; + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = fmaxf( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = fmaxf( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = fmaxf( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = fmaxf( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = fmaxf( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = fmaxf( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); + } + } + } + if ( st->hIGFEnc ) + { + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->infoStopLine - IGF_START_MN ); + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, st->hIGFEnc->infoStopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + Word16 q_spectrum = L_get_q_buf1( hTcxEnc->spectrum[0], st->hTcxEnc->L_frameTCX / nSubframes ); + hTcxEnc->spectrum_e[0] = 31 - q_spectrum; + floatToFixed_arrL32( hTcxEnc->spectrum[0], hTcxEnc->spectrum_fx[0], sub( Q31, hTcxEnc->spectrum_e[0] ), st->hTcxEnc->L_frameTCX / nSubframes ); + IF( hTcxEnc->tcxMode != TCX_20 ) + { + q_spectrum = L_get_q_buf1( hTcxEnc->spectrum[1], st->hTcxEnc->L_frameTCX / nSubframes ); + hTcxEnc->spectrum_e[1] = 31 - q_spectrum; + floatToFixed_arrL32( hTcxEnc->spectrum[1], hTcxEnc->spectrum_fx[1], sub( Q31, hTcxEnc->spectrum_e[1] ), st->hTcxEnc->L_frameTCX / nSubframes ); + } + + Q_new = 0; +#endif + core_signal_analysis_high_bitrate_ivas_fx( new_samples_fx[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal_fx[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0, mdst_spectrum_fx[ch], mdst_spectrum_e[ch], &Q_new ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) && st->igf ) + { + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); + me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->infoStopLine - IGF_START_MN ); + } + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + } + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IF( st->hTcxEnc->fUseTns[0] || st->hTcxEnc->fUseTns[1] ) + { + if ( st->hTcxCfg->fIsTNSAllowed ) + { // conv params to float + // avgSqrCoef_flt = float(avgSqrCoef, Q 15) + hTcxEnc->tnsData[0].filter[0].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[0].filter[0].avgSqrCoef, 15 ); + hTcxEnc->tnsData[0].filter[1].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[0].filter[1].avgSqrCoef, 15 ); + IF( hTcxEnc->tcxMode != TCX_20 ) + { + hTcxEnc->tnsData[1].filter[0].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[1].filter[0].avgSqrCoef, 15 ); + hTcxEnc->tnsData[1].filter[1].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[1].filter[1].avgSqrCoef, 15 ); + } + + // avgSqrCoef_flt = float(avgSqrCoef, Q 15) + hTcxEnc->tnsData[0].filter[0].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[0].filter[0].predictionGain, 7 ); + hTcxEnc->tnsData[0].filter[1].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[0].filter[1].predictionGain, 7 ); + IF( hTcxEnc->tcxMode != TCX_20 ) + { + hTcxEnc->tnsData[1].filter[0].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[1].filter[0].predictionGain, 7 ); + hTcxEnc->tnsData[1].filter[1].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[1].filter[1].predictionGain, 7 ); + } + // spectrum[]=float( (fix)spectrum_fx[]) , Q=q_factor_spectrum + // fixedToFloat_arrL( hTcxEnc->spectrum_long_fx, hTcxEnc->spectrum_long, q_factor_spectrum, N_MAX ); + + // subblockNrg_flt=(float)((fixed)subblockNrg) + fixedToFloat_arrL( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg_flt, 7, 24 ); + + // subblockNrgChange_flt=(float)((fixed)subblockNrgChange) + fixedToFloat_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, 7, 24 ); + } + } + } + + if ( st->element_mode == IVAS_CPE_DFT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( st->buf_wspeech_enc, st->buf_wspeech_enc_flt, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( st->hTcxEnc->buf_speech_ltp, st->hTcxEnc->buf_speech_ltp_flt, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + + fixedToFloat_arrL32( hTcxEnc->spectrum_fx[0], hTcxEnc->spectrum[0], sub( Q31, hTcxEnc->spectrum_e[0] ), st->hTcxEnc->L_frameTCX / nSubframes ); + IF( hTcxEnc->tcxMode != TCX_20 ) + { + fixedToFloat_arrL32( hTcxEnc->spectrum_fx[1], hTcxEnc->spectrum[1], sub( Q31, hTcxEnc->spectrum_e[1] ), st->hTcxEnc->L_frameTCX / nSubframes ); + } + fixedToFloat_arrL32( mdst_spectrum_fx[ch][0], mdst_spectrum[ch][0], sub( Q31, mdst_spectrum_e[ch][0] ), st->hTcxEnc->L_frameTCX / nSubframes ); + IF( hTcxEnc->tcxMode != TCX_20 ) + { + fixedToFloat_arrL32( mdst_spectrum_fx[ch][1], mdst_spectrum[ch][1], sub( Q31, mdst_spectrum_e[ch][1] ), st->hTcxEnc->L_frameTCX / nSubframes ); + } + IF( ( EQ_16( transform_type[0], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + windowedSignal[ch][0] = (float) windowedSignal_fx[ch][0]; + windowedSignal[ch][1] = (float) windowedSignal_fx[ch][1]; + } + ELSE + { + tcx_get_windows( st->hTcxCfg, overlap_mode[0], overlap_mode[1], &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( st->hTcxEnc->L_frameTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + windowedSignal[ch][0] = (float) windowedSignal_fx[ch][0]; + windowedSignal[ch][1] = (float) windowedSignal_fx[ch][1]; + fixedToFloat_arrL32( windowedSignal_fx[ch] + 2, windowedSignal[ch] + 2, 0, len_windowSignal ); + } + IF( NE_16( hTcxEnc->tcxMode, TCX_20 ) ) + { + IF( ( EQ_16( transform_type[1], TCX_20 ) ) && ( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) + { + windowedSignal[ch][L_FRAME48k + 0] = (float) windowedSignal_fx[ch][L_FRAME_MAX + 0]; + windowedSignal[ch][L_FRAME48k + 1] = (float) windowedSignal_fx[ch][L_FRAME_MAX + 1]; + } + ELSE + { + tcx_get_windows( st->hTcxCfg, overlap_mode[1], overlap_mode[2], &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( st->hTcxEnc->L_frameTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + windowedSignal[ch][L_FRAME48k + 0] = (float) windowedSignal_fx[ch][L_FRAME_MAX + 0]; + windowedSignal[ch][L_FRAME48k + 1] = (float) windowedSignal_fx[ch][L_FRAME_MAX + 1]; + fixedToFloat_arrL32( windowedSignal_fx[ch] + L_FRAME48k + 2, windowedSignal[ch] + L_FRAME48k + 2, 0, len_windowSignal ); + } + } +#endif +#else + core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); +#endif + + /* BWD in MDCT domain */ + if ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + bw_detect( st, NULL, st->hTcxEnc->spectrum[n], NULL, MC_FORMAT /*just cannot be ISM_FORMAT*/, mct_on ); + + if ( nSubframes == NB_DIV && n == 0 ) + { + st->last_input_bwidth = st->input_bwidth; + } + } + } + + if ( st->last_core == ACELP_CORE ) /* reset past kernel info */ + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + st->hTcxEnc->kernel_symmetry_past = 0; + } + } + + /*--------------------------------------------------------------* + * Transform Kernel Switching, Stereo Pre-Processing, and TNS + *---------------------------------------------------------------*/ + + sts[0]->hTcxEnc->fUseTns[1] = 0; + + if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on && !hCPE->hStereoMdct->isSBAStereoMode ) + { + int16_t nSampCore; + int32_t totalRate; + TCX_ENC_HANDLE hTcxEnc0, hTcxEnc1; + + nSampCore = ( sts[0]->igf ) ? max( sts[0]->hIGFEnc->infoStartLine, sts[1]->hIGFEnc->infoStartLine ) : 0; + totalRate = sts[0]->element_brate; + hTcxEnc0 = sts[0]->hTcxEnc; + hTcxEnc1 = sts[1]->hTcxEnc; + +#ifdef IVAS_FLOAT_FIXED + init_tcx_enc_info_fx( sts[0], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#else + init_tcx_enc_info( sts[0], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#endif + + if ( nSampCore == 0 ) + { + nSampCore = tcx_subframe_coded_lines; + } + + nrg = 0.25f * ( hTcxEnc0->tcxltp_norm_corr_past_flt + hTcxEnc0->tcxltp_norm_corr_mem_flt + /* tcxltp_norm_corr_past already contains the */ + hTcxEnc1->tcxltp_norm_corr_past_flt + hTcxEnc1->tcxltp_norm_corr_mem_flt ); /* normalized correlation of the current frame */ + + L_subframe = max( 512, L_subframe ); + nSubframes = ( hTcxEnc0->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( hTcxEnc0->transform_type[n] == hTcxEnc1->transform_type[n] ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( hTcxEnc0->spectrum[n], hTcxEnc0->L_frameTCX / nSubframes ); + q_com = s_min( q_com, L_get_q_buf1( hTcxEnc1->spectrum[n], hTcxEnc1->L_frameTCX / nSubframes ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n], hTcxEnc0->L_frameTCX / nSubframes ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n], hTcxEnc1->L_frameTCX / nSubframes ) ); + + floatToFixed_arrL32( hTcxEnc0->spectrum[n], hTcxEnc0->spectrum_fx[n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); + floatToFixed_arrL32( hTcxEnc1->spectrum[n], hTcxEnc1->spectrum_fx[n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[0][n], mdst_spectrum_fx[0][n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[1][n], mdst_spectrum_fx[1][n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); + + hTcxEnc0->kernel_switch_corr_past = float_to_fix16( hTcxEnc0->kernel_switch_corr_past_flt, Q15 ); +#endif + const Word16 switchKernel = /* these 4 transform types can be applied: 0 = MDCT-IV, 1 = MDST-II, 2 = MDCT-II, 3 = MDST-IV */ + kernel_switch_detect_fx( hTcxEnc0->spectrum_fx[n], hTcxEnc1->spectrum_fx[n], mdst_spectrum_fx[0][n], mdst_spectrum_fx[1][n], q_com, nSampCore / nSubframes, + L_subframeTCX / nSubframes, hTcxEnc0->transform_type[n], &hTcxEnc0->kernel_switch_corr_past, ( totalRate * L_subframe ) / nSubframes ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hTcxEnc0->kernel_switch_corr_past_flt = fix16_to_float( hTcxEnc0->kernel_switch_corr_past, Q15 ); +#endif +#else + const int16_t switchKernel = /* these 4 transform types can be applied: 0 = MDCT-IV, 1 = MDST-II, 2 = MDCT-II, 3 = MDST-IV */ + kernel_switch_detect( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / nSubframes, + L_subframeTCX / nSubframes, hTcxEnc0->transform_type[n], &hTcxEnc0->kernel_switch_corr_past_flt, ( totalRate * L_subframe ) / nSubframes ); +#endif + if ( switchKernel ) /* apply MDST-IV coding in one of the channels */ + { + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 3 : 1 ) - max( 0, switchKernel ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 2 : 0 ) + max( 0, switchKernel ); + } + else /* switchKernel == 0, switch back to MDCT-IV in both channels */ + { + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 2 : 0 ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 2 : 0 ); + } + } + else + { + hTcxEnc0->kernel_switch_corr_past_flt = 0.f; /* don't update the kernel switching state, postpone it to when data is available */ + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 3 : 0 ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 3 : 0 ); + } + hTcxEnc0->kernel_symmetry_past = hTcxEnc0->kernel_type[n] & 1; + hTcxEnc1->kernel_symmetry_past = hTcxEnc1->kernel_type[n] & 1; + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( hTcxEnc0->spectrum[n], hTcxEnc0->L_frameTCX / nSubframes ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n], hTcxEnc0->L_frameTCX / nSubframes ) ); + floatToFixed_arrL32( hTcxEnc0->spectrum[n], hTcxEnc0->spectrum_fx[n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[0][n], mdst_spectrum_fx[0][n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); + + Word16 nl = (int16_t) ( (float) ( hTcxEnc0->L_frameTCX / nSubframes ) * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + floatToFixed_arr( &hTcxEnc0->new_speech_TCX_flt[nl - ( hTcxEnc0->L_frameTCX / nSubframes )], + &hTcxEnc0->new_speech_TCX[nl - ( hTcxEnc0->L_frameTCX / nSubframes )], + 0, + 2 * hTcxEnc0->L_frameTCX / nSubframes ); + + if ( n == 0 ) + { + floatToFixed_arr( &hTcxEnc0->speech_TCX_flt[-( sts[0]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + &hTcxEnc0->speech_TCX[-( sts[0]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + 0, + sts[0]->hTcxCfg->tcx_mdct_window_min_lengthFB ); + } + + Word16 leftOverlap = 0, rightOverlap = 0; + PWord16 const *left_win; + PWord16 const *right_win; + Word16 q_windowedSignal, len_windowSignal; + + windowedSignal_fx[0][0] = ( Word16 ) * ( windowedSignal[0] + n * L_FRAME48k ); + windowedSignal_fx[0][1] = ( Word16 ) * ( windowedSignal[0] + n * L_FRAME48k + 1 ); + if ( ( hTcxEnc0->transform_type[n] == TCX_5 ) || ( n == 0 /* speech_TCX != NULL*/ && NE_16( hTcxEnc0->transform_type[n], TCX_20 ) && windowedSignal_fx[0][0] == FULL_OVERLAP && GT_16( sub( L_subframeTCX / nSubframes, leftOverlap ), sts[0]->hTcxCfg->tcx_mdct_window_min_lengthFB - 1 ) ) ) + { + tcx_get_windows( sts[0]->hTcxCfg, extract_l( windowedSignal_fx[0][0] ), extract_l( windowedSignal_fx[0][1] ), &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( L_subframeTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + q_windowedSignal = Q_factor_arrL( windowedSignal[0] + n * L_FRAME48k + 2, len_windowSignal ) - 1; + floatToFixed_arrL32( windowedSignal[0] + n * L_FRAME48k + 2, windowedSignal_fx[0] + n * L_FRAME48k + 2, q_windowedSignal, len_windowSignal ); + } +#endif + kernel_switch_update_transforms_fx( hTcxEnc0->spectrum_fx[n], mdst_spectrum_fx[0][n], &q_com, hTcxEnc0->transform_type[n], sts[0]->hTcxCfg, sts[0]->bwidth_sw_cnt, hTcxEnc0->kernel_type[n], + hTcxEnc0->new_speech_TCX, ( n == 1 ? NULL : hTcxEnc0->speech_TCX ), windowedSignal_fx[0] + n * L_FRAME48k, &q_windowedSignal, L_subframeTCX / nSubframes ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( hTcxEnc0->spectrum_fx[n], hTcxEnc0->spectrum[n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( mdst_spectrum_fx[0][n], mdst_spectrum[0][n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); +#endif +#else + kernel_switch_update_transforms( hTcxEnc0->spectrum[n], mdst_spectrum[0][n], hTcxEnc0->transform_type[n], sts[0]->hTcxCfg, sts[0]->bwidth_sw_cnt, hTcxEnc0->kernel_type[n], + hTcxEnc0->new_speech_TCX_flt, ( n == 1 ? NULL : hTcxEnc0->speech_TCX_flt ), windowedSignal[0] + n * L_FRAME48k, L_subframeTCX / nSubframes ); +#endif +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( hTcxEnc1->spectrum[n], hTcxEnc1->L_frameTCX / nSubframes ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n], hTcxEnc1->L_frameTCX / nSubframes ) ); + floatToFixed_arrL32( hTcxEnc1->spectrum[n], hTcxEnc1->spectrum_fx[n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[1][n], mdst_spectrum_fx[1][n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); + + nl = (int16_t) ( (float) ( hTcxEnc1->L_frameTCX / nSubframes ) * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + floatToFixed_arr( &hTcxEnc1->new_speech_TCX_flt[nl - ( hTcxEnc1->L_frameTCX / nSubframes )], + &hTcxEnc1->new_speech_TCX[nl - ( hTcxEnc1->L_frameTCX / nSubframes )], + 0, + 2 * hTcxEnc1->L_frameTCX / nSubframes ); + + if ( n == 0 ) + { + floatToFixed_arr( &hTcxEnc1->speech_TCX_flt[-( sts[1]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + &hTcxEnc1->speech_TCX[-( sts[1]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + 0, + sts[1]->hTcxCfg->tcx_mdct_window_min_lengthFB ); + } + + windowedSignal_fx[1][0] = ( Word16 ) * ( windowedSignal[1] + n * L_FRAME48k ); + windowedSignal_fx[1][1] = ( Word16 ) * ( windowedSignal[1] + n * L_FRAME48k + 1 ); + if ( ( hTcxEnc1->transform_type[n] == TCX_5 ) || ( n == 0 /* speech_TCX != NULL*/ && NE_16( hTcxEnc1->transform_type[n], TCX_20 ) && windowedSignal_fx[1][0] == FULL_OVERLAP && GT_16( sub( L_subframeTCX / nSubframes, leftOverlap ), sts[1]->hTcxCfg->tcx_mdct_window_min_lengthFB - 1 ) ) ) + { + tcx_get_windows( sts[1]->hTcxCfg, extract_l( windowedSignal_fx[1][0] ), extract_l( windowedSignal_fx[1][1] ), &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( L_subframeTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + q_windowedSignal = Q_factor_arrL( windowedSignal[1] + n * L_FRAME48k + 2, len_windowSignal ) - 1; + floatToFixed_arrL32( windowedSignal[1] + n * L_FRAME48k + 2, windowedSignal_fx[1] + n * L_FRAME48k + 2, q_windowedSignal, len_windowSignal ); + } +#endif + kernel_switch_update_transforms_fx( hTcxEnc1->spectrum_fx[n], mdst_spectrum_fx[1][n], &q_com, hTcxEnc1->transform_type[n], sts[1]->hTcxCfg, sts[1]->bwidth_sw_cnt, hTcxEnc1->kernel_type[n], + hTcxEnc1->new_speech_TCX, ( n == 1 ? NULL : hTcxEnc1->speech_TCX ), windowedSignal_fx[1] + n * L_FRAME48k, &q_windowedSignal, L_subframeTCX / nSubframes ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( hTcxEnc1->spectrum_fx[n], hTcxEnc1->spectrum[n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( mdst_spectrum_fx[1][n], mdst_spectrum[1][n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); +#endif +#else + kernel_switch_update_transforms( hTcxEnc1->spectrum[n], mdst_spectrum[1][n], hTcxEnc1->transform_type[n], sts[1]->hTcxCfg, sts[1]->bwidth_sw_cnt, hTcxEnc1->kernel_type[n], + hTcxEnc1->new_speech_TCX_flt, ( n == 1 ? NULL : hTcxEnc1->speech_TCX_flt ), windowedSignal[1] + n * L_FRAME48k, L_subframeTCX / nSubframes ); +#endif + } + for ( n = 0; n < nSubframes; n++ ) + { + if ( hTcxEnc0->transform_type[n] == hTcxEnc1->transform_type[n] && /* do not combine TCX-5 and TCX-10 as this causes artifacts */ + sts[0]->hTcxCfg->tcx_curr_overlap_mode == sts[1]->hTcxCfg->tcx_curr_overlap_mode && + sts[0]->hTcxCfg->tcx_last_overlap_mode == sts[1]->hTcxCfg->tcx_last_overlap_mode ) + { + if ( hTcxEnc0->transform_type[n] == TCX_5 ) + { + const int16_t tcx5SizeFB = sts[1]->hTcxCfg->tcx5SizeFB; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 length; + length = max( nSampCore / ( 2 * NB_DIV ), L_subframeTCX / ( 2 * NB_DIV ) ); + q_com = L_get_q_buf1( hTcxEnc0->spectrum[n], length ); + q_com = s_min( q_com, L_get_q_buf1( hTcxEnc1->spectrum[n], length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n], length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n], length ) ) - 6; + + floatToFixed_arrL32( hTcxEnc0->spectrum[n], hTcxEnc0->spectrum_fx[n], q_com, length ); + floatToFixed_arrL32( hTcxEnc1->spectrum[n], hTcxEnc1->spectrum_fx[n], q_com, length ); + floatToFixed_arrL32( mdst_spectrum[0][n], mdst_spectrum_fx[0][n], q_com, length ); + floatToFixed_arrL32( mdst_spectrum[1][n], mdst_spectrum_fx[1][n], q_com, length ); +#endif + + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum_fx[n], hTcxEnc1->spectrum_fx[n], mdst_spectrum_fx[0][n], mdst_spectrum_fx[1][n], &q_com, nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( hTcxEnc0->spectrum_fx[n], hTcxEnc0->spectrum[n], q_com, length ); + fixedToFloat_arrL( hTcxEnc1->spectrum_fx[n], hTcxEnc1->spectrum[n], q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[0][n], mdst_spectrum[0][n], q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[1][n], mdst_spectrum[1][n], q_com, length ); + + q_com = L_get_q_buf1( hTcxEnc0->spectrum[n] + tcx5SizeFB, length ); + q_com = s_min( q_com, L_get_q_buf1( hTcxEnc1->spectrum[n] + tcx5SizeFB, length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n] + tcx5SizeFB, length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n] + tcx5SizeFB, length ) ) - 6; + + floatToFixed_arrL32( hTcxEnc0->spectrum[n] + tcx5SizeFB, hTcxEnc0->spectrum_fx[n] + tcx5SizeFB, q_com, length ); + floatToFixed_arrL32( hTcxEnc1->spectrum[n] + tcx5SizeFB, hTcxEnc1->spectrum_fx[n] + tcx5SizeFB, q_com, length ); + floatToFixed_arrL32( mdst_spectrum[0][n] + tcx5SizeFB, mdst_spectrum_fx[0][n] + tcx5SizeFB, q_com, length ); + floatToFixed_arrL32( mdst_spectrum[1][n] + tcx5SizeFB, mdst_spectrum_fx[1][n] + tcx5SizeFB, q_com, length ); + +#endif + + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum_fx[n] + tcx5SizeFB, hTcxEnc1->spectrum_fx[n] + tcx5SizeFB, mdst_spectrum_fx[0][n] + tcx5SizeFB, mdst_spectrum_fx[1][n] + tcx5SizeFB, &q_com, nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( hTcxEnc0->spectrum_fx[n] + tcx5SizeFB, hTcxEnc0->spectrum[n] + tcx5SizeFB, q_com, length ); + fixedToFloat_arrL( hTcxEnc1->spectrum_fx[n] + tcx5SizeFB, hTcxEnc1->spectrum[n] + tcx5SizeFB, q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[0][n] + tcx5SizeFB, mdst_spectrum[0][n] + tcx5SizeFB, q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[1][n] + tcx5SizeFB, mdst_spectrum[1][n] + tcx5SizeFB, q_com, length ); +#endif +#else + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); + + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n] + tcx5SizeFB, hTcxEnc1->spectrum[n] + tcx5SizeFB, mdst_spectrum[0][n] + tcx5SizeFB, mdst_spectrum[1][n] + tcx5SizeFB, nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); +#endif + } + else + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 length; + length = max( nSampCore / nSubframes, L_subframeTCX / nSubframes ); + q_com = L_get_q_buf1( hTcxEnc0->spectrum[n], length ); + q_com = s_min( q_com, L_get_q_buf1( hTcxEnc1->spectrum[n], length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n], length ) ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n], length ) ) - 6; + + floatToFixed_arrL32( hTcxEnc0->spectrum[n], hTcxEnc0->spectrum_fx[n], q_com, length ); + floatToFixed_arrL32( hTcxEnc1->spectrum[n], hTcxEnc1->spectrum_fx[n], q_com, length ); + floatToFixed_arrL32( mdst_spectrum[0][n], mdst_spectrum_fx[0][n], q_com, length ); + floatToFixed_arrL32( mdst_spectrum[1][n], mdst_spectrum_fx[1][n], q_com, length ); +#endif + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum_fx[n], hTcxEnc1->spectrum_fx[n], mdst_spectrum_fx[0][n], mdst_spectrum_fx[1][n], &q_com, nSampCore / nSubframes, + L_subframeTCX / nSubframes, ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / nSubframes ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( hTcxEnc0->spectrum_fx[n], hTcxEnc0->spectrum[n], q_com, length ); + fixedToFloat_arrL( hTcxEnc1->spectrum_fx[n], hTcxEnc1->spectrum[n], q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[0][n], mdst_spectrum[0][n], q_com, length ); + fixedToFloat_arrL( mdst_spectrum_fx[1][n], mdst_spectrum[1][n], q_com, length ); +#endif +#else + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / nSubframes, + L_subframeTCX / nSubframes, ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / nSubframes ); +#endif + } + } + else + { + hTcxEnc0->enc_ste_pre_corr_past = 0; + } + } + } + else + { + sts[0]->hTcxEnc->enc_ste_pre_corr_past = 0; + sts[0]->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + TCX_ENC_HANDLE hTcxEncCh = sts[ch]->hTcxEnc; + + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + hTcxEncCh->kernel_symmetry_past = hTcxEncCh->kernel_type[0] = 0; + + continue; + } + +#ifdef IVAS_FLOAT_FIXED + init_tcx_enc_info_fx( sts[ch], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#else + init_tcx_enc_info( sts[ch], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#endif + nSubframes = ( hTcxEncCh->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + hTcxEncCh->kernel_type[n] = ( hTcxEncCh->kernel_symmetry_past && sts[ch]->element_mode == IVAS_CPE_MDCT ? 3 - mct_on : 0 ); + hTcxEncCh->kernel_symmetry_past = hTcxEncCh->kernel_type[n] & 1; + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( hTcxEncCh->spectrum[n], hTcxEncCh->L_frameTCX / nSubframes ); + q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[ch][n], hTcxEncCh->L_frameTCX / nSubframes ) ); + floatToFixed_arrL32( hTcxEncCh->spectrum[n], hTcxEncCh->spectrum_fx[n], q_com, hTcxEncCh->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[ch][n], mdst_spectrum_fx[ch][n], q_com, hTcxEncCh->L_frameTCX / nSubframes ); + + Word16 nl = (int16_t) ( (float) ( hTcxEncCh->L_frameTCX / nSubframes ) * N_ZERO_MDCT_NS / FRAME_SIZE_NS ); + floatToFixed_arr( &hTcxEncCh->new_speech_TCX_flt[nl - ( hTcxEncCh->L_frameTCX / nSubframes )], + &hTcxEncCh->new_speech_TCX[nl - ( hTcxEncCh->L_frameTCX / nSubframes )], + 0, + 2 * hTcxEncCh->L_frameTCX / nSubframes ); + + if ( n == 0 ) + { + floatToFixed_arr( &hTcxEncCh->speech_TCX_flt[-( sts[ch]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + &hTcxEncCh->speech_TCX[-( sts[ch]->hTcxCfg->tcx_mdct_window_min_lengthFB - 0 )], + 0, + sts[ch]->hTcxCfg->tcx_mdct_window_min_lengthFB ); + } + + Word16 leftOverlap = 0, rightOverlap = 0; + PWord16 const *left_win; + PWord16 const *right_win; + Word16 q_windowedSignal, len_windowSignal; + + windowedSignal_fx[ch][0] = ( Word16 ) * ( windowedSignal[ch] + n * L_FRAME48k ); + windowedSignal_fx[ch][1] = ( Word16 ) * ( windowedSignal[ch] + n * L_FRAME48k + 1 ); + if ( ( hTcxEncCh->transform_type[n] == TCX_5 ) || ( n == 0 /* speech_TCX != NULL*/ && NE_16( hTcxEncCh->transform_type[n], TCX_20 ) && windowedSignal_fx[ch][0] == FULL_OVERLAP && GT_16( sub( L_subframeTCX / nSubframes, leftOverlap ), sts[ch]->hTcxCfg->tcx_mdct_window_min_lengthFB - 1 ) ) ) + { + tcx_get_windows( sts[ch]->hTcxCfg, extract_l( windowedSignal_fx[ch][0] ), extract_l( windowedSignal_fx[ch][1] ), &leftOverlap, &left_win, &rightOverlap, &right_win, 1 ); + len_windowSignal = ( L_subframeTCX / nSubframes ) + ( leftOverlap + rightOverlap ) / 2; + q_windowedSignal = Q_factor_arrL( windowedSignal[ch] + n * L_FRAME48k + 2, len_windowSignal ) - 1; + floatToFixed_arrL32( windowedSignal[ch] + n * L_FRAME48k + 2, windowedSignal_fx[ch] + n * L_FRAME48k + 2, q_windowedSignal, len_windowSignal ); + } +#endif + kernel_switch_update_transforms_fx( hTcxEncCh->spectrum_fx[n], mdst_spectrum_fx[ch][n], &q_com, hTcxEncCh->transform_type[n], sts[ch]->hTcxCfg, sts[ch]->bwidth_sw_cnt, hTcxEncCh->kernel_type[n], + hTcxEncCh->new_speech_TCX, ( n /*1*/ ? NULL : hTcxEncCh->speech_TCX ), windowedSignal_fx[ch] + n * L_FRAME48k, &q_windowedSignal, L_subframeTCX / nSubframes ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( hTcxEncCh->spectrum_fx[n], hTcxEncCh->spectrum[n], q_com, hTcxEncCh->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][n], mdst_spectrum[ch][n], q_com, hTcxEncCh->L_frameTCX / nSubframes ); +#endif +#else + kernel_switch_update_transforms( hTcxEncCh->spectrum[n], mdst_spectrum[ch][n], hTcxEncCh->transform_type[n], sts[ch]->hTcxCfg, sts[ch]->bwidth_sw_cnt, hTcxEncCh->kernel_type[n], + hTcxEncCh->new_speech_TCX_flt, ( n /*1*/ ? NULL : hTcxEncCh->speech_TCX_flt ), windowedSignal[ch] + n * L_FRAME48k, L_subframeTCX / nSubframes ); +#endif + } + } + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + int k; + + Word16 q_temp[2][2]; + TCX_ENC_HANDLE hTcxEnc = NULL; + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + q_com = L_get_q_buf1( st->hTcxEnc->spectrum[k], st->hTcxEnc->L_frameTCX / nSubframes ); + st->hTcxEnc->spectrum_e[k] = Q31 - ( q_com - 4 ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[k], st->hTcxEnc->spectrum_fx[k], ( Q31 - st->hTcxEnc->spectrum_e[k] ), st->hTcxEnc->L_frameTCX / nSubframes ); + + q_temp[ch][k] = L_get_q_buf1( mdst_spectrum[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_temp[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + } + + hTcxEnc->tcxltp_gain = (Word16) ( hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif + + TNSAnalysisStereo_fx( sts, mdst_spectrum_fx, 0, tnsSize, tnsBits, param_core, mct_on ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[k], st->hTcxEnc->spectrum[k], ( Q31 - st->hTcxEnc->spectrum_e[k] ), st->hTcxEnc->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_temp[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + } + sts[ch]->hTcxEnc->tcxltp_gain_flt = fix16_to_float( sts[ch]->hTcxEnc->tcxltp_gain, Q15 ); + } +#endif +#else + TNSAnalysisStereo( sts, mdst_spectrum, 0, tnsSize, tnsBits, param_core, mct_on ); +#endif + /*--------------------------------------------------------------* + * Envelope Quantization and FDNS + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + if ( mct_on ) + { + set_zero( chE, NB_DIV ); + } + +#ifdef IVAS_FLOAT_FIXED + init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#else + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#endif + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = ( mct_on ? L_subframeTCX / nSubframes : L_subframe ); + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( st->hTcxEnc->fUseTns[n] ) + { + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpec[i] = ( st->hTcxEnc->spectrum[n][i] * st->hTcxEnc->spectrum[n][i] ); + } + } + else + { + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpec[i] = ( mdst_spectrum[ch][n][i] * mdst_spectrum[ch][n][i] + st->hTcxEnc->spectrum[n][i] * st->hTcxEnc->spectrum[n][i] ); + } + } + + if ( mct_on ) + { + chE[n] = sum_f( powerSpec, L_subframeTCX ); + } +#ifndef IVAS_FLOAT_FIXED + sns_compute_scf( powerSpec, st->hTcxCfg->psychParamsCurrent, st->L_frame, scf[ch][n] ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q = L_get_q_buf1( powerSpec, st->L_frame ); + floatToFixed_arrL32( powerSpec, powerSpec_fx, q, st->L_frame ); +#endif + sns_compute_scf_fx( powerSpec_fx, st->hTcxCfg->psychParamsCurrent, st->L_frame, scf_fx[ch][n], q ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( scf_fx[ch][n], scf[ch][n], Q16, SNS_NPTS ); +#endif +#endif + } + + /* MCT: detect whether there are silent channels and set mct_chan_mode accordingly */ + if ( mct_on ) + { + chE_tot = sum_f( chE, NB_DIV ); + + if ( chE_tot < SILENT_CHANNEL_THRES && nSubframes == 1 ) + { + st->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + st->bits_frame_channel = 0; + } + else + { + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + } + } + + /* set low br mode, if possible. Can later be discarded, depending on the stereo mode used for SNS parameter decoding */ + if ( hCPE->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) ) + { + sns_low_br_mode = !sts[0]->sp_aud_decision0; + } + else + { + sns_low_br_mode = 0; + } + + if ( !mct_on && sts[0]->sr_core == 25600 && ( ( hCPE->element_brate == IVAS_48k || hCPE->element_brate == IVAS_64k ) ) ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 scf_e = L_get_q_buf1( scf[0][0], M ); + scf_e = min( scf_e, L_get_q_buf1( scf[0][1], M ) ); + scf_e = min( scf_e, L_get_q_buf1( scf[1][0], M ) ); + scf_e = min( scf_e, L_get_q_buf1( scf[1][1], M ) ); + scf_e = 31 - ( scf_e - 4 ); + + floatToFixed_arrL32( scf[0][0], scf_fx[0][0], ( Q31 - scf_e ), M ); + floatToFixed_arrL32( scf[0][1], scf_fx[0][1], ( Q31 - scf_e ), M ); + floatToFixed_arrL32( scf[1][0], scf_fx[1][0], ( Q31 - scf_e ), M ); + floatToFixed_arrL32( scf[1][1], scf_fx[1][1], ( Q31 - scf_e ), M ); + +#endif + quantize_sns_fx( scf_fx, scf_q_fx, &scf_e, sts, sns_vq_indices, zero_side_flag, sns_stereo_mode ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( scf_q_fx[0][0], scf_q[0][0], ( Q31 - scf_e ), M ); + fixedToFloat_arrL32( scf_q_fx[0][1], scf_q[0][1], ( Q31 - scf_e ), M ); + fixedToFloat_arrL32( scf_q_fx[1][0], scf_q[1][0], ( Q31 - scf_e ), M ); + fixedToFloat_arrL32( scf_q_fx[1][1], scf_q[1][1], ( Q31 - scf_e ), M ); + +#endif + +#else + quantize_sns( scf, scf_q, sts, sns_vq_indices, zero_side_flag, sns_stereo_mode ); +#endif + } + else + { + if ( sts[0]->hTcxEnc->tcxMode == TCX_20 && sts[1]->hTcxEnc->tcxMode == TCX_20 && + sts[0]->mct_chan_mode == MCT_CHAN_MODE_REGULAR && sts[1]->mct_chan_mode == MCT_CHAN_MODE_REGULAR ) + { +#ifdef IVAS_FLOAT_FIXED + /*=================flt-2-fix==============*/ + Word16 exp_snl = 0, exp_snr = 0; + f2me_buf( scf[0][0], scf_fx[0][0], &exp_snl, M ); + f2me_buf( scf[1][0], scf_fx[1][0], &exp_snr, M ); + /*=================flt-2-fix==============*/ + sns_avq_cod_stereo_fx( scf_fx[0][0], exp_snl, scf_fx[1][0], exp_snr, sts[0]->L_frame, scf_q_fx[0][0], scf_q_fx[1][0], param_lpc[0], param_lpc[1] ); + /*===============fix-2-flt==========================*/ + fixedToFloat_arrL( scf_q_fx[0][0], scf_q[0][0], Q16, M ); + fixedToFloat_arrL( scf_q_fx[1][0], scf_q[1][0], Q16, M ); + /*===============fix-2-flt==========================*/ +#else + sns_avq_cod_stereo( scf[0][0], scf[1][0], sts[0]->L_frame, scf_q[0][0], scf_q[1][0], param_lpc[0], param_lpc[1] ); +#endif + } + else + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + param_lpc[ch][0] = ch; + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_scf_1 = 0, exp_scf_0 = 0; + IF( st->hTcxEnc->tcxMode == TCX_20 ) + { + /*===============flt-2-fix==========================*/ + f2me_buf( scf[ch][0], scf_fx[ch][0], &exp_scf_0, M ); + /*===============flt-2-fix==========================*/ + sns_avq_cod_fx( scf_fx[ch][0], exp_scf_0, NULL, 0, scf_q_fx[ch][0], NULL, ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + /*===============fix-2-flt==========================*/ + fixedToFloat_arrL( scf_q_fx[ch][0], scf_q[ch][0], Q16, M ); + /*===============fix-2-flt==========================*/ + } + ELSE + { + /*===============flt-2-fix==========================*/ + f2me_buf( scf[ch][1], scf_fx[ch][1], &exp_scf_1, M ); + f2me_buf( scf[ch][0], scf_fx[ch][0], &exp_scf_0, M ); + /*===============flt-2-fix==========================*/ + sns_avq_cod_fx( scf_fx[ch][1], exp_scf_1, scf_fx[ch][0], exp_scf_0, scf_q_fx[ch][1], scf_q_fx[ch][0], ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + /*===============fix-2-flt==========================*/ + fixedToFloat_arrL( scf_q_fx[ch][0], scf_q[ch][0], Q16, M ); + fixedToFloat_arrL( scf_q_fx[ch][1], scf_q[ch][1], Q16, M ); + /*===============fix-2-flt==========================*/ + } +#else + if ( st->hTcxEnc->tcxMode == TCX_20 ) + { + sns_avq_cod( scf[ch][0], NULL, scf_q[ch][0], NULL, ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + } + else + { + sns_avq_cod( scf[ch][1], scf[ch][0], scf_q[ch][1], scf_q[ch][0], ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + } +#endif + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; +#ifdef IVAS_FLOAT_FIXED + init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#else + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#endif + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = L_subframeTCX / nSubframes; + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + mvr2r( st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], L_subframeTCX ); + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 A_q_fx[CPE_CHANNELS][NB_DIV][M + 1]; + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxEnc->spectrum_e[n] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[n], tcx_subframe_coded_lines ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], 31 - st->hTcxEnc->spectrum_e[n], tcx_subframe_coded_lines ); + floatToFixed_arrL( scf_q[ch][n], scf_q_fx[ch][n], Q16, M ); +#endif + + /* Shape spectrum */ + ShapeSpectrum_ivas_fx( st->hTcxCfg, A_q_fx[ch][n], NULL, NULL, L_subframe, tcx_subframe_coded_lines, st->hTcxEnc->spectrum_fx[n], &st->hTcxEnc->spectrum_e[n], st->hTcxEnc->fUseTns[n], st, scf_q_fx[ch][n] ); + + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], 31 - st->hTcxEnc->spectrum_e[n], tcx_subframe_coded_lines ); + if ( st->enablePlcWaveadjust ) + { + st->hTcxCfg->SFM2_flt = fix_to_float( st->hTcxCfg->SFM2, Q31 ); + } + +#endif +#else + ShapeSpectrum( st->hTcxCfg, A_q[ch][n], NULL, L_subframe, tcx_subframe_coded_lines, st->hTcxEnc->spectrum[n], st->hTcxEnc->fUseTns[n], st, scf_q[ch][n] ); +#endif + } + } + + /*--------------------------------------------------------------* + * TNS + *---------------------------------------------------------------*/ + + /* first deinterleave once more */ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( st->hTcxEnc->transform_type[n] == TCX_5 ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTcxEnc->spectrum_e[n] = Q31 - L_get_q_buf1( st->hTcxEnc->spectrum[n], st->hTcxCfg->tcx5SizeFB * 2 ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], ( Q31 - st->hTcxEnc->spectrum_e[n] ), st->hTcxCfg->tcx5SizeFB * 2 ); + mdst_spectrum_e[ch][n] = Q31 - L_get_q_buf1( mdst_spectrum[ch][n], st->hTcxCfg->tcx5SizeFB * 2 ); + floatToFixed_arrL32( mdst_spectrum[ch][n], mdst_spectrum_fx[ch][n], ( Q31 - mdst_spectrum_e[ch][n] ), st->hTcxCfg->tcx5SizeFB * 2 ); +#endif + tcx5SpectrumDeinterleaving_fx( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum_fx[n] ); + tcx5SpectrumDeinterleaving_fx( st->hTcxCfg->tcx5SizeFB, mdst_spectrum_fx[ch][n] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], ( Q31 - st->hTcxEnc->spectrum_e[n] ), st->hTcxCfg->tcx5SizeFB * 2 ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][n], mdst_spectrum[ch][n], ( Q31 - mdst_spectrum_e[ch][n] ), st->hTcxCfg->tcx5SizeFB * 2 ); +#endif +#else + tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum[n] ); + tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, mdst_spectrum[ch][n] ); +#endif + } + } + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + q_com = L_get_q_buf1( st->hTcxEnc->spectrum[k], st->hTcxEnc->L_frameTCX / nSubframes ); + st->hTcxEnc->spectrum_e[k] = Q31 - ( q_com - 4 ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[k], st->hTcxEnc->spectrum_fx[k], ( Q31 - st->hTcxEnc->spectrum_e[k] ), st->hTcxEnc->L_frameTCX / nSubframes ); + + q_temp[ch][k] = L_get_q_buf1( mdst_spectrum[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_temp[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + } + + hTcxEnc->tcxltp_gain = (Word16) ( hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif + + TNSAnalysisStereo_fx( sts, mdst_spectrum_fx, 1, tnsSize, tnsBits, param_core, mct_on ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[k], st->hTcxEnc->spectrum[k], ( Q31 - st->hTcxEnc->spectrum_e[k] ), st->hTcxEnc->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_temp[ch][k], st->hTcxEnc->L_frameTCX / nSubframes ); + } + sts[ch]->hTcxEnc->tcxltp_gain_flt = fix16_to_float( sts[ch]->hTcxEnc->tcxltp_gain, Q15 ); + } +#endif +#else + TNSAnalysisStereo( sts, mdst_spectrum, 1, tnsSize, tnsBits, param_core, mct_on ); +#endif + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + +#ifdef IVAS_FLOAT_FIXED + init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#else + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); +#endif + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = L_subframeTCX / nSubframes; + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( !st->hTcxEnc->fUseTns[n] ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 A_q_fx[CPE_CHANNELS][NB_DIV][M + 1]; + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + floatToFixed_arr( A_q[ch][n], A_q_fx[ch][n], Q12, M + 1 ); + mdst_spectrum_e[ch][n] = 31 - ( Q_factor_arrL( mdst_spectrum[ch][n], tcx_subframe_coded_lines ) - 2 ); + floatToFixed_arrL( mdst_spectrum[ch][n], mdst_spectrum_fx[ch][n], 31 - mdst_spectrum_e[ch][n], tcx_subframe_coded_lines ); + floatToFixed_arrL( scf_q[ch][n], scf_q_fx[ch][n], Q16, M ); +#endif + + /* Shape spectrum */ + ShapeSpectrum_ivas_fx( st->hTcxCfg, A_q_fx[ch][n], NULL, NULL, L_subframe, tcx_subframe_coded_lines, mdst_spectrum_fx[ch][n], &mdst_spectrum_e[ch][n], st->hTcxEnc->fUseTns[n], st, scf_q_fx[ch][n] ); + + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( mdst_spectrum_fx[ch][n], mdst_spectrum[ch][n], 31 - mdst_spectrum_e[ch][n], tcx_subframe_coded_lines ); + if ( st->enablePlcWaveadjust ) + { + st->hTcxCfg->SFM2_flt = fix_to_float( st->hTcxCfg->SFM2, Q31 ); + } + +#endif +#else + ShapeSpectrum( st->hTcxCfg, A_q[ch][n], NULL, L_subframe, tcx_subframe_coded_lines, mdst_spectrum[ch][n], st->hTcxEnc->fUseTns[n], st, scf_q[ch][n] ); +#endif // IVAS_FLOAT_FIXED + } + } + } + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + /*no need to write last channel bit in case of odd channels*/ + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + + st = sts[ch]; + + if ( mct_on ) /* signal bits should be written only for MCT*/ + { + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + push_next_indice( hBstr, 1, 1 ); + } + else + { + assert( st->mct_chan_mode == MCT_CHAN_MODE_REGULAR ); + push_next_indice( hBstr, 0, 1 ); + } + } + } + + /* write bitstream with info up to here */ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + st->side_bits_frame_channel = 0; + /*dummy initialization to prevent range coder crashing in case all channels are silent and bits are distributed to channel 0 */ + *p_param[ch] = 1 + NOISE_FILL_RANGES + LTPSIZE + tnsSize[ch][0] + NPRM_CTX_HM; + continue; + } + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); +#endif + test(); + test(); + IF( ( ch > 0 ) && ( add( sts[0]->hTcxEnc->fUseTns[0], sts[0]->hTcxEnc->fUseTns[1] ) > 0 ) && !mct_on ) + { + enc_prm_pre_mdct_fx( st, param_core[ch], tnsSize[ch], p_param[ch], mct_on, hBstr ); + } + ELSE + { + enc_prm_pre_mdct_fx( st, param_core[ch], NULL, p_param[ch], mct_on, hBstr ); + } +#else + enc_prm_pre_mdct( st, param_core[ch], ( ( ( ch > 0 ) && ( sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 ) && !mct_on ) ? tnsSize[ch] : NULL ), p_param[ch], mct_on, hBstr ); +#endif + + if ( ch > 0 && sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 && !mct_on ) + { + if ( st->hTcxEnc->tnsData[0].nFilters < 0 ) + { + tnsBits[ch][0] = 1; + } + else + { + tnsBits[ch][0]++; + } + + if ( st->core == TCX_10_CORE ) + { + if ( st->hTcxEnc->tnsData[1].nFilters < 0 ) + { + tnsBits[ch][1] = 1; + } + else + { + tnsBits[ch][1]++; + } + } + } + } + + /*--------------------------------------------------------------------------------* + * SNS parameters + *--------------------------------------------------------------------------------*/ + + if ( !mct_on && sts[0]->sr_core == 25600 && ( ( hCPE->element_brate == IVAS_48k || hCPE->element_brate == IVAS_64k ) ) ) + { + idx = 0; + + if ( sts[0]->core == sts[1]->core ) + { + nSubframes = ( sts[0]->core == TCX_20_CORE ) ? 1 : NB_DIV; + + /* push all stereo mode bits first */ + for ( n = 0; n < nSubframes; ++n ) + { + push_next_indice( hBstr, sns_stereo_mode[n], 1 ); + sts[0]->side_bits_frame_channel++; + } + + /* zero side flags only get transmitted if needed */ + for ( n = 0; n < nSubframes; ++n ) + { + if ( sns_stereo_mode[n] == SNS_STEREO_MODE_MS ) + { + push_next_indice( hBstr, zero_side_flag[n], 1 ); + sts[0]->side_bits_frame_channel++; + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ++ch ) + { + st = sts[ch]; + nbits_start_sns = hBstr->nb_bits_tot; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( n = 0; n < nSubframes; ++n ) + { + const int16_t is_side = ch == 1 && sns_stereo_mode[n] == SNS_STEREO_MODE_MS; + const int16_t *bits = ( nSubframes == 1 ) ? ivas_sns_cdbks_tcx20_bits : ivas_sns_cdbks_tcx10_bits; + int16_t nStages = ( ( nSubframes == 1 ) ? SNS_MSVQ_NSTAGES_TCX20 : SNS_MSVQ_NSTAGES_TCX10 ); + + if ( is_side ) + { + if ( zero_side_flag[n] ) + { + continue; + } + nStages = SNS_MSVQ_NSTAGES_SIDE; + bits = ( sts[ch]->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_bits : ivas_sns_cdbks_side_tcx10_bits; + } + for ( int16_t j = 0; j < nStages; ++j, ++idx ) + { + push_next_indice( hBstr, sns_vq_indices[idx], bits[j] ); + } + } + st->side_bits_frame_channel += hBstr->nb_bits_tot - nbits_start_sns; + } + } + else + { + /* write SNS parameter separately since at the decoder, both channels' cores need to be decoded before, so the joint SNS decoding can be done */ + skipped_first_channel = 0; + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + skipped_first_channel = 1; + continue; + } + + nbits_start_sns = hBstr->nb_bits_tot; + + num_sns = ( st->core == TCX_20_CORE ) ? 1 : NB_DIV; + + if ( ch == 0 || skipped_first_channel ) + { + push_next_indice( hBstr, param_lpc[0][0] >> 1, 1 ); + + if ( st->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) ) + { + /* write classifier decision to signal low br mode for SNS encoding, for all other configs, low_br mode is not possible */ + push_next_indice( hBstr, sns_low_br_mode, 1 ); + } + } +#ifdef IVAS_FLOAT_FIXED + encode_lpc_avq_ivas_fx( hBstr, num_sns, param_lpc[ch], st->core, st->element_mode ); +#else + encode_lpc_avq( hBstr, num_sns, param_lpc[ch], st->core, st->element_mode ); +#endif + + st->side_bits_frame_channel += hBstr->nb_bits_tot - nbits_start_sns; + } + } + + + /*update pitch buffer*/ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + if ( param_core[ch][1 + NOISE_FILL_RANGES] != 0 ) + { + set_f( pitch_buf[ch], ( st->hTcxEnc->tcxltp_pitch_int + (float) st->hTcxEnc->tcxltp_pitch_fr / (float) st->pit_res_max ) * (float) st->sr_core / (float) INT_FS_12k8, NB_SUBFR16k ); + } + else + { + set_f( pitch_buf[ch], L_SUBFR, NB_SUBFR16k ); + } + } + + pop_wmops(); + return; +} +#else +void ivas_mdct_core_whitening_enc( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ + float old_wsp[CPE_CHANNELS][L_WSP], /* i : 12.8kHz weighted speech (for LTP */ + float pitch_buf[CPE_CHANNELS][NB_SUBFR16k], /* o : floating pitch for each subframe */ + float *mdst_spectrum_long[CPE_CHANNELS], /* o : buffer for MDST spectrum */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* o : buffer TNS bits */ + float *orig_spectrum_long[CPE_CHANNELS], /* o : origingal spectrum w/o whitening */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* o : number of tns parameters put into prm */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to the parameter table */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t nChannels /* i : total number of coded channels */ +) +{ + int16_t n, ch, nSubframes, L_subframe, L_subframeTCX, tcx_subframe_coded_lines; + float A_q[CPE_CHANNELS][NB_DIV][M + 1]; + int16_t sns_vq_indices[CPE_CHANNELS * NB_DIV * SNS_MSVQ_NSTAGES_TCX10]; + int16_t sns_stereo_mode[NB_DIV]; + int16_t idx; + int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW]; + int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; + int16_t ltpBits[CPE_CHANNELS]; + int16_t i, T_op[CPE_CHANNELS][3]; + float *orig_spectrum[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ + float temp_buffer[15 * L_FRAME48k / 8]; + float *windowedSignal[CPE_CHANNELS]; + float *powerSpec = orig_spectrum_long[0]; + float *mdst_spectrum[CPE_CHANNELS][NB_DIV]; + float nrg; + Encoder_State *st, **sts; + float scf[CPE_CHANNELS][NB_DIV][M]; + float scf_q[CPE_CHANNELS][NB_DIV][M]; + float chE[2], chE_tot; + int8_t sns_low_br_mode; + int16_t nbits_start_sns; + int16_t num_sns; + int8_t skipped_first_channel; + int16_t zero_side_flag[NB_DIV]; + + push_wmops( "mdct_core_whitening" ); + + /*--------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + sts = hCPE->hCoreCoder; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + stereo_tcx_init_enc( sts[ch] ); + + set_s( tnsSize[ch], 0, 2 ); + set_s( tnsBits[ch], 0, 2 ); + ltpBits[ch] = 0; + + for ( i = 0; i < 3; i++ ) + { + T_op[ch][i] = sts[ch]->pitch[i]; + + /* check minimum pitch for quantization */ + if ( T_op[ch][i] < PIT_MIN_SHORTER ) + { + T_op[ch][i] *= 2; + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + orig_spectrum[ch][0] = orig_spectrum_long[ch]; + orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; + mdst_spectrum[ch][0] = mdst_spectrum_long[ch]; + mdst_spectrum[ch][1] = mdst_spectrum_long[ch] + N_TCX10_MAX; + } + + windowedSignal[0] = orig_spectrum_long[0]; /* NOTE temporarily available */ + windowedSignal[1] = temp_buffer; /* orig_spectrum_long isn't long enough */ + + /*--------------------------------------------------------------* + * TCX20/TCX10 switching decision + *---------------------------------------------------------------*/ + + if ( mct_on ) + { + sts[0]->hTcxEnc->tfm_mem = sts[1]->hTcxEnc->tfm_mem = sqrtf( 0.5f * ( sts[0]->hTcxEnc->tfm_mem * sts[0]->hTcxEnc->tfm_mem + sts[1]->hTcxEnc->tfm_mem * sts[1]->hTcxEnc->tfm_mem ) ); /* RMS */ + sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt = sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt = 0.5f * ( sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt + sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt ); + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + SetTCXModeInfo( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + } + + sts[0]->core = sts[0]->hTcxEnc->tcxMode; + sts[1]->core = sts[1]->hTcxEnc->tcxMode; + + /*--------------------------------------------------------------* + * Core Signal Analysis: MDCT, TNS + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + SetCurrentPsychParams( st->core, 0, st->hTcxCfg ); + + /* tcx ltp analysis on the 12.8kHz weighted speech, saves preproc resampling to sr_core */ + tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); + + core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); + + /* BWD in MDCT domain */ + if ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + bw_detect( st, NULL, st->hTcxEnc->spectrum[n], NULL, MC_FORMAT /*just cannot be ISM_FORMAT*/, mct_on ); + + if ( nSubframes == NB_DIV && n == 0 ) + { + st->last_input_bwidth = st->input_bwidth; + } + } + } + + if ( st->last_core == ACELP_CORE ) /* reset past kernel info */ + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + st->hTcxEnc->kernel_symmetry_past = 0; + } + } + + /*--------------------------------------------------------------* + * Transform Kernel Switching, Stereo Pre-Processing, and TNS + *---------------------------------------------------------------*/ + + sts[0]->hTcxEnc->fUseTns[1] = 0; + + if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on && !hCPE->hStereoMdct->isSBAStereoMode ) + { + int16_t nSampCore; + int32_t totalRate; + TCX_ENC_HANDLE hTcxEnc0, hTcxEnc1; + + nSampCore = ( sts[0]->igf ) ? max( sts[0]->hIGFEnc->infoStartLine, sts[1]->hIGFEnc->infoStartLine ) : 0; + totalRate = sts[0]->element_brate; + hTcxEnc0 = sts[0]->hTcxEnc; + hTcxEnc1 = sts[1]->hTcxEnc; -#ifdef IVAS_FLOAT_FIXED - init_tcx_enc_info_fx( sts[0], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#else init_tcx_enc_info( sts[0], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#endif if ( nSampCore == 0 ) { @@ -1043,31 +3310,9 @@ void ivas_mdct_core_whitening_enc( { if ( hTcxEnc0->transform_type[n] == hTcxEnc1->transform_type[n] ) { -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - q_com = L_get_q_buf1( hTcxEnc0->spectrum[n], hTcxEnc0->L_frameTCX / nSubframes ); - q_com = s_min( q_com, L_get_q_buf1( hTcxEnc1->spectrum[n], hTcxEnc1->L_frameTCX / nSubframes ) ); - q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[0][n], hTcxEnc0->L_frameTCX / nSubframes ) ); - q_com = s_min( q_com, L_get_q_buf1( mdst_spectrum[1][n], hTcxEnc1->L_frameTCX / nSubframes ) ); - - floatToFixed_arrL32( hTcxEnc0->spectrum[n], hTcxEnc0->spectrum_fx[n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); - floatToFixed_arrL32( hTcxEnc1->spectrum[n], hTcxEnc1->spectrum_fx[n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); - floatToFixed_arrL32( mdst_spectrum[0][n], mdst_spectrum_fx[0][n], q_com, hTcxEnc0->L_frameTCX / nSubframes ); - floatToFixed_arrL32( mdst_spectrum[1][n], mdst_spectrum_fx[1][n], q_com, hTcxEnc1->L_frameTCX / nSubframes ); - - hTcxEnc0->kernel_switch_corr_past = float_to_fix16( hTcxEnc0->kernel_switch_corr_past_flt, Q15 ); -#endif - const Word16 switchKernel = /* these 4 transform types can be applied: 0 = MDCT-IV, 1 = MDST-II, 2 = MDCT-II, 3 = MDST-IV */ - kernel_switch_detect_fx( hTcxEnc0->spectrum_fx[n], hTcxEnc1->spectrum_fx[n], mdst_spectrum_fx[0][n], mdst_spectrum_fx[1][n], q_com, nSampCore / nSubframes, - L_subframeTCX / nSubframes, hTcxEnc0->transform_type[n], &hTcxEnc0->kernel_switch_corr_past, ( totalRate * L_subframe ) / nSubframes ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - hTcxEnc0->kernel_switch_corr_past_flt = fix16_to_float( hTcxEnc0->kernel_switch_corr_past, Q15 ); -#endif -#else const int16_t switchKernel = /* these 4 transform types can be applied: 0 = MDCT-IV, 1 = MDST-II, 2 = MDCT-II, 3 = MDST-IV */ kernel_switch_detect( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / nSubframes, L_subframeTCX / nSubframes, hTcxEnc0->transform_type[n], &hTcxEnc0->kernel_switch_corr_past_flt, ( totalRate * L_subframe ) / nSubframes ); -#endif if ( switchKernel ) /* apply MDST-IV coding in one of the channels */ { hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 3 : 1 ) - max( 0, switchKernel ); @@ -1140,11 +3385,7 @@ void ivas_mdct_core_whitening_enc( continue; } -#ifdef IVAS_FLOAT_FIXED - init_tcx_enc_info_fx( sts[ch], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#else init_tcx_enc_info( sts[ch], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#endif nSubframes = ( hTcxEncCh->tcxMode == TCX_20 ) ? 1 : NB_DIV; for ( n = 0; n < nSubframes; n++ ) @@ -1179,11 +3420,7 @@ void ivas_mdct_core_whitening_enc( set_zero( chE, NB_DIV ); } -#ifdef IVAS_FLOAT_FIXED - init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#else init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#endif L_subframe = L_subframe / nSubframes; L_subframeTCX = ( mct_on ? L_subframeTCX / nSubframes : L_subframe ); @@ -1250,20 +3487,7 @@ void ivas_mdct_core_whitening_enc( if ( sts[0]->hTcxEnc->tcxMode == TCX_20 && sts[1]->hTcxEnc->tcxMode == TCX_20 && sts[0]->mct_chan_mode == MCT_CHAN_MODE_REGULAR && sts[1]->mct_chan_mode == MCT_CHAN_MODE_REGULAR ) { -#ifdef IVAS_FLOAT_FIXED - /*=================flt-2-fix==============*/ - Word16 exp_snl = 0, exp_snr = 0; - f2me_buf( scf[0][0], scf_fx[0][0], &exp_snl, M ); - f2me_buf( scf[1][0], scf_fx[1][0], &exp_snr, M ); - /*=================flt-2-fix==============*/ - sns_avq_cod_stereo_fx( scf_fx[0][0], exp_snl, scf_fx[1][0], exp_snr, sts[0]->L_frame, scf_q_fx[0][0], scf_q_fx[1][0], param_lpc[0], param_lpc[1] ); - /*===============fix-2-flt==========================*/ - fixedToFloat_arrL( scf_q_fx[0][0], scf_q[0][0], Q16, M ); - fixedToFloat_arrL( scf_q_fx[1][0], scf_q[1][0], Q16, M ); - /*===============fix-2-flt==========================*/ -#else sns_avq_cod_stereo( scf[0][0], scf[1][0], sts[0]->L_frame, scf_q[0][0], scf_q[1][0], param_lpc[0], param_lpc[1] ); -#endif } else { @@ -1275,31 +3499,6 @@ void ivas_mdct_core_whitening_enc( continue; } st = sts[ch]; -#ifdef IVAS_FLOAT_FIXED - Word16 exp_scf_1 = 0, exp_scf_0 = 0; - IF( st->hTcxEnc->tcxMode == TCX_20 ) - { - /*===============flt-2-fix==========================*/ - f2me_buf( scf[ch][0], scf_fx[ch][0], &exp_scf_0, M ); - /*===============flt-2-fix==========================*/ - sns_avq_cod_fx( scf_fx[ch][0], exp_scf_0, NULL, 0, scf_q_fx[ch][0], NULL, ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); - /*===============fix-2-flt==========================*/ - fixedToFloat_arrL( scf_q_fx[ch][0], scf_q[ch][0], Q16, M ); - /*===============fix-2-flt==========================*/ - } - ELSE - { - /*===============flt-2-fix==========================*/ - f2me_buf( scf[ch][1], scf_fx[ch][1], &exp_scf_1, M ); - f2me_buf( scf[ch][0], scf_fx[ch][0], &exp_scf_0, M ); - /*===============flt-2-fix==========================*/ - sns_avq_cod_fx( scf_fx[ch][1], exp_scf_1, scf_fx[ch][0], exp_scf_0, scf_q_fx[ch][1], scf_q_fx[ch][0], ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); - /*===============fix-2-flt==========================*/ - fixedToFloat_arrL( scf_q_fx[ch][0], scf_q[ch][0], Q16, M ); - fixedToFloat_arrL( scf_q_fx[ch][1], scf_q[ch][1], Q16, M ); - /*===============fix-2-flt==========================*/ - } -#else if ( st->hTcxEnc->tcxMode == TCX_20 ) { sns_avq_cod( scf[ch][0], NULL, scf_q[ch][0], NULL, ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); @@ -1308,7 +3507,6 @@ void ivas_mdct_core_whitening_enc( { sns_avq_cod( scf[ch][1], scf[ch][0], scf_q[ch][1], scf_q[ch][0], ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); } -#endif } } } @@ -1321,11 +3519,7 @@ void ivas_mdct_core_whitening_enc( } st = sts[ch]; nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; -#ifdef IVAS_FLOAT_FIXED - init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#else init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#endif L_subframe = L_subframe / nSubframes; L_subframeTCX = L_subframeTCX / nSubframes; @@ -1358,23 +3552,8 @@ void ivas_mdct_core_whitening_enc( { if ( st->hTcxEnc->transform_type[n] == TCX_5 ) { -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxEnc->spectrum_e[n] = Q31 - L_get_q_buf1( st->hTcxEnc->spectrum[n], st->hTcxCfg->tcx5SizeFB * 2 ); - floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], ( Q31 - st->hTcxEnc->spectrum_e[n] ), st->hTcxCfg->tcx5SizeFB * 2 ); - mdst_spectrum_e[ch][n] = Q31 - L_get_q_buf1( mdst_spectrum[ch][n], st->hTcxCfg->tcx5SizeFB * 2 ); - floatToFixed_arrL32( mdst_spectrum[ch][n], mdst_spectrum_fx[ch][n], ( Q31 - mdst_spectrum_e[ch][n] ), st->hTcxCfg->tcx5SizeFB * 2 ); -#endif - tcx5SpectrumDeinterleaving_fx( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum_fx[n] ); - tcx5SpectrumDeinterleaving_fx( st->hTcxCfg->tcx5SizeFB, mdst_spectrum_fx[ch][n] ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], ( Q31 - st->hTcxEnc->spectrum_e[n] ), st->hTcxCfg->tcx5SizeFB * 2 ); - fixedToFloat_arrL32( mdst_spectrum_fx[ch][n], mdst_spectrum[ch][n], ( Q31 - mdst_spectrum_e[ch][n] ), st->hTcxCfg->tcx5SizeFB * 2 ); -#endif -#else tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum[n] ); tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, mdst_spectrum[ch][n] ); -#endif } } } @@ -1391,11 +3570,7 @@ void ivas_mdct_core_whitening_enc( st = sts[ch]; nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; -#ifdef IVAS_FLOAT_FIXED - init_tcx_enc_info_fx( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#else init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); -#endif L_subframe = L_subframe / nSubframes; L_subframeTCX = L_subframeTCX / nSubframes; @@ -1446,23 +3621,7 @@ void ivas_mdct_core_whitening_enc( continue; } -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif - test(); - test(); - IF( ( ch > 0 ) && ( add( sts[0]->hTcxEnc->fUseTns[0], sts[0]->hTcxEnc->fUseTns[1] ) > 0 ) && !mct_on ) - { - enc_prm_pre_mdct_fx( st, param_core[ch], tnsSize[ch], p_param[ch], mct_on, hBstr ); - } - ELSE - { - enc_prm_pre_mdct_fx( st, param_core[ch], NULL, p_param[ch], mct_on, hBstr ); - } -#else enc_prm_pre_mdct( st, param_core[ch], ( ( ( ch > 0 ) && ( sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 ) && !mct_on ) ? tnsSize[ch] : NULL ), p_param[ch], mct_on, hBstr ); -#endif if ( ch > 0 && sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 && !mct_on ) { @@ -1575,11 +3734,7 @@ void ivas_mdct_core_whitening_enc( push_next_indice( hBstr, sns_low_br_mode, 1 ); } } -#ifdef IVAS_FLOAT_FIXED - encode_lpc_avq_ivas_fx( hBstr, num_sns, param_lpc[ch], st->core, st->element_mode ); -#else encode_lpc_avq( hBstr, num_sns, param_lpc[ch], st->core, st->element_mode ); -#endif st->side_bits_frame_channel += hBstr->nb_bits_tot - nbits_start_sns; } @@ -1624,24 +3779,23 @@ void ivas_mdct_quant_coder( ) { Encoder_State *st, **sts; - int16_t bitsAvailable, target_bits, nSubframes, ch, n; - int16_t L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ - int16_t L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ - int16_t L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ - int16_t tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 bitsAvailable, target_bits, nSubframes, ch, n; + Word16 L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ + Word16 L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ + Word16 L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ + Word16 tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ + Word16 noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ + Word16 hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ float fac_ns[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - int16_t nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ - int16_t hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ float ener[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ float gain_tcx[CPE_CHANNELS][NB_DIV]; /* global gain */ float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; - int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; - int16_t ignore_chan[CPE_CHANNELS]; - int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; - int16_t nbits_start, total_nbbits; - + Word16 param_core[CPE_CHANNELS][2 * NPRM_DIV]; + Word16 ignore_chan[CPE_CHANNELS]; + Word16 target_bitsTCX10[CPE_CHANNELS][NB_DIV]; + Word16 nbits_start, total_nbbits; push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; @@ -1649,8 +3803,6 @@ void ivas_mdct_quant_coder( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { set_f( fac_ns[ch], 0.0f, NB_DIV ); - set_s( nf_seed[ch], 0, NB_DIV ); - set_s( hm_active[ch], 0, NB_DIV ); set_f( ener[ch], 0.0f, NB_DIV ); set_f( gain_tcx[ch], 0.0f, NB_DIV ); } @@ -1659,6 +3811,7 @@ void ivas_mdct_quant_coder( { quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; + st = sts[ch]; if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) @@ -1749,15 +3902,7 @@ void ivas_mdct_quant_coder( } nbits_start = st->hBstr->nb_bits_tot; -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif - - writeTCXparam_fx( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#else writeTCXparam( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#endif total_nbbits = st->hBstr->nb_bits_tot - nbits_start - nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); @@ -1767,106 +3912,105 @@ void ivas_mdct_quant_coder( pop_wmops(); return; } +#endif #ifdef IVAS_FLOAT_FIXED void ivas_mdct_quant_coder_fx( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + Word16 p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { Encoder_State *st, **sts; - int16_t bitsAvailable, target_bits, nSubframes, ch, n; - int16_t L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ - int16_t L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ - int16_t L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ - int16_t tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ - float fac_ns[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - int16_t nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ - int16_t hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ - float ener[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ - float gain_tcx[CPE_CHANNELS][NB_DIV]; /* global gain */ - float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ - float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; - int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; - int16_t ignore_chan[CPE_CHANNELS]; - int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; - int16_t nbits_start, total_nbbits; -#ifdef IVAS_FLOAT_FIXED + Word16 bitsAvailable, target_bits, nSubframes, ch, n; + Word16 L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ + Word16 L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ + Word16 L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ + Word16 tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ + Word16 noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ + Word16 hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ + Word16 param_core[CPE_CHANNELS][2 * NPRM_DIV]; + Word16 ignore_chan[CPE_CHANNELS]; + Word16 target_bitsTCX10[CPE_CHANNELS][NB_DIV]; + Word16 nbits_start, total_nbbits; + Word16 fac_ns_fx[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - Word16 ener_fx[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ + Word32 ener_fx[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ Word16 gain_tcx_fx[CPE_CHANNELS][NB_DIV]; /* global gain */ - Word16 gain_tcx_e; + Word16 gain_tcx_e[CPE_CHANNELS][NB_DIV]; Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ Word32 *quantized_spectrum_fx[CPE_CHANNELS][NB_DIV]; -#endif + Word16 quantized_spectrum_e[CPE_CHANNELS][NB_DIV]; + Word16 ener_e[CPE_CHANNELS][NB_DIV]; + Word16 gain_tcx_ee; push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; -#ifdef IVAS_FLOAT_FIXED FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { set16_fx( fac_ns_fx[ch], 0, NB_DIV ); set16_fx( nf_seed[ch], 0, NB_DIV ); set16_fx( hm_active[ch], 0, NB_DIV ); - set16_fx( ener_fx[ch], 0, NB_DIV ); + set32_fx( ener_fx[ch], 0, NB_DIV ); + set32_fx( quantized_spectrum_long_fx[ch], 0, N_MAX ); set16_fx( gain_tcx_fx[ch], 0, NB_DIV ); + set16_fx( gain_tcx_e[ch], -1000, NB_DIV ); set16_fx( L_frame[ch], 0, NB_DIV ); - } -#endif - - - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) - { - set_f( fac_ns[ch], 0.0f, NB_DIV ); - set_s( nf_seed[ch], 0, NB_DIV ); - set_s( hm_active[ch], 0, NB_DIV ); - set_f( ener[ch], 0.0f, NB_DIV ); - set_f( gain_tcx[ch], 0.0f, NB_DIV ); + set16_fx( L_spec[ch], 0, NB_DIV ); } - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; - quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; -#ifdef IVAS_FLOAT_FIXED quantized_spectrum_fx[ch][0] = quantized_spectrum_long_fx[ch]; quantized_spectrum_fx[ch][1] = quantized_spectrum_long_fx[ch] + N_TCX10_MAX; -#endif st = sts[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { ignore_chan[ch] = 1; + move16(); continue; } - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + ignore_chan[ch] = 0; + move16(); - bitsAvailable = st->bits_frame_channel + nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ) + tnsBits[ch][0] + tnsBits[ch][1]; + bitsAvailable = add( add( st->bits_frame_channel, i_mult( nSubframes, NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ) ), add( tnsBits[ch][0], tnsBits[ch][1] ) ); /* calculate TCX10 target bits before to assure minimum amount is distributed between subframes */ - if ( st->hTcxEnc->tcxMode == TCX_10 ) + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_10 ) ) { - int16_t nTnsBitsTCX10Tmp[2]; + Word16 nTnsBitsTCX10Tmp[2]; nTnsBitsTCX10Tmp[0] = tnsBits[ch][0]; + move16(); nTnsBitsTCX10Tmp[1] = tnsBits[ch][1]; + move16(); - ivas_mdct_tcx10_bit_distribution( target_bitsTCX10[ch], bitsAvailable, nTnsBitsTCX10Tmp ); + ivas_mdct_tcx10_bit_distribution_fx( target_bitsTCX10[ch], bitsAvailable, nTnsBitsTCX10Tmp ); } - for ( n = 0; n < nSubframes; n++ ) + FOR( n = 0; n < nSubframes; n++ ) { - if ( nSubframes == 2 ) + IF( EQ_16( nSubframes, 2 ) ) { target_bits = target_bitsTCX10[ch][n]; + move16(); } - else + ELSE { - target_bits = bitsAvailable / nSubframes - tnsBits[ch][n]; + target_bits = sub( idiv1616( bitsAvailable, nSubframes ), tnsBits[ch][n] ); } assert( target_bits >= NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL + SMDCT_MINIMUM_ARITH_BITS ); @@ -1875,74 +4019,141 @@ void ivas_mdct_quant_coder_fx( * Quantize the MDCT spectrum * *-----------------------------------------------------------*/ - QuantizeTCXSpectrum( st, n, st->hTcxEnc->spectrum[n], NULL, NULL, tnsSize[ch][n], target_bits, 0, &L_frameTCX[ch][n], - &L_frame[ch][n], &L_spec[ch][n], &tcx_offset[ch][n], &noiseFillingBorder[ch][n], quantized_spectrum[ch][n], NULL, - &hm_active[ch][n], NULL, &nf_seed[ch][n], &ener[ch][n], &gain_tcx[ch][n], param_core[ch] + n * NPRM_DIV ); + QuantizeTCXSpectrum_fx( st, n, st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum_e[n], NULL, 0, NULL, tnsSize[ch][n], target_bits, 0, &L_frameTCX[ch][n], + &L_frame[ch][n], &L_spec[ch][n], &tcx_offset[ch][n], &noiseFillingBorder[ch][n], quantized_spectrum_fx[ch][n], &quantized_spectrum_e[ch][n], NULL, + &hm_active[ch][n], NULL, &nf_seed[ch][n], &ener_fx[ch][n], &ener_e[ch][n], &gain_tcx_fx[ch][n], &gain_tcx_e[ch][n], param_core[ch] + n * NPRM_DIV ); } } -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* Scaling buffers to common exp*/ + + Word16 temp_scale, min_shift = -1000; + move16(); FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; - floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); - st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); - st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); - st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); - st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], L_frame[ch][0] ) - 4 ); - st->hTcxEnc->spectrum_e[1] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[1], L_frame[ch][1] ) - 4 ); - floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); - floatToFixed_arrL( st->hTcxEnc->spectrum[1], st->hTcxEnc->spectrum_fx[1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } - floatToFixed_arrL( quantized_spectrum[ch][0], quantized_spectrum_fx[ch][0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); - floatToFixed_arrL( quantized_spectrum[ch][1], quantized_spectrum_fx[ch][1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); + FOR( n = 0; n < nSubframes; n++ ) + { + temp_scale = getScaleFactor32( quantized_spectrum_fx[ch][n], L_spec[ch][n] ); + scale_sig32( quantized_spectrum_fx[ch][n], L_spec[ch][n], temp_scale ); + quantized_spectrum_e[ch][n] = sub( quantized_spectrum_e[ch][n], temp_scale ); + min_shift = s_max( min_shift, quantized_spectrum_e[ch][n] ); + temp_scale = getScaleFactor32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n] ); + scale_sig32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n], temp_scale ); + st->hTcxEnc->spectrum_e[n] = sub( st->hTcxEnc->spectrum_e[n], temp_scale ); + min_shift = s_max( min_shift, st->hTcxEnc->spectrum_e[n] ); + } } - gain_tcx_e = Q_factor_arr( gain_tcx[0], NB_DIV ); - gain_tcx_e = 15 - min( gain_tcx_e, Q_factor_arr( gain_tcx[1], NB_DIV ) ); - floatToFixed_arr( gain_tcx[0], gain_tcx_fx[0], 15 - gain_tcx_e, NB_DIV ); - floatToFixed_arr( gain_tcx[1], gain_tcx_fx[1], 15 - gain_tcx_e, NB_DIV ); -#endif + min_shift = add( min_shift, 4 ); + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); - EstimateStereoTCXNoiseLevel_fx( sts, quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns_fx, param_core, MCT_flag ); + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arr( fac_ns[0], fac_ns_fx[0], Q15, NB_DIV ); - floatToFixed_arr( fac_ns[1], fac_ns_fx[1], Q15, NB_DIV ); -#endif -#else - EstimateStereoTCXNoiseLevel( sts, quantized_spectrum, gain_tcx, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns, param_core, MCT_flag ); -#endif - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( n = 0; n < nSubframes; n++ ) + { + scale_sig32( quantized_spectrum_fx[ch][n], L_spec[ch][n], sub( quantized_spectrum_e[ch][n], min_shift ) ); + quantized_spectrum_e[ch][n] = min_shift; + move16(); + scale_sig32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n], sub( st->hTcxEnc->spectrum_e[n], min_shift ) ); + st->hTcxEnc->spectrum_e[n] = min_shift; + move16(); + } + } + + gain_tcx_ee = s_max( gain_tcx_e[0][0], gain_tcx_e[0][1] ); + gain_tcx_ee = s_max( gain_tcx_ee, gain_tcx_e[1][0] ); + gain_tcx_ee = s_max( gain_tcx_ee, gain_tcx_e[1][1] ); + gain_tcx_fx[0][0] = shl( gain_tcx_fx[0][0], sub( gain_tcx_e[0][0], gain_tcx_ee ) ); + gain_tcx_fx[0][1] = shl( gain_tcx_fx[0][1], sub( gain_tcx_e[0][1], gain_tcx_ee ) ); + gain_tcx_fx[1][0] = shl( gain_tcx_fx[1][0], sub( gain_tcx_e[1][0], gain_tcx_ee ) ); + gain_tcx_fx[1][1] = shl( gain_tcx_fx[1][1], sub( gain_tcx_e[1][1], gain_tcx_ee ) ); + + EstimateStereoTCXNoiseLevel_fx( sts, quantized_spectrum_fx, gain_tcx_fx, gain_tcx_ee, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns_fx, param_core, MCT_flag ); + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; /* update the pointer to the buffer of indices of the second channel */ - if ( ch > 0 ) + IF( ch > 0 ) { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { /*Enable appropriate upadte of tcx_curr_overlap_mode even for uncoded channel index 1*/ L_frameTCX[ch][0] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; L_frameTCX[ch][1] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + L_frameTCX[ch][0] = shr( st->hTcxEnc->L_frameTCX, 1 ); + L_frameTCX[ch][1] = shr( st->hTcxEnc->L_frameTCX, 1 ); + } + ELSE + { + L_frameTCX[ch][0] = st->hTcxEnc->L_frameTCX; + move16(); + L_frameTCX[ch][1] = st->hTcxEnc->L_frameTCX; + move16(); + } L_frame[ch][0] = st->L_frame; + move16(); L_frame[ch][1] = st->L_frame; + move16(); } - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; - for ( n = 0; n < nSubframes; n++ ) + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( n = 0; n < nSubframes; n++ ) { /* Update L_frame_past */ st->L_frame_past = L_frame[ch][n]; + move16(); /* Update overlap */ - if ( ( ( ( L_frameTCX[ch][n] == st->hTcxEnc->L_frameTCX >> 1 ) && n > 0 ) || ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) + test(); + test(); + test(); + IF( ( ( EQ_16( L_frameTCX[ch][n], shr( st->hTcxEnc->L_frameTCX, 1 ) ) && n > 0 ) || EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) && EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) { st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); } } @@ -1950,21 +4161,14 @@ void ivas_mdct_quant_coder_fx( * Generate Bitstream *---------------------------------------------------------------*/ - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { continue; } nbits_start = st->hBstr->nb_bits_tot; - -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif + move16(); writeTCXparam_fx( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#else - writeTCXparam( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#endif total_nbbits = st->hBstr->nb_bits_tot - nbits_start - nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); diff --git a/lib_enc/ivas_omasa_enc.c b/lib_enc/ivas_omasa_enc.c index b6bf286c93900c025d13ece907e6c0d8703436d6..2bcaf05aff4e77caf6a2d871956a678cd184053e 100644 --- a/lib_enc/ivas_omasa_enc.c +++ b/lib_enc/ivas_omasa_enc.c @@ -55,12 +55,36 @@ static void ivas_omasa_param_est_enc( OMASA_ENC_HANDLE hOMasa, OMASA_ENCODER_DAT static void ivas_omasa_energy_and_ratio_est( OMASA_ENC_HANDLE hOMasa, OMASA_ENCODER_DATA_HANDLE hOmasaData, float *data_f[], const int16_t input_frame, const int16_t nchan_inp ); +#ifndef IVAS_FLOAT_FIXED static void ivas_omasa_dmx( float *data_in_f[], float data_out_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_transport, const int16_t nchan_ism, ISM_METADATA_HANDLE hIsmMeta[], float prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], const float interpolator[L_FRAME48k] ); - +#else +static void ivas_omasa_dmx_fx( + Word32 *data_in[], /*i:Qx*/ + Word32 data_out[][L_FRAME48k], /*i:Qx*/ + const Word16 input_frame, /*i:q0*/ + const Word16 nchan_transport, /*i:q0*/ + const Word16 nchan_ism, /*i:q0*/ + ISM_METADATA_HANDLE hIsmMeta[], /*i*/ + Word16 prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], /*o:q15*/ + const Word16 interpolator[L_FRAME48k] /*i:q15*/ +); +#endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +static void computeIntensityVector_enc_fx( + const Word16 *band_grouping, /* i : Band grouping for estimation */ + Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */ + Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal */ + const Word16 num_frequency_bands, /* i : Number of frequency bands */ + Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS], /* o : Intensity vector */ + Word16 guard_bits ); +#else static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], const int16_t num_frequency_bands, float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS] ); - +#endif // IVAS_FLOAT_FIXED +#ifndef IVAS_FLOAT_FIXED static void computeReferencePower_omasa( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], float *reference_power, const int16_t enc_param_start_band, const int16_t num_freq_bands ); - +#else +static void computeReferencePower_omasa_ivas_fx( const Word16 *band_grouping, Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], Word32 *reference_power, const Word16 enc_param_start_band, const Word16 num_freq_bands, Word16 *ref_exp ); +#endif /*--------------------------------------------------------------------------* * ivas_omasa_enc_open() * @@ -267,7 +291,7 @@ ivas_error ivas_omasa_enc_config( } /* reconfigure core-coders for ISMs */ - if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, 1, 2, st_ivas->nSCE > 0 ? sep_object_brate[k - 2][st_ivas->nSCE - 1] : 0, ivas_total_brate - ism_total_brate, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, 1, 2, st_ivas->nSCE > 0 ? sep_object_brate[k - 2][st_ivas->nSCE - 1] : 0, ivas_total_brate - ism_total_brate, MC_MODE_NONE ) ) != IVAS_ERR_OK ) { return error; } @@ -322,7 +346,11 @@ ivas_error ivas_omasa_enc_config( if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) { /* Configure oMASA analysis based on MASA config */ +#ifdef IVAS_FLOAT_FIXED + ivas_omasa_set_config_fx( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hEncoderConfig->input_Fs, st_ivas->ism_mode ); +#else ivas_omasa_set_config( st_ivas->hOMasa, st_ivas->hMasa, st_ivas->hEncoderConfig->input_Fs, st_ivas->ism_mode ); +#endif // IVAS_FLOAT_FIXED } return IVAS_ERR_OK; @@ -334,7 +362,78 @@ ivas_error ivas_omasa_enc_config( * * Frame-by-frame config for oMASA *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_omasa_set_config_fx( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ + const Word32 input_Fs, /* i : Input sample rate */ + const ISM_MODE ism_mode /* i : ISM mode */ +) +{ + UWord8 i, maxBin; + /* Determine the number of bands */ + test(); + IF( EQ_16( ism_mode, ISM_MODE_NONE ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + /* use full resolution for the ISM+MASA merge and reduce later */ + hOMasa->nbands = 24; + } + ELSE + { + hOMasa->nbands = hMasa->config.numCodingBands; + } + move16(); + + hOMasa->nCodingBands = hMasa->config.numCodingBands; + move16(); + + /* Determine the number of subframes */ + IF( EQ_16( hMasa->config.joinedSubframes, TRUE ) ) + hOMasa->nSubframes = 1; + ELSE + hOMasa->nSubframes = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + + /* Determine band grouping */ + IF( EQ_16( hOMasa->nbands, 24 ) ) + { + Copy( MASA_band_grouping_24, hOMasa->band_grouping, 24 + 1 ); + } + ELSE + { + FOR( i = 0; i < hOMasa->nbands + 1; i++ ) + { + hOMasa->band_grouping[i] = MASA_band_grouping_24[hMasa->data.band_mapping[i]]; + move16(); + } + } + + maxBin = (UWord8) L_shr( L_add( Mpy_32_32( L_shl( input_Fs, 1 ), INV_CLDFB_BANDWIDTH_Q31 ), 1 ), 1 ); /*(uint8_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f )*/ + move16(); + + FOR( i = 1; i < hOMasa->nbands + 1; i++ ) + { + IF( GE_16( hOMasa->band_grouping[i], maxBin ) ) + { + hOMasa->band_grouping[i] = maxBin; + hOMasa->nbands = i; + move16(); + move16(); + BREAK; + } + } + + Copy( DirAC_block_grouping, hOMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + IF( EQ_16( hOMasa->nSubframes, 1 ) ) + { + hOMasa->block_grouping[1] = hOMasa->block_grouping[MAX_PARAM_SPATIAL_SUBFRAMES]; + move16(); + } + + return; +} +#else void ivas_omasa_set_config( OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ MASA_ENCODER_HANDLE hMasa, /* i : MASA encoder handle */ @@ -393,6 +492,7 @@ void ivas_omasa_set_config( return; } +#endif // IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* @@ -400,6 +500,262 @@ void ivas_omasa_set_config( * * Main OMASA encoding function *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_omasa_enc( + OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ + MASA_ENCODER_HANDLE hMasa, /* i/o: MASA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + float *data_in_f[], /* i/o: Input / transport audio signals */ + Word32 *data_in[], /* i/o: Input / transport audio signals */ + Word16 q_data, /* i:Q0 Stores the q for data_in_f */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_transport, /* i : Number of transport channels */ + const int16_t nchan_ism, /* i : Number of objects for parameter analysis */ + const ISM_MODE ism_mode, /* i : ISM mode */ + float *data_separated_object, /* o : Separated object audio signal */ + int16_t *idx_separated_object /* o : Index of the separated object */ +) +{ + int16_t i, j; + float data_out_f[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k]; +#ifdef IVAS_FLOAT_FIXED + Word32 data_out[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k]; +#endif // IVAS_FLOAT_FIXED + + /* Determine separated object (when applicable) */ + if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + float broadband_energy[MAX_NUM_OBJECTS + MASA_MAX_TRANSPORT_CHANNELS]; + int16_t loudest_object; + int16_t selected_object; + int16_t nchan_all_inp; + float alpha; + uint8_t fade_out_separate_object; + uint8_t fade_in_separate_object; + + /* Estimate broadband energies */ + nchan_all_inp = nchan_ism + nchan_transport; + set_zero( broadband_energy, nchan_all_inp ); + for ( i = 0; i < nchan_all_inp; i++ ) + { + for ( j = 0; j < input_frame; j++ ) + { + broadband_energy[i] += data_in_f[i][j] * data_in_f[i][j]; + } + } + + /* Temporal averaging */ + alpha = 0.8f; + for ( i = 0; i < nchan_all_inp; i++ ) + { + hOMasa->broadband_energy_sm[i] = ( 1.0f - alpha ) * broadband_energy[i] + alpha * hOMasa->broadband_energy_sm[i]; + } + + /* Determine loudest object */ + loudest_object = 0; + for ( i = 1; i < nchan_ism; i++ ) + { + if ( hOMasa->broadband_energy_sm[i] > hOMasa->broadband_energy_sm[loudest_object] ) + { + loudest_object = i; + } + } + + /* Determine object to separate */ + selected_object = hOMasa->prev_selected_object; + fade_out_separate_object = 0; + fade_in_separate_object = 0; + if ( hOMasa->changing_object ) + { + hOMasa->changing_object = 0; + selected_object = loudest_object; + fade_in_separate_object = 1; + } + else + { + if ( loudest_object != hOMasa->prev_selected_object ) + { + float selected_ene; + float total_ene; + float selected_ratio; + float adaptive_threshold_dB; + float ratio_objects_dB; + float hardswitch_threshold = 0.25f; + + /* Compute the energy of the current and the previous selected object in the current and the previous frame */ + selected_ene = broadband_energy[loudest_object] + broadband_energy[hOMasa->prev_selected_object] + hOMasa->broadband_energy_prev[loudest_object] + hOMasa->broadband_energy_prev[hOMasa->prev_selected_object]; + + /* Compute the energy of all objects and MASA channels in the current and the previous frame */ + total_ene = 0.0f; + for ( i = 0; i < nchan_all_inp; i++ ) + { + total_ene += broadband_energy[i] + hOMasa->broadband_energy_prev[i]; + } + + /* Compute the ratio */ + selected_ratio = selected_ene / ( total_ene + EPSILON ); + + adaptive_threshold_dB = selected_ratio * 9.0f + 1.0f; /* selected ratio = 0 -> 1 dB, selected ratio = 1 -> 10 dB */ + ratio_objects_dB = 10.0f * log10f( hOMasa->broadband_energy_sm[loudest_object] / ( hOMasa->broadband_energy_sm[hOMasa->prev_selected_object] + EPSILON ) ); + + /* Adaptively determine whether to change the separated object. If they are quiet compared to the total energy, change easier, as other signals mask the change. */ + if ( ratio_objects_dB > adaptive_threshold_dB ) + { + if ( selected_ratio < hardswitch_threshold ) /* If low level compared to all audio channels, perform hardswitch */ + { + selected_object = loudest_object; + } + else /* If high level compared to all audio channels, perform switch via fade out fade in */ + { + hOMasa->changing_object = 1; + fade_out_separate_object = 1; + } + } + } + } + + /* Set values for next frame */ + for ( i = 0; i < nchan_all_inp; i++ ) + { + hOMasa->broadband_energy_prev[i] = broadband_energy[i]; + } + hOMasa->prev_selected_object = selected_object; + + /* Separate the selected object */ + *idx_separated_object = selected_object; + mvr2r( data_in_f[selected_object], data_separated_object, input_frame ); + if ( fade_out_separate_object ) + { + v_mult( data_separated_object, hOMasa->fade_out_gain, data_separated_object, input_frame ); + v_mult( data_in_f[selected_object], hOMasa->fade_in_gain, data_in_f[selected_object], input_frame ); + } + else if ( fade_in_separate_object ) + { + v_mult( data_separated_object, hOMasa->fade_in_gain, data_separated_object, input_frame ); + v_mult( data_in_f[selected_object], hOMasa->fade_out_gain, data_in_f[selected_object], input_frame ); + } + else + { + set_zero( data_in_f[selected_object], input_frame ); + } + } + + /* Analysis */ + if ( ism_mode == ISM_MODE_NONE || ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + OMASA_SPATIAL_META OMasaMeta; /* working memory for the ISM-object MASA-parameters */ + OMASA_SPATIAL_META_HANDLE hOMasaMeta; + uint8_t n_bands_orig, n_subframes_orig; + uint8_t numCodingBands_orig, joinedSubframes_orig; + + hOMasaMeta = &OMasaMeta; + hOMasaMeta->num_dirs = 1; + + /* merge MASA directions before adding ISM to the mixture */ + if ( hMasa->config.numberOfDirections == 2 ) + { + n_bands_orig = hMasa->config.numCodingBands; + hMasa->config.numCodingBands = MASA_FREQUENCY_BANDS; + + ivas_masa_combine_directions( hMasa ); + + hMasa->config.numCodingBands = (int8_t) n_bands_orig; + } + + /* force computation into high resolution */ + + n_subframes_orig = hOMasa->nSubframes; + hOMasa->nSubframes = MAX_PARAM_SPATIAL_SUBFRAMES; + + /* Estimate MASA parameters from the objects */ + /* NB: only first direction is populated */ + /* NB2: in energy_ratios and surround_coherence only first sub-frame contains valid data */ + ivas_omasa_param_est_enc( hOMasa, hMasa->data.hOmasaData, hIsmMeta, data_in_f, hOMasaMeta->directional_meta[0].elevation, hOMasaMeta->directional_meta[0].azimuth, hOMasaMeta->directional_meta[0].energy_ratio[0], hOMasaMeta->directional_meta[0].spread_coherence, hOMasaMeta->common_meta.surround_coherence[0], + hOMasaMeta->common_meta.diffuse_to_total_ratio[0], input_frame, nchan_ism ); + + /* copy energy_ratios and surrCoh from first sub-frame to the remaining ones */ + for ( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + mvr2r( hOMasaMeta->directional_meta[0].energy_ratio[0], hOMasaMeta->directional_meta[0].energy_ratio[i], MASA_FREQUENCY_BANDS ); + mvr2r( hOMasaMeta->common_meta.surround_coherence[0], hOMasaMeta->common_meta.surround_coherence[i], MASA_FREQUENCY_BANDS ); + mvr2r( hOMasaMeta->common_meta.diffuse_to_total_ratio[0], hOMasaMeta->common_meta.diffuse_to_total_ratio[i], MASA_FREQUENCY_BANDS ); + } + + /* restore resolution parameters */ + hOMasa->nSubframes = n_subframes_orig; + + /* perform MASA+ISM merge in full resolution */ + numCodingBands_orig = hMasa->config.numCodingBands; + joinedSubframes_orig = hMasa->config.joinedSubframes; + + hMasa->config.numCodingBands = hOMasa->nbands; + hMasa->config.joinedSubframes = 0; + + ivas_merge_masa_metadata( hMasa, hOMasaMeta ); /* => merge result in hMasa->masaMetadata */ + + hMasa->config.numCodingBands = numCodingBands_orig; + hMasa->config.joinedSubframes = joinedSubframes_orig; + } + else if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + /* Estimate energies and ratios */ + ivas_omasa_energy_and_ratio_est( hOMasa, hMasa->data.hOmasaData, data_in_f, input_frame, nchan_ism ); + } + + /* Downmix */ +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + for ( j = 0; j < nchan_ism; j++ ) + { + for ( int k = 0; k < input_frame; k++ ) + { + data_in[j][k] = float_to_fix( data_in_f[j][k], q_data ); + } + } + for ( i = 0; i < nchan_ism; i++ ) + { + for ( j = 0; j < nchan_transport; j++ ) + { + hOMasa->prev_object_dm_gains_fx[i][j] = float_to_fix16( hOMasa->prev_object_dm_gains[i][j], 15 ); + } + } + for ( i = 0; i < input_frame; i++ ) + { + hOMasa->interpolator_fx[i] = float_to_fix16( hOMasa->interpolator[i], 15 ); + } + FOR( i = 0; i < nchan_ism; i++ ) + { + hIsmMeta[i]->azimuth_fx = float_to_fix( hIsmMeta[i]->azimuth, Q22 ); + hIsmMeta[i]->elevation_fx = float_to_fix( hIsmMeta[i]->elevation, Q22 ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + ivas_omasa_dmx_fx( data_in, data_out, input_frame, nchan_transport, nchan_ism, hIsmMeta, hOMasa->prev_object_dm_gains_fx, hOMasa->interpolator_fx ); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + for ( i = 0; i < nchan_transport; i++ ) + { + fixedToFloat_arrL( data_out[i], data_out_f[i], q_data, input_frame ); + } + for ( i = 0; i < nchan_ism; i++ ) + { + for ( j = 0; j < nchan_transport; j++ ) + { + hOMasa->prev_object_dm_gains[i][j] = fixedToFloat( hOMasa->prev_object_dm_gains_fx[i][j], 15 ); + } + } +#endif + + /* Move the ISM metadata to the first entry for encoding in the MASA_ONE_OBJ mode */ + if ( ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + hIsmMeta[0]->azimuth = hIsmMeta[*idx_separated_object]->azimuth; + hIsmMeta[0]->elevation = hIsmMeta[*idx_separated_object]->elevation; + } + + /* Merge transport signals */ + ivas_merge_masa_transports( data_out_f, &( data_in_f[nchan_ism] ), data_in_f, input_frame, nchan_transport ); + + return; +} +#else void ivas_omasa_enc( OMASA_ENC_HANDLE hOMasa, /* i/o: OMASA encoder handle */ @@ -612,6 +968,7 @@ void ivas_omasa_enc( return; } +#endif // IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* @@ -757,6 +1114,7 @@ void ivas_set_ism_importance_interformat( * set bit-rate surplus in combined format coding *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void ivas_set_surplus_brate_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ #ifdef DEBUG_MODE_INFO @@ -765,7 +1123,8 @@ void ivas_set_surplus_brate_enc( #endif ) { - if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + test(); + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) { #ifndef IVAS_FLOAT_FIXED st_ivas->hCPE[0]->brate_surplus = st_ivas->hSCE[0]->element_brate - ivas_interformat_brate( ISM_MASA_MODE_PARAM_ONE_OBJ, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ); @@ -775,13 +1134,14 @@ void ivas_set_surplus_brate_enc( #endif /* note: ISM st->total_brate is iset in ivas_sce_enc() */ } - else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) { /* it is already set in ivas_ism_enc() */ } - else + ELSE { st_ivas->hCPE[0]->brate_surplus = 0; + move32(); } #ifdef DEBUG_MODE_INFO @@ -813,6 +1173,29 @@ void ivas_set_surplus_brate_enc( return; } +#else +void ivas_set_surplus_brate_enc( + Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +) +{ + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + st_ivas->hCPE[0]->brate_surplus = st_ivas->hSCE[0]->element_brate - ivas_interformat_brate( ISM_MASA_MODE_PARAM_ONE_OBJ, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ); + /* note: ISM st->total_brate is iset in ivas_sce_enc() */ + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + /* it is already set in ivas_ism_enc() */ + } + else + { + st_ivas->hCPE[0]->brate_surplus = 0; + } + + + return; +} +#endif /*--------------------------------------------------------------------------* * ivas_omasa_ener_brate() @@ -821,6 +1204,78 @@ void ivas_set_surplus_brate_enc( *--------------------------------------------------------------------------*/ /*! r: OMASA energy bitrate flag */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_omasa_ener_brate_fx( + const Word16 nchan_ism, /* i : number of ISMs */ + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + Word32 *data_f[], /* i : Input / transport audio signals */ + const Word16 input_frame, /* i : Input frame size */ + Word16 data_e /*i:exponent for data_f */ +) +{ + Word16 i, flag_omasa_ener_brate; + Word32 energy_ism, energy_masa; + Word16 energy_ism_e, energy_masa_e; + Word32 temp_32; + Word16 temp, temp_e; + flag_omasa_ener_brate = 0; + energy_ism_e = 0; + energy_masa_e = 0; + move16(); + move16(); + move16(); + + test(); + IF( GE_16( nchan_ism, 3 ) && EQ_32( ivas_total_brate, IVAS_128k ) ) + { + energy_ism = 0; + move32(); + FOR( i = 0; i < nchan_ism; i++ ) + { + temp_e = data_e; + move16(); + temp_32 = sum2_32_fx( data_f[i], input_frame, &temp_e ); + energy_ism = BASOP_Util_Add_Mant32Exp( energy_ism, energy_ism_e, temp_32, temp_e, &energy_ism_e ); + } + + energy_masa = 0; + move32(); + FOR( i = nchan_ism; i < nchan_ism + MASA_MAXIMUM_DIRECTIONS; i++ ) + { + temp_e = data_e; + move16(); + temp_32 = sum2_32_fx( data_f[i], input_frame, &temp_e ); + energy_masa = BASOP_Util_Add_Mant32Exp( energy_masa, energy_masa_e, temp_32, temp_e, &energy_masa_e ); + } + IF( energy_masa_e < 0 ) + { + energy_masa = L_shl( energy_masa, energy_masa_e ); + energy_masa_e = 0; + move16(); + } + energy_masa = L_shr( energy_masa, 1 ); + energy_masa_e = add( energy_masa_e, 1 ); + temp = divide1616( 2, nchan_ism ); /*q15*/ + energy_ism = BASOP_Util_Divide3232_Scale( energy_ism, L_add( energy_masa, L_shr( ONE_IN_Q31, energy_masa_e ) ), &temp_e ); + energy_ism_e = add( temp_e, sub( energy_ism_e, energy_masa_e ) ); + energy_ism = Mpy_32_16_1( energy_ism, temp ); + IF( energy_ism_e < 0 ) + { + energy_ism = L_shl( energy_ism, energy_ism_e ); + energy_ism_e = 0; + move16(); + } + + IF( LT_32( energy_ism, L_shr( ONE_IN_Q31, energy_ism_e ) ) ) + { + flag_omasa_ener_brate = 1; + move16(); + } + } + + return flag_omasa_ener_brate; +} +#else int16_t ivas_omasa_ener_brate( const int16_t nchan_ism, /* i : number of ISMs */ const int32_t ivas_total_brate, /* i : IVAS total bitrate */ @@ -857,7 +1312,7 @@ int16_t ivas_omasa_ener_brate( return flag_omasa_ener_brate; } - +#endif // IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* * Local functions @@ -880,6 +1335,10 @@ static void ivas_omasa_param_est_enc( const int16_t nchan_ism ) { float reference_power[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#ifdef IVAS_FLOAT_FIXED + Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; // Q(31-ref_exp) + Word16 ref_exp; +#endif int16_t ts, i, j, d, k; int16_t num_freq_bins, num_freq_bands, index; float dir_v[DIRAC_NUM_DIMS]; @@ -893,7 +1352,17 @@ static void ivas_omasa_param_est_enc( float Chnl_ImagBuffer[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX]; float Foa_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float Foa_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; +#ifdef IVAS_FLOAT_FIXED + Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; // Q6 + Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; // Q6 +#endif float intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; +#ifdef IVAS_FLOAT_FIXED + Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word16 Foa_RealBuffer_e; /*exponent for Foa_RealBuffer_fx*/ + Word16 Foa_ImagBuffer_e; /*exponent for Foa_ImagBuffer_fx*/ + Word16 intensity_real_e; /*exponent for intensity_real_fx*/ +#endif // IVAS_FLOAT_FIXED float direction_vector[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; float diffuseness_vector[MASA_FREQUENCY_BANDS]; int16_t band_m_idx, block_m_idx; @@ -901,6 +1370,19 @@ static void ivas_omasa_param_est_enc( float norm_tmp; int16_t mrange[2], brange[2]; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*To be removed later*/ + set_f( &Foa_RealBuffer[0][0], 0, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); + set_f( &Foa_ImagBuffer[0][0], 0, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); + set_f( &intensity_real[0][0], 0, DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS ); + /*To be removed later*/ +#endif + set32_fx( &Foa_RealBuffer_fx[0][0], 0, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); + set32_fx( &Foa_ImagBuffer_fx[0][0], 0, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); + set32_fx( &intensity_real_fx[0][0], 0, DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS ); +#endif // IVAS_FLOAT_FIXED + num_freq_bins = hOMasa->cldfbAnaEnc[0]->no_channels; num_freq_bands = hOMasa->nbands; l_ts = input_frame / CLDFB_NO_COL_MAX; @@ -992,12 +1474,57 @@ static void ivas_omasa_param_est_enc( } /* Direction estimation */ - computeIntensityVector_enc( hOMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, num_freq_bands, intensity_real ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + f2me_buf( &Foa_RealBuffer[0][0], &Foa_RealBuffer_fx[0][0], &Foa_RealBuffer_e, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); + f2me_buf( &Foa_ImagBuffer[0][0], &Foa_ImagBuffer_fx[0][0], &Foa_ImagBuffer_e, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + /*scaling real and imaginary buffers so they have same exponent for computeIntensityVector_enc*/ + IF( GT_16( Foa_ImagBuffer_e, Foa_RealBuffer_e ) ) + { + Scale_sig32( &Foa_RealBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX, sub( Foa_RealBuffer_e, Foa_ImagBuffer_e ) ); + Foa_RealBuffer_e = Foa_ImagBuffer_e; + move16(); + } + ELSE + { + Scale_sig32( &Foa_ImagBuffer_fx[0][0], FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX, sub( Foa_ImagBuffer_e, Foa_RealBuffer_e ) ); + Foa_ImagBuffer_e = Foa_RealBuffer_e; + move16(); + } + Word16 band_grouping_diff[MASA_FREQUENCY_BANDS], guard_bits, max_band_grouping_diff; + FOR( i = 0; i < num_freq_bands; i++ ) + { + band_grouping_diff[i] = sub( hOMasa->band_grouping[i + 1], hOMasa->band_grouping[i] ); + move16(); + } + maximum_abs_16_fx( band_grouping_diff, num_freq_bands, &max_band_grouping_diff ); + guard_bits = add( find_guarded_bits_fx( max_band_grouping_diff ), 1 ); + computeIntensityVector_enc_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx, guard_bits ); + intensity_real_e = add( add( Foa_RealBuffer_e, Foa_ImagBuffer_e ), guard_bits ); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + me2f_buf( &intensity_real_fx[0][0], intensity_real_e, &intensity_real[0][0], DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED +#endif // IVAS_FLOAT_FIXED computeDirectionVectors( intensity_real[0], intensity_real[1], intensity_real[2], 0, num_freq_bands, direction_vector[0], direction_vector[1], direction_vector[2] ); /* Power estimation for diffuseness */ +#ifndef IVAS_FLOAT_FIXED computeReferencePower_omasa( hOMasa->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, reference_power[ts], 0, num_freq_bands ); - +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Q for Foa_RealBuffer_fx and Foa_ImagBuffer is assumed to be 6 + for ( int r = 0; r < FOA_CHANNELS; r++ ) + { + floatToFixed_arrL( Foa_RealBuffer[r], Foa_RealBuffer_fx[r], 6, CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL( Foa_ImagBuffer[r], Foa_ImagBuffer_fx[r], 6, CLDFB_NO_CHANNELS_MAX ); + } +#endif + computeReferencePower_omasa_ivas_fx( hOMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], 0, num_freq_bands, &ref_exp ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( reference_power_fx[ts], reference_power[ts], 31 - ref_exp, num_freq_bands ); +#endif +#endif /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hOMasa->index_buffer_intensity = ( hOMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ index = hOMasa->index_buffer_intensity; @@ -1350,6 +1877,62 @@ static void ivas_omasa_energy_and_ratio_est( /* Compute downmix */ +#ifdef IVAS_FLOAT_FIXED +static void ivas_omasa_dmx_fx( + Word32 *data_in[], /*i:Qx*/ + Word32 data_out[][L_FRAME48k], /*i:Qx*/ + const Word16 input_frame, /*i:q0*/ + const Word16 nchan_transport, /*i:q0*/ + const Word16 nchan_ism, /*i:q0*/ + ISM_METADATA_HANDLE hIsmMeta[], /*i*/ + Word16 prev_gains[][MASA_MAX_TRANSPORT_CHANNELS], /*o:q15*/ + const Word16 interpolator[L_FRAME48k] /*i:q15*/ +) +{ + Word16 i, j, k; + Word16 azimuth, elevation; + Word16 gains[MASA_MAX_TRANSPORT_CHANNELS]; + Word16 g1, g2; + + FOR( i = 0; i < nchan_transport; i++ ) + { + set_zero_fx( data_out[i], input_frame ); + } + + FOR( i = 0; i < nchan_ism; i++ ) + { + azimuth = extract_l( L_shr( L_add( hIsmMeta[i]->azimuth_fx, ONE_IN_Q21 ), 22 ) ); /* scaling from q22 to q0 for ivas_get_stereo_panning_gains_fx*/ + elevation = extract_l( L_shr( L_add( hIsmMeta[i]->elevation_fx, ONE_IN_Q21 ), 22 ) ); /* scaling from q22 to q0 for ivas_get_stereo_panning_gains_fx*/ + + /*gains is q15*/ + /*azimuth is q0*/ + /*elevation is q0*/ + ivas_get_stereo_panning_gains_fx( azimuth, elevation, gains ); + + /* Downmix using the panning gains */ + FOR( j = 0; j < nchan_transport; j++ ) + { + test(); + IF( abs_s( gains[j] ) > 0 || abs_s( prev_gains[i][j] ) > 0 ) + { + FOR( k = 0; k < input_frame; k++ ) + { + g1 = interpolator[k]; + move16(); + g2 = sub( MAX_WORD16, g1 ); /*q15*/ + data_out[j][k] = L_add( data_out[j][k], Mpy_32_32( L_add( L_mult( g1, gains[j] ), L_mult( g2, prev_gains[i][j] ) ) /*q31*/, data_in[i][k] ) ); /*Qx*/ + move32(); + } + } + prev_gains[i][j] = gains[j]; /*q15*/ + move16(); + } + } + + return; +} +#else + static void ivas_omasa_dmx( float *data_in_f[], float data_out_f[][L_FRAME48k], @@ -1395,8 +1978,56 @@ static void ivas_omasa_dmx( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +void computeIntensityVector_enc_fx( + const Word16 *band_grouping, /* i : Band grouping for estimation */ + Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */ + Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal */ + const Word16 num_frequency_bands, /* i : Number of frequency bands */ + Word32 intensity_real[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS], /* o : Intensity vector */ + Word16 guard_bits ) +{ + /* Reminder + * X = a + ib; Y = c + id + * X*Y = ac - bd + i(ad +bc) + */ + Word16 i, j; + Word32 real, img; + Word16 brange[2]; + FOR( i = 0; i < num_frequency_bands; i++ ) + { + brange[0] = band_grouping[i]; + move16(); + brange[1] = band_grouping[i + 1]; + move16(); + + intensity_real[0][i] = 0; + move32(); + intensity_real[1][i] = 0; + move32(); + intensity_real[2][i] = 0; + move32(); + + FOR( j = brange[0]; j < brange[1]; j++ ) + { + real = Cldfb_RealBuffer[0][j]; + img = Cldfb_ImagBuffer[0][j]; + /* Intensity is XYZ order, audio is WYZX order. */ + intensity_real[0][i] = L_add( intensity_real[0][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[3][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[3][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits + move32(); + intensity_real[1][i] = L_add( intensity_real[1][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[1][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[1][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits + move32(); + intensity_real[2][i] = L_add( intensity_real[2][i], L_add( L_shr( Mpy_32_32( Cldfb_RealBuffer[2][j], real ), guard_bits ), L_shr( Mpy_32_32( Cldfb_ImagBuffer[2][j], img ), guard_bits ) ) ); // output Q= 2* input_q -31-guard_bits + move32(); + } + } + + return; +} +#else static void computeIntensityVector_enc( const int16_t *band_grouping, float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], @@ -1433,8 +2064,10 @@ static void computeIntensityVector_enc( return; } +#endif +#ifndef IVAS_FLOAT_FIXED static void computeReferencePower_omasa( const int16_t *band_grouping, /* i : Band grouping for estimation */ float Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal */ @@ -1467,3 +2100,64 @@ static void computeReferencePower_omasa( return; } +#else +static void computeReferencePower_omasa_ivas_fx( + const Word16 *band_grouping, /* i : Band grouping for estimation */ + Word32 Cldfb_RealBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Real part of input signal Q6*/ + Word32 Cldfb_ImagBuffer[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX], /* i : Imag part of input signal Q6*/ + Word32 *reference_power, /* o : Estimated power Q(31-ref_exp)*/ + const Word16 enc_param_start_band, /* i : first band to process */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + Word16 *ref_exp ) +{ + Word16 brange[2]; + Word16 ch_idx, i, j; + Word64 reference_power_tmp[CLDFB_NO_CHANNELS_MAX]; + Word16 ref_Q = 63; + move16(); + + FOR( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = band_grouping[i + enc_param_start_band]; + move16(); + brange[1] = band_grouping[i + enc_param_start_band + 1]; + move16(); + reference_power[i] = 0; + move32(); + reference_power_tmp[i] = 0; + move64(); + + FOR( ch_idx = 0; ch_idx < FOA_CHANNELS; ch_idx++ ) + { + /* abs()^2 */ + FOR( j = brange[0]; j < brange[1]; j++ ) + { + // reference_power[i] += ( Cldfb_RealBuffer[ch_idx][j] * Cldfb_RealBuffer[ch_idx][j] ) + ( Cldfb_ImagBuffer[ch_idx][j] * Cldfb_ImagBuffer[ch_idx][j] ); + // Q13 (Q6+Q6+1) + reference_power_tmp[i] = W_add( reference_power_tmp[i], W_mac_32_32( W_mult_32_32( Cldfb_RealBuffer[ch_idx][j], Cldfb_RealBuffer[ch_idx][j] ), Cldfb_ImagBuffer[ch_idx][j], Cldfb_ImagBuffer[ch_idx][j] ) ); + move64(); + } + } + } + // v_multc( reference_power, 0.5f, reference_power, num_freq_bands ); + FOR( i = 0; i < num_freq_bands; i++ ) + { + reference_power_tmp[i] = W_shr( reference_power_tmp[i], 1 ); + move64(); + ref_Q = s_min( ref_Q, W_norm( reference_power_tmp[i] ) ); + } + + FOR( i = 0; i < num_freq_bands; i++ ) + { + reference_power_tmp[i] = W_shl( reference_power_tmp[i], ref_Q ); // Q13 + ref_Q + move64(); + reference_power[i] = W_extract_h( reference_power_tmp[i] ); // Q13 + ref_Q -32 + move32(); + } + + // ref_exp = 31- ((13+ref_Q) -32) + *ref_exp = sub( 31, ( sub( add( ref_Q, 13 ), 32 ) ) ); + move16(); + return; +} +#endif diff --git a/lib_enc/ivas_osba_enc.c b/lib_enc/ivas_osba_enc.c index b170b0066565665698de119764afe6f344889653..4da8169fbc1b5e5f3a7d7281bc89397268c05cfc 100644 --- a/lib_enc/ivas_osba_enc.c +++ b/lib_enc/ivas_osba_enc.c @@ -49,15 +49,51 @@ /*------------------------------------------------------------------------- * Local function prototypes *------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void ivas_osba_render_ism_to_sba( float *data_in_f[], float data_out_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_sba, const int16_t nchan_ism, ISM_METADATA_HANDLE hIsmMeta[], float prev_gains[][MAX_INPUT_CHANNELS], const float interpolator[L_FRAME48k] ); - +#else +static void ivas_osba_render_ism_to_sba_fx( + Word32 *data_in_fx[], + Word32 data_out_fx[][L_FRAME48k], + const Word16 input_frame, + const Word16 sba_analysis_order, + const Word16 nchan_ism, + ISM_METADATA_HANDLE hIsmMeta[], + Word32 prev_gains_fx[][MAX_INPUT_CHANNELS], + const Word32 interpolator_fx[L_FRAME48k], + Word16 *Q_data ); +#endif /*-------------------------------------------------------------------* * ivas_merge_sba_transports() * * Merge SBA transport channels *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_merge_sba_transports_fx( + Word32 data_in_f1[][L_FRAME48k], + Word32 *data_in_f2[], + Word32 *data_out_f[], + const Word16 input_frame, + const Word16 sba_analysis_order, + Word16 Q_f1, + Word16 Q_f2, + Word16 *Q_out ) +{ + Word16 i, j, nchan_sba; + nchan_sba = imult1616( add( sba_analysis_order, 1 ), add( sba_analysis_order, 1 ) ); + FOR( i = 0; i < nchan_sba; i++ ) + { + FOR( j = 0; j < input_frame; j++ ) + { + data_out_f[i][j] = L_add( L_shr( data_in_f1[i][j], 1 ), L_shr( data_in_f2[i][j], sub( Q_f2, sub( Q_f1, 1 ) ) ) ); + move32(); + } + } + *Q_out = sub( Q_f1, 1 ); + return; +} +#else static void ivas_merge_sba_transports( float data_in_f1[][L_FRAME48k], float *data_in_f2[], @@ -79,13 +115,62 @@ static void ivas_merge_sba_transports( return; } - +#endif /*--------------------------------------------------------------------------* * ivas_osba_enc_open() * * Allocate and initialize OMASA handle *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_osba_enc_open_fx( + Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ +) +{ + Word16 i; + OSBA_ENC_HANDLE hOSba; + Word16 input_frame; + ivas_error error; + Word16 len; + error = IVAS_ERR_OK; + + IF( ( hOSba = (OSBA_ENC_HANDLE) malloc( sizeof( OSBA_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OMASA encoder\n" ) ); + } + FOR( i = 0; i < MAX_NUM_OBJECTS; i++ ) + { + set_val_Word32( hOSba->prev_object_dm_gains_fx[i], INV_SQRT_2_Q30, MAX_INPUT_CHANNELS ); + } + len = NS2SA( st_ivas->hEncoderConfig->input_Fs, IVAS_FB_ENC_DELAY_NS ); + move16(); + FOR( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + IF( ( hOSba->input_data_mem_fx[i] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for OSBA input buffers" ); + } + set_val_Word32( hOSba->input_data_mem_fx[i], 0, len ); + } + FOR( ; i < MAX_NUM_OBJECTS; i++ ) + { + hOSba->input_data_mem_fx[i] = NULL; + } + Word16 tmp_e; + Word32 tmp32 = L_deposit_h( BASOP_Util_Divide3216_Scale( st_ivas->hEncoderConfig->input_Fs, FRAMES_PER_SEC, &tmp_e ) ); + tmp32 = L_shr( tmp32, sub( 15, tmp_e ) ); + input_frame = extract_l( tmp32 ); + + for ( i = 0; i < input_frame; i++ ) + { + tmp32 = L_deposit_h( BASOP_Util_Divide1616_Scale( i, input_frame, &tmp_e ) ); + hOSba->interpolator_fx[i] = L_shl( tmp32, tmp_e ); + move32(); + } + st_ivas->hOSba = hOSba; + return error; +} +#else ivas_error ivas_osba_enc_open( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ) @@ -133,14 +218,38 @@ ivas_error ivas_osba_enc_open( return error; } - +#endif /*--------------------------------------------------------------------------* * ivas_omasa_enc_close() * * Close OMASA handle *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_osba_enc_close_fx( + OSBA_ENC_HANDLE *hOSba /* i/o: encoder OSBA handle */ +) +{ + Word16 n; + test(); + IF( hOSba == NULL || *hOSba == NULL ) + { + return; + } + FOR( n = 0; n < MAX_NUM_OBJECTS; n++ ) + { + IF( ( *hOSba )->input_data_mem_fx[n] != NULL ) + { + free( ( *hOSba )->input_data_mem_fx[n] ); + ( *hOSba )->input_data_mem_fx[n] = NULL; + } + } + free( *hOSba ); + ( *hOSba ) = NULL; + return; +} +#else void ivas_osba_enc_close( OSBA_ENC_HANDLE *hOSba /* i/o: encoder OSBA handle */ ) @@ -164,7 +273,7 @@ void ivas_osba_enc_close( return; } - +#endif /*--------------------------------------------------------------------------* * ivas_osba_enc_reconfig() @@ -193,10 +302,10 @@ ivas_error ivas_osba_enc_reconfig( { DIRAC_ENC_HANDLE hDirAC = st_ivas->hDirAC; SPAR_ENC_HANDLE hSpar; - int16_t analysis_order_old; - int16_t spar_reconfig_flag; - int16_t nbands_old; - int16_t ndir_old; + Word16 analysis_order_old; + Word16 spar_reconfig_flag; + Word16 nbands_old; + Word16 ndir_old; spar_reconfig_flag = 0; move16(); @@ -354,52 +463,57 @@ ivas_error ivas_osba_enc_reconfig( } } -#ifdef IVAS_FLOAT_FIXED ivas_spar_config_fx( ivas_total_brate, min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ), &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->hSpar->core_nominal_brate, -1 ); -#else - ivas_spar_config( ivas_total_brate, min( st_ivas->sba_analysis_order, IVAS_MAX_SBA_ORDER ), &st_ivas->nchan_transport, &st_ivas->nSCE, &st_ivas->nCPE, &st_ivas->hSpar->core_nominal_brate, -1 ); -#endif hSpar = st_ivas->hSpar; - if ( st_ivas->nchan_transport == 1 ) + IF( EQ_16( st_ivas->nchan_transport, 1 ) ) { hEncoderConfig->element_mode_init = IVAS_SCE; + move16(); } - else + ELSE { hEncoderConfig->element_mode_init = IVAS_CPE_MDCT; + move16(); } - if ( nchan_transport_old != st_ivas->nchan_transport || ( ivas_total_brate < IVAS_512k && hEncoderConfig->last_ivas_total_brate >= IVAS_512k ) || ( ivas_total_brate >= IVAS_512k && hEncoderConfig->last_ivas_total_brate < IVAS_512k ) ) + test(); + test(); + test(); + test(); + IF( NE_16( nchan_transport_old, st_ivas->nchan_transport ) || ( LT_32( ivas_total_brate, IVAS_512k ) && GE_32( hEncoderConfig->last_ivas_total_brate, IVAS_512k ) ) || ( GE_32( ivas_total_brate, IVAS_512k ) && LT_32( hEncoderConfig->last_ivas_total_brate, IVAS_512k ) ) ) { /* FB mixer handle */ - if ( hDirAC->hFbMixer != NULL ) + IF( hDirAC->hFbMixer != NULL ) { ivas_FB_mixer_close( &( hDirAC->hFbMixer ), hEncoderConfig->input_Fs, 0 ); hDirAC->hFbMixer = NULL; } spar_reconfig_flag = 1; + move16(); ivas_spar_enc_close( &( st_ivas->hSpar ), hEncoderConfig->input_Fs, hEncoderConfig->nchan_inp, spar_reconfig_flag ); - if ( ( error = ivas_spar_enc_open( st_ivas, spar_reconfig_flag ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_spar_enc_open( st_ivas, spar_reconfig_flag ) ) != IVAS_ERR_OK ) { return error; } } st_ivas->hSpar->spar_reconfig_flag = spar_reconfig_flag; - if ( ( error = ivas_dirac_enc_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) + move16(); + IF( ( error = ivas_dirac_enc_reconfigure( st_ivas ) ) != IVAS_ERR_OK ) { return error; } - if ( st_ivas->hQMetaData->q_direction->cfg.nbands != nbands_old || st_ivas->hQMetaData->no_directions != ndir_old ) + test(); + IF( NE_16( st_ivas->hQMetaData->q_direction->cfg.nbands, nbands_old ) || NE_16( st_ivas->hQMetaData->no_directions, ndir_old ) ) { - int16_t dir, j, i; + Word16 dir, j, i; IVAS_QDIRECTION *q_direction = st_ivas->hQMetaData->q_direction; - for ( dir = 0; dir < st_ivas->hQMetaData->no_directions; dir++ ) + FOR( dir = 0; dir < st_ivas->hQMetaData->no_directions; dir++ ) { - for ( j = 0; j < q_direction[dir].cfg.nbands; j++ ) + FOR( j = 0; j < q_direction[dir].cfg.nbands; j++ ) { - for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) { q_direction[dir].band_data[j].energy_ratio_index[i] = 0; q_direction[dir].band_data[j].energy_ratio_index_mod[i] = 0; @@ -412,24 +526,29 @@ ivas_error ivas_osba_enc_reconfig( /*-----------------------------------------------------------------* * Allocate, initialize, and configure SCE/CPE/MCT handles *-----------------------------------------------------------------*/ - - if ( old_ism_mode == ISM_MODE_NONE && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + test(); + test(); + IF( old_ism_mode == ISM_MODE_NONE && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) { - st_ivas->nCPE += ( st_ivas->hEncoderConfig->nchan_ism + 1 ) >> 1; + st_ivas->nCPE = add( st_ivas->nCPE, shr( add( st_ivas->hEncoderConfig->nchan_ism, 1 ), 1 ) ); } - else if ( old_ism_mode == ISM_SBA_MODE_DISC && st_ivas->ism_mode == ISM_MODE_NONE ) + ELSE IF( EQ_32( old_ism_mode, ISM_SBA_MODE_DISC ) && st_ivas->ism_mode == ISM_MODE_NONE ) { - nchan_transport_old += st_ivas->hEncoderConfig->nchan_ism; + nchan_transport_old = add( nchan_transport_old, st_ivas->hEncoderConfig->nchan_ism ); } - else if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) { - st_ivas->nCPE += ( st_ivas->hEncoderConfig->nchan_ism + 1 ) >> 1; + st_ivas->nCPE = add( st_ivas->nCPE, shr( add( st_ivas->hEncoderConfig->nchan_ism, 1 ), 1 ) ); nCPE_old = st_ivas->nCPE; + move16(); nchan_transport_old = st_ivas->nchan_transport; - nchan_transport_old += st_ivas->hEncoderConfig->nchan_ism; + move16(); + nchan_transport_old = add( nchan_transport_old, st_ivas->hEncoderConfig->nchan_ism ); } - - if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, ivas_total_brate / st_ivas->nchan_transport, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + Word16 tmp_e; + Word32 bitrate_per_chan = L_deposit_h( BASOP_Util_Divide3216_Scale( ivas_total_brate, st_ivas->nchan_transport, &tmp_e ) ); + bitrate_per_chan = L_shr( bitrate_per_chan, sub( 15, tmp_e ) ); + IF( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, bitrate_per_chan, imult3216( bitrate_per_chan, CPE_CHANNELS ), MC_MODE_NONE ) ) != IVAS_ERR_OK ) { return error; } @@ -628,13 +747,70 @@ ivas_error ivas_osba_enc_reconfig( return error; } #endif - +#ifdef IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* * ivas_osba_enc() * * Main OSBA encoding function *--------------------------------------------------------------------------*/ +void ivas_osba_enc_fx( + OSBA_ENC_HANDLE hOSba, /* i/o: OSBA encoder handle */ + ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ + Word32 *data_in_fx[], /* i/o: Input / transport audio signals */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_ism, /* i : Number of objects for parameter analysis */ + const ISM_MODE ism_mode, /* i : ISM mode */ + const Word16 sba_analysis_order, /* i : SBA order evaluated in DirAC/SPAR encoder */ + const Word32 input_Fs, /* i : input sampling rate */ + const Word16 sba_planar, /* i : planar SBA flag */ + Word16 *q_data ) +{ + Word32 data_out_fx[MAX_INPUT_CHANNELS][L_FRAME48k]; + Word16 Q_out = *q_data; + move16(); + Word16 n, delay_s; + delay_s = NS2SA( input_Fs, IVAS_FB_ENC_DELAY_NS ); + IF( ism_mode == ISM_MODE_NONE ) + { + /*keep the delay buffer up to date*/ + FOR( n = 0; n < nchan_ism; n++ ) + { + MVR2R_WORD32( &data_in_fx[n][input_frame - delay_s], hOSba->input_data_mem_fx[n], delay_s ); + } + /* Convert ISM to SBA */ + + ivas_osba_render_ism_to_sba_fx( data_in_fx, data_out_fx, input_frame, sba_analysis_order, nchan_ism, hIsmMeta, hOSba->prev_object_dm_gains_fx, hOSba->interpolator_fx, &Q_out ); + + IF( sba_planar ) + { + ivas_sba_zero_vert_comp_fx( &( data_in_fx[nchan_ism] ), sba_analysis_order, sba_planar, input_frame ); + } + + + /* Merge SBA signals */ + ivas_merge_sba_transports_fx( data_out_fx, &( data_in_fx[nchan_ism] ), data_in_fx, input_frame, sba_analysis_order, Q_out, *q_data, q_data ); + } + ELSE + { + Word16 azimuth_fx, elevation_fx; + /* delay ISM input channels to match the SBA encoder delay */ + FOR( n = 0; n < nchan_ism; n++ ) + { + delay_signal_fx( data_in_fx[n], input_frame, hOSba->input_data_mem_fx[n], delay_s ); + + azimuth_fx = extract_l( L_shr( L_add( hIsmMeta[n]->azimuth_fx, 2097152 ), Q22 ) ); + elevation_fx = extract_l( L_shr( L_add( hIsmMeta[n]->elevation_fx, 2097152 ), Q22 ) ); + ivas_dirac_dec_get_response_fx( azimuth_fx, elevation_fx, hOSba->prev_object_dm_gains_fx[n], sba_analysis_order, Q30 ); + } + } + + /* Set the number of objects */ + hOSba->nchan_ism = nchan_ism; + move16(); + return; +} +#else void ivas_osba_enc( OSBA_ENC_HANDLE hOSba, /* i/o: OSBA encoder handle */ ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handle */ @@ -691,12 +867,86 @@ void ivas_osba_enc( return; } - +#endif /*--------------------------------------------------------------------------* * Local functions *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/* Render ISMs to SBA */ +static void ivas_osba_render_ism_to_sba_fx( + Word32 *data_in_fx[], + Word32 data_out_fx[][L_FRAME48k], + const Word16 input_frame, + const Word16 sba_analysis_order, + const Word16 nchan_ism, + ISM_METADATA_HANDLE hIsmMeta[], + Word32 prev_gains_fx[][MAX_INPUT_CHANNELS], + const Word32 interpolator_fx[L_FRAME48k], + Word16 *Q_data ) +{ + Word16 i, j, k; + Word16 azimuth_fx, elevation_fx; + Word32 gains_fx[MAX_INPUT_CHANNELS]; + Word32 g1_fx, g2_fx; + Word32 output_gain_fx; + Word16 nchan_sba; + nchan_sba = imult1616( add( sba_analysis_order, 1 ), add( sba_analysis_order, 1 ) ); + + FOR( i = 0; i < nchan_sba; i++ ) + { + set_val_Word32( data_out_fx[i], 0, input_frame ); + } + FOR( i = 0; i < nchan_ism; i++ ) + { + // azimuth = (int16_t) floorf( hIsmMeta[i]->azimuth + 0.5f ); + azimuth_fx = extract_l( L_shr( L_add( hIsmMeta[i]->azimuth_fx, 2097152 ), Q22 ) ); + // elevation = (int16_t) floorf( hIsmMeta[i]->elevation + 0.5f ); + elevation_fx = extract_l( L_shr( L_add( hIsmMeta[i]->elevation_fx, 2097152 ), Q22 ) ); + + ivas_dirac_dec_get_response_fx( azimuth_fx, elevation_fx, gains_fx, sba_analysis_order, Q30 ); + + /* Render using the sh gains */ + FOR( j = 0; j < nchan_sba; j++ ) + { + IF( L_abs( gains_fx[j] ) > 0 || L_abs( prev_gains_fx[i][j] ) > 0 ) + { + FOR( k = 0; k < input_frame; k++ ) + { + // g1 = interpolator[k]; + g1_fx = interpolator_fx[k]; + move32(); + // g2 = 1.0f - g1; + g2_fx = L_sub( ONE_IN_Q31, g1_fx ); + move32(); + // data_out_f[j][k] += ( g1 * gains[j] + g2 * prev_gains[i][j] ) * data_in_f[i][k]; + data_out_fx[j][k] = L_add( data_out_fx[j][k], L_shr( Mpy_32_32( L_add( Mpy_32_32( g1_fx, gains_fx[j] ), Mpy_32_32( g2_fx, prev_gains_fx[i][j] ) ), data_in_fx[i][k] ), 1 ) ); // Q_data-2 + move32(); + } + } + prev_gains_fx[i][j] = gains_fx[j]; + move32(); + } + } + *Q_data = sub( *Q_data, 2 ); + /* Gain with loudness-matching gains */ + // output_gain = 0.7499f; + output_gain_fx = 1610397988; // 0.7499f in Q31 + move32(); + FOR( j = 0; j < nchan_sba; j++ ) + { + FOR( k = 0; k < input_frame; k++ ) + { + // data_out_f[j][k] *= output_gain; + data_out_fx[j][k] = Mpy_32_32( data_out_fx[j][k], output_gain_fx ); + move32(); + } + } + + return; +} +#else /* Render ISMs to SBA */ static void ivas_osba_render_ism_to_sba( float *data_in_f[], @@ -758,3 +1008,5 @@ static void ivas_osba_render_ism_to_sba( return; } + +#endif diff --git a/lib_enc/ivas_qmetadata_enc.c b/lib_enc/ivas_qmetadata_enc.c index e0a8fdeb14d48430f55b74c8bd6619beb2ad4aab..4d246daa0f7f682d29e77941604fdf971091770d 100644 --- a/lib_enc/ivas_qmetadata_enc.c +++ b/lib_enc/ivas_qmetadata_enc.c @@ -37,13 +37,13 @@ #include "ivas_cnst.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_rom_com.h" #include "ivas_stat_enc.h" #include "wmc_auto.h" #include "prot.h" #include "prot_fx.h" -#include "ivas_prot_fx.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_rom_com_fx.h" #endif @@ -52,25 +52,55 @@ * Local function prototypes *-----------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *needed_bits, int16_t *nbits_diff, int16_t *dfRatioBits, const int16_t hodirac_flag ); +#else +static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *needed_bits, int16_t *nbits_diff, int16_t *dfRatioBits, const int16_t hodirac_flag ); +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_encode_diffuseness_fx( + BSTR_ENC_HANDLE hMetaData, + IVAS_QDIRECTION *q_direction, + UWord16 *diffuseness_index_max_ec_frame ); +#else static int16_t ivas_qmetadata_entropy_encode_diffuseness( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, uint16_t *diffuseness_index_max_ec_frame ); +#endif +#ifdef IVAS_FLOAT_FIXED +static void ivas_qmetadata_reorder_2dir_bands_fx( IVAS_QMETADATA_HANDLE hQMetaData ); +#else static void ivas_qmetadata_reorder_2dir_bands( IVAS_QMETADATA_HANDLE hQMetaData ); +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_encode_df_ratio_fx( + BSTR_ENC_HANDLE hMetaData, + IVAS_QDIRECTION *q_direction, + Word16 *df_ratio_bits ); +#else static int16_t ivas_qmetadata_entropy_encode_df_ratio( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, int16_t *df_ratio_bits ); +#endif static int16_t ivas_qmetadata_entropy_encode_dir( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const uint16_t diffuseness_index_max_ec_frame, const int16_t nbands, const int16_t start_band, const int16_t direction_bits_raw, int16_t max_bits, const int16_t hrmasa_flag ); static int16_t ivas_qmetadata_raw_encode_dir( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const int16_t nbands, const int16_t start_band ); -int16_t ivas_qmetadata_encode_extended_gr_length( const uint16_t value, const uint16_t alphabet_size, const int16_t gr_param ); - static int16_t ivas_qmetadata_get_optimal_gr_param( uint16_t *unsigned_data, const int16_t count, const int16_t gr_param_count, int16_t *opt_gr_size ); +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_qmetadata_encode_extended_gr_length( const UWord16 value, const UWord16 alphabet_size, const Word16 gr_param ); + +static Word16 ivas_qmetadata_encode_quasi_uniform_length( const UWord16 value, const UWord16 alphabet_size ); + +static void ivas_qmetadata_encode_quasi_uniform( BSTR_ENC_HANDLE hMetaData, const UWord16 value, const UWord16 alphabet_size ); +#else +int16_t ivas_qmetadata_encode_extended_gr_length( const uint16_t value, const uint16_t alphabet_size, const int16_t gr_param ); + static int16_t ivas_qmetadata_encode_quasi_uniform_length( const uint16_t value, const uint16_t alphabet_size ); static void ivas_qmetadata_encode_quasi_uniform( BSTR_ENC_HANDLE hMetaData, const uint16_t value, const uint16_t alphabet_size ); +#endif static int16_t ivas_qmetadata_reorder_elevation_index( const int16_t elevation_index, const int16_t avg_elevation_index, const int16_t elevation_alphabet ); @@ -96,31 +126,67 @@ static int16_t encode_coherence_indexesDCT0( uint16_t *idx_dct, const int16_t le static int16_t encode_coherence_indexesDCT1( uint16_t *idx_dct, const int16_t len, BSTR_ENC_HANDLE hMetaData ); +#ifdef IVAS_FLOAT_FIXED +static UWord64 create_combined_index( uint16_t *idx_dct, const int16_t len, const int16_t *no_cb_vec ); +#else static uint64_t create_combined_index( uint16_t *idx_dct, const int16_t len, const int16_t *no_cb_vec ); +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 encode_surround_coherence_fx( + IVAS_QMETADATA *hQMetaData, /* i : quantized metadata */ + BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ +); +#else static int16_t encode_surround_coherence( IVAS_QMETADATA *hQMetaData, BSTR_ENC_HANDLE hMetaData ); +#endif static int16_t write_fixed_rate_direction( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const int16_t j_idx, const int16_t len ); static int16_t common_direction( IVAS_QDIRECTION *q_direction, const int16_t band_idx, const int16_t len, const int16_t bits_allowed, BSTR_ENC_HANDLE hMetaData, float *elevation_orig, float *azimuth_orig ); +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_diffuseness_huff_ec_encode_fx( + BSTR_ENC_HANDLE hMetaData, + const UWord16 idx ); +#else static int16_t ivas_diffuseness_huff_ec_encode( BSTR_ENC_HANDLE hMetaData, const uint16_t idx ); +#endif +#ifdef IVAS_FLOAT_FIXED +static void ivas_diffuseness_huff_ec_prepare_fx( + IVAS_QDIRECTION *q_direction, + Word16 *best_av, + UWord16 *avr_idx, + Word16 *diffuseness_bits_huff ); +#else static void ivas_diffuseness_huff_ec_prepare( IVAS_QDIRECTION *q_direction, int16_t *best_av, uint16_t *avr_idx, int16_t *diffuseness_bits_huff ); +#endif static int16_t coherence_coding_length( const uint16_t *idx_sur_coh_shift, const uint8_t idx_shift_len, const int16_t coding_subbands, const int16_t *no_cv, uint16_t *mr_idx, int16_t *no_cv_shift, int16_t *p_min_idx, int16_t *GR_ord, int16_t *nbits_fr, int16_t *nbits_fr1 ); static int16_t write_2dir_info( BSTR_ENC_HANDLE hMetaData, uint8_t *twoDirBands, const int16_t n, const int16_t k ); +#ifdef IVAS_FLOAT_FIXED +static void transform_azimuth_dir2_fx( + IVAS_QMETADATA_HANDLE hQMetaData, + Word16 *dir2_bands ); +#else static void transform_azimuth_dir2( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *dir2_bands ); +#endif static int16_t calc_var_azi( const IVAS_QDIRECTION *q_direction, const int16_t diffuseness_index_max_ec_frame, const float avg_azimuth, float *avg_azimuth_out ); - +#ifndef IVAS_FLOAT_FIXED static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *needed_bits, const int16_t bits_dir_hr, BSTR_ENC_HANDLE hMetaData ); -static int16_t encode_surround_coherence_hr( IVAS_QMETADATA *hQMetaData, BSTR_ENC_HANDLE hMetaData ); - static int16_t ivas_qmetadata_quantize_coherence_hr_512( IVAS_QMETADATA *hQMetaData, const int16_t idx_d, const int16_t all_coherence_zero, BSTR_ENC_HANDLE hMetaData, const int16_t bits_coh ); +#else +static Word16 ivas_qmetadata_quantize_coherence_hr_512_fx( IVAS_QMETADATA *hQMetaData, const Word16 idx_d, const Word16 all_coherence_zero, BSTR_ENC_HANDLE hMetaData, const Word16 bits_coh ); + +static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx( IVAS_QMETADATA_HANDLE hQMetaData, Word16 *needed_bits, const Word16 bits_dir_hr, BSTR_ENC_HANDLE hMetaData ); +#endif + +static int16_t encode_surround_coherence_hr( IVAS_QMETADATA *hQMetaData, BSTR_ENC_HANDLE hMetaData ); static int16_t write_stream_dct_coeffs_omasa( int16_t *q_idx, const int16_t len_stream, BSTR_ENC_HANDLE hMetaData, const int16_t first_line, const int16_t low_bitrate_mode ); @@ -142,30 +208,31 @@ ivas_error ivas_qmetadata_enc_encode( const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ ) { - int16_t i, bit_pos_start, bit_pos_start_coh; - int16_t next_ind_start; - uint16_t diffuseness_index_max_ec_frame; - uint16_t diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t bits_diff_sum; - int16_t bits_diff[QMETADATA_MAX_NO_DIRECTIONS], bits_coherence[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t bits_dir[QMETADATA_MAX_NO_DIRECTIONS], bits_dir_raw; - int16_t extra_bits; + Word16 i, bit_pos_start, bit_pos_start_coh; + Word16 next_ind_start; + UWord16 diffuseness_index_max_ec_frame; + UWord16 diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 bits_diff_sum; + Word16 bits_diff[QMETADATA_MAX_NO_DIRECTIONS], bits_coherence[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 bits_dir[QMETADATA_MAX_NO_DIRECTIONS], bits_dir_raw; + Word16 extra_bits; IVAS_QDIRECTION *q_direction; - int16_t nbands, nblocks, start_band; - int16_t ndirections, d; - float azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t all_coherence_zero; - int16_t bit_pos_0, total_bits_1dir, bits_no_dirs_coh; - int16_t bits_signaling[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t indice_coherence; - int16_t bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS], raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t diff_bits, bits_ec, next_ind_raw_flag; - int16_t dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t bits_surround_coh, no_TF; - int16_t dir2_bands[MASA_MAXIMUM_TWO_DIR_BANDS]; - int16_t ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t reduce_bits; + Word16 nbands, nblocks, start_band; + Word16 ndirections, d; + Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + float azimuth_orig_flt[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig_flt[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 all_coherence_zero; + Word16 bit_pos_0, total_bits_1dir, bits_no_dirs_coh; + Word16 bits_signaling[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 indice_coherence; + Word16 bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS], raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 diff_bits, bits_ec, next_ind_raw_flag; + Word16 dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bits_surround_coh, no_TF; + Word16 dir2_bands[MASA_MAXIMUM_TWO_DIR_BANDS]; + Word16 ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 reduce_bits; ivas_error error; error = IVAS_ERR_OK; @@ -182,7 +249,7 @@ ivas_error ivas_qmetadata_enc_encode( all_coherence_zero = 1; bits_no_dirs_coh = 0; - if ( hQMetaData->coherence_flag ) + IF( hQMetaData->coherence_flag ) { all_coherence_zero = hQMetaData->all_coherence_zero; @@ -190,25 +257,33 @@ ivas_error ivas_qmetadata_enc_encode( bits_no_dirs_coh += 1; } - if ( ndirections > 1 ) + IF( GT_16( ndirections, 1 ) ) { /* Reorder 2dir bands for more efficient encoding. */ - if ( !hodirac_flag ) + IF( !hodirac_flag ) { - ivas_qmetadata_reorder_2dir_bands( hQMetaData ); + ivas_qmetadata_reorder_2dir_bands_fx( hQMetaData ); +#if 0 // def IVAS_FLOAT_FIXED_CONVERSIONS + for (i = 0; i < ndirections; i++) { + for (int j = hQMetaData->q_direction[i].cfg.start_band; j < hQMetaData->q_direction[i].cfg.nbands; ++j) + { + floatToFixed_arrL(hQMetaData->q_direction[i].band_data[j].energy_ratio, hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, Q30, MAX_PARAM_SPATIAL_SUBFRAMES); + } + } +#endif } d = 0; - for ( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ ) + FOR( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ ) { - if ( hQMetaData->twoDirBands[i] == 1 ) + IF( hQMetaData->twoDirBands[i] == 1 ) { - mvr2r( hQMetaData->q_direction[1].band_data[i].azimuth, hQMetaData->q_direction[1].band_data[d].azimuth, hQMetaData->q_direction[1].cfg.nblocks ); - mvr2r( hQMetaData->q_direction[1].band_data[i].elevation, hQMetaData->q_direction[1].band_data[d].elevation, hQMetaData->q_direction[1].cfg.nblocks ); - mvr2r( hQMetaData->q_direction[1].band_data[i].energy_ratio, hQMetaData->q_direction[1].band_data[d].energy_ratio, hQMetaData->q_direction[1].cfg.nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[i].azimuth_fx, hQMetaData->q_direction[1].band_data[d].azimuth_fx, hQMetaData->q_direction[1].cfg.nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[i].elevation_fx, hQMetaData->q_direction[1].band_data[d].elevation_fx, hQMetaData->q_direction[1].cfg.nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, hQMetaData->q_direction[1].band_data[d].energy_ratio_fx, hQMetaData->q_direction[1].cfg.nblocks ); dir2_bands[d] = i; - if ( hQMetaData->coherence_flag ) + IF( hQMetaData->coherence_flag ) { mvc2c( hQMetaData->q_direction[1].coherence_band_data[i].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].cfg.nblocks ); } @@ -218,57 +293,49 @@ ivas_error ivas_qmetadata_enc_encode( bits_no_dirs_coh += write_2dir_info( hMetaData, hQMetaData->twoDirBands, hQMetaData->q_direction[0].cfg.nbands, hQMetaData->numTwoDirBands ); - for ( i = d; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) + FOR( i = d; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) { - set_f( hQMetaData->q_direction[1].band_data[i].energy_ratio, 0.0f, hQMetaData->q_direction[1].cfg.nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, 0, hQMetaData->q_direction[1].cfg.nblocks ); } hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands; } /*Quantization of the Diffuseness */ - ivas_qmetadata_quantize_diffuseness_nrg_ratios( hQMetaData, bits_dir_raw_pre, bits_diff, dfRatio_bits, hodirac_flag ); + ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx( hQMetaData, bits_dir_raw_pre, bits_diff, dfRatio_bits, hodirac_flag ); bits_diff_sum = 0; - bits_diff[0] = ivas_qmetadata_entropy_encode_diffuseness( hMetaData, &( hQMetaData->q_direction[0] ), &diffuseness_index_max_ec_frame_pre[0] ); + // TODO + bits_diff[0] = ivas_qmetadata_entropy_encode_diffuseness_fx( hMetaData, &( hQMetaData->q_direction[0] ), &diffuseness_index_max_ec_frame_pre[0] ); bits_diff_sum += bits_diff[0]; - if ( ndirections == 2 ) + IF( EQ_16( ndirections, 2 ) ) { - bits_diff[1] = ivas_qmetadata_entropy_encode_df_ratio( hMetaData, &( hQMetaData->q_direction[1] ), dfRatio_bits ); + bits_diff[1] = ivas_qmetadata_entropy_encode_df_ratio_fx( hMetaData, &( hQMetaData->q_direction[1] ), dfRatio_bits ); bits_diff_sum += bits_diff[1]; } /* 2dir energy ratio encoding reuses index memory. Now that diffRatio and dFRatio have been encoded, * we retrieve index_dirRatio1Inv and index_dirRatio1Inv for further parameter encoding. This is * necessary only for bands that have two concurrent directions. */ - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { - int16_t j, k, dir2band, index_dirRatio1Inv, index_dirRatio2Inv; + Word16 j, k, dir2band, index_dirRatio1Inv, index_dirRatio2Inv; dir2band = 0; - for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) { - if ( hQMetaData->twoDirBands[j] == 1 ) + IF( hQMetaData->twoDirBands[j] == 1 ) { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] = floatToFixed( hQMetaData->q_direction[0].band_data[j].energy_ratio[0], Q30 ); - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0] = floatToFixed( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[0], Q30 ); - /*=====================================flt-2-fix============================================*/ - index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); index_dirRatio2Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - index_dirRatio1Inv = masa_sq( 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[0], diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); - index_dirRatio2Inv = masa_sq( 1.0f - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[0], diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif - for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + + FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_dirRatio1Inv; } - for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) { hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[k] = index_dirRatio2Inv; } @@ -278,20 +345,28 @@ ivas_error ivas_qmetadata_enc_encode( } } +#if 0 // def IVAS_FLOAT_FIXED_CONVERSIONS + for (i = 0; i < ndirections; i++) { + for (int j = hQMetaData->q_direction[i].cfg.start_band; j < hQMetaData->q_direction[i].cfg.nbands; ++j) + { + fixedToFloat_arrL(hQMetaData->q_direction[i].band_data[j].energy_ratio_fx, hQMetaData->q_direction[i].band_data[j].energy_ratio, Q30, MAX_PARAM_SPATIAL_SUBFRAMES); + } + } +#endif /* Encode surround coherence */ - if ( ndirections == 2 ) + IF( EQ_16( ndirections, 2 ) ) { - no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks + hQMetaData->q_direction[1].cfg.nbands * hQMetaData->q_direction[1].cfg.nblocks; - if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - sum_s( bits_diff, ndirections ) >= MASA_MIN_BITS_SURR_COH ) ) + no_TF = add( imult1616( hQMetaData->q_direction[0].cfg.nbands, hQMetaData->q_direction[0].cfg.nblocks ), imult1616( hQMetaData->q_direction[1].cfg.nbands, hQMetaData->q_direction[1].cfg.nblocks ) ); + IF( EQ_16( all_coherence_zero, 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - ( ( 43 * no_TF ) / 10 ) - sum_s( bits_diff, ndirections ) >= MASA_MIN_BITS_SURR_COH ) ) { - bits_surround_coh = encode_surround_coherence( hQMetaData, hMetaData ); + bits_surround_coh = encode_surround_coherence_fx( hQMetaData, hMetaData ); } - else + ELSE { bits_surround_coh = 0; - for ( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) + FOR( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { set_c( (int8_t *) hQMetaData->surcoh_band_data[i].surround_coherence, 0, hQMetaData->q_direction[0].cfg.nblocks ); } @@ -300,19 +375,19 @@ ivas_error ivas_qmetadata_enc_encode( bits_no_dirs_coh += bits_surround_coh; total_bits_1dir = ( ( hQMetaData->metadata_max_bits - bits_no_dirs_coh ) * hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks ) / no_TF; } - else + ELSE { no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks; - if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff[0] >= MASA_MIN_BITS_SURR_COH ) ) + IF( EQ_16( all_coherence_zero, 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - ( ( 43 * no_TF ) / 10 ) - bits_diff[0] >= MASA_MIN_BITS_SURR_COH ) ) { - bits_surround_coh = encode_surround_coherence( hQMetaData, hMetaData ); + bits_surround_coh = encode_surround_coherence_fx( hQMetaData, hMetaData ); } - else + ELSE { bits_surround_coh = 0; - for ( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) + FOR( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { set_c( (int8_t *) hQMetaData->surcoh_band_data[i].surround_coherence, 0, hQMetaData->q_direction[0].cfg.nblocks ); } @@ -322,13 +397,13 @@ ivas_error ivas_qmetadata_enc_encode( } /* Loop over number of directions*/ - for ( d = 0; d < ndirections; d++ ) + FOR( d = 0; d < ndirections; d++ ) { q_direction = &( hQMetaData->q_direction[d] ); - if ( d == 1 ) + IF( EQ_16( d, 1 ) ) { - transform_azimuth_dir2( hQMetaData, dir2_bands ); + transform_azimuth_dir2_fx( hQMetaData, dir2_bands ); } nbands = q_direction->cfg.nbands; @@ -338,11 +413,11 @@ ivas_error ivas_qmetadata_enc_encode( bits_dir_raw = bits_dir_raw_pre[d]; /* This sets bit budget correctly for the second direction */ - if ( d == 0 ) + IF( EQ_16( d, 0 ) ) { bits_diff[d] = bits_diff_sum; } - else + ELSE { bits_diff[d] = 0; } @@ -354,21 +429,22 @@ ivas_error ivas_qmetadata_enc_encode( bits_coherence[d] = 0; bit_pos_start_coh = hMetaData->nb_bits_tot; - if ( all_coherence_zero == 0 ) + IF( EQ_16( all_coherence_zero, 0 ) ) { bits_coherence[d] = ivas_qmetadata_quantize_coherence( hQMetaData, d, all_coherence_zero, hMetaData, 0, &indice_coherence, 0 ); } - if ( q_direction->cfg.mc_ls_setup == MC_LS_SETUP_5_1 || q_direction->cfg.mc_ls_setup == MC_LS_SETUP_7_1 ) + IF( q_direction->cfg.mc_ls_setup == MC_LS_SETUP_5_1 || q_direction->cfg.mc_ls_setup == MC_LS_SETUP_7_1 ) { q_direction->not_in_2D = 0; /* Quantize directions*/ - quantize_direction_frame2D( q_direction, azimuth_orig, elevation_orig ); + // TODO : Remove azimuth_orig_flt and elevation_orig_flt once full fixed point + quantize_direction_frame2D( q_direction, azimuth_orig_flt, elevation_orig_flt ); } - else + ELSE { /* Quantize directions*/ - quantize_direction_frame( q_direction, azimuth_orig, elevation_orig, 0 ); + quantize_direction_frame( q_direction, azimuth_orig_flt, elevation_orig_flt, 0 ); } /* Signalling 2D*/ @@ -380,7 +456,7 @@ ivas_error ivas_qmetadata_enc_encode( next_ind_start = hMetaData->nb_ind_tot; /* Encode quantized directions with EC frame-wise*/ - if ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) + IF( LE_16( ( total_bits_1dir + bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) ) { push_next_indice( hMetaData, 0, 1 ); /*Write 1 bit to signal EC frame-wise (EC1)*/ bits_signaling[d]++; @@ -394,7 +470,7 @@ ivas_error ivas_qmetadata_enc_encode( reduce_bits = hQMetaData->is_masa_ivas_format ? ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signaling[d] ) - 1 ) : MASA_MAX_BITS; bits_ec = ivas_qmetadata_entropy_encode_dir( hMetaData, q_direction, diffuseness_index_max_ec_frame, q_direction->cfg.nbands, q_direction->cfg.start_band, bits_dir_bands[0], reduce_bits, 0 ); - if ( bits_ec < 0 ) + IF( LT_16( bits_ec, 0 ) ) { hMetaData->ind_list[next_ind_raw_flag].value = 1; /*rewrite flag*/ bits_ec = ivas_qmetadata_raw_encode_dir( hMetaData, q_direction, q_direction->cfg.nbands, q_direction->cfg.start_band ); @@ -403,7 +479,7 @@ ivas_error ivas_qmetadata_enc_encode( extra_bits = hQMetaData->metadata_max_bits - ( hMetaData->nb_bits_tot - bit_pos_0 ); /* Encode quantized directions with EC band-wise */ - if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] > total_bits_1dir ) && q_direction->cfg.nblocks > 1 ) + IF( LE_16( ( total_bits_1dir + bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) && GT_16( ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] ), total_bits_1dir ) && GT_16( q_direction->cfg.nblocks, 1 ) ) { restore_metadata_buffer( hMetaData, next_ind_start, bit_pos_start ); @@ -414,37 +490,37 @@ ivas_error ivas_qmetadata_enc_encode( /* Write raw flags */ next_ind_raw_flag = hMetaData->nb_ind_tot; - for ( i = start_band; i < nbands; i++ ) + FOR( i = start_band; i < nbands; i++ ) { push_next_indice( hMetaData, 0, 1 ); /* Raw coding flag*/ } bits_dir[d] = 0; diff_bits = bits_diff[d] + bits_coherence[d] + bits_signaling[d] - total_bits_1dir; - for ( i = start_band; i < nbands; i++ ) + FOR( i = start_band; i < nbands; i++ ) { bits_dir_bands[i] = ivas_qmetadata_raw_encode_dir( NULL, q_direction, i + 1, i ); /* Write ec bits */ bits_ec = ivas_qmetadata_entropy_encode_dir( hMetaData, q_direction, diffuseness_index_max_ec_frame, i + 1, i, bits_dir_bands[i], MASA_MAX_BITS, 0 ); - if ( bits_ec >= 0 ) + IF( GE_16( bits_ec, 0 ) ) { bits_dir_bands[i] = bits_ec; raw_flag[i] = 0; } - else + ELSE { raw_flag[i] = 1; } diff_bits += bits_dir_bands[i] + 1; } - small_requantize_direction_frame( q_direction, azimuth_orig, elevation_orig, raw_flag, bits_dir_bands, &diff_bits ); + small_requantize_direction_frame( q_direction, azimuth_orig_flt, elevation_orig_flt, raw_flag, bits_dir_bands, &diff_bits ); - for ( i = start_band; i < nbands; i++ ) + FOR( i = start_band; i < nbands; i++ ) { - if ( raw_flag[i] ) + IF( raw_flag[i] ) { /* Rewrite raw flag value */ hMetaData->ind_list[next_ind_raw_flag + i - start_band].value = 1; @@ -459,7 +535,7 @@ ivas_error ivas_qmetadata_enc_encode( } /* Requantized directions */ - if ( ( total_bits_1dir + bits_surround_coh <= hQMetaData->qmetadata_max_bit_req ) && ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] > total_bits_1dir ) ) + IF( LE_16( ( total_bits_1dir + bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) && GT_16( ( bits_dir[d] + bits_diff[d] + bits_coherence[d] + bits_signaling[d] ), total_bits_1dir ) ) { /*Bit budget exceeded, bit reduction strategy?*/ @@ -468,44 +544,40 @@ ivas_error ivas_qmetadata_enc_encode( restore_metadata_buffer( hMetaData, next_ind_start, bit_pos_start ); push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal no EC frame-wise (EC1)*/ - if ( nblocks > 1 ) + IF( GT_16( nblocks, 1 ) ) { push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal requantization stage (EC3)*/ bits_signaling[d] = 3; } - else + ELSE { bits_signaling[d] = 2; } - if ( hQMetaData->is_masa_ivas_format == 0 ) + IF( hQMetaData->is_masa_ivas_format == 0 ) { reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signaling[d] ); ind_order[0] = -1; } - else + ELSE { ind_order[0] = 0; reduce_bits = min( nbands * nblocks + MASA_BIT_REDUCT_PARAM, bits_dir_raw - ( total_bits_1dir - bits_diff[d] - bits_coherence[d] - bits_signaling[d] ) ); - if ( reduce_bits > bits_dir_raw - nbands * nblocks ) + IF( GT_16( reduce_bits, ( bits_dir_raw - nbands * nblocks ) ) ) { reduce_bits = bits_dir_raw - nbands * nblocks; } } -#ifdef IVAS_FLOAT_FIXED only_reduce_bits_direction_fx( &extra_bits, q_direction, reduce_bits, nbands, nblocks, ind_order ); -#else - only_reduce_bits_direction( &extra_bits, q_direction, reduce_bits, nbands, nblocks, ind_order ); -#endif bits_dir[d] = hMetaData->nb_bits_tot; - requantize_direction_EC_3( &extra_bits, q_direction, nbands, hMetaData, elevation_orig, azimuth_orig, ind_order ); + requantize_direction_EC_3( &extra_bits, q_direction, nbands, hMetaData, elevation_orig_flt, azimuth_orig_flt, ind_order ); bits_dir[d] = hMetaData->nb_bits_tot - bits_dir[d]; } /* finalize writing coherence */ - if ( ( bits_coherence[d] > 0 ) && ( all_coherence_zero == 0 ) && ( nblocks > 1 ) ) + IF( GT_16( bits_coherence[d], 0 ) && EQ_16( all_coherence_zero, 0 ) && GT_16( nblocks, 1 ) ) { bit_pos_start = hMetaData->nb_bits_tot; hMetaData->nb_bits_tot = bit_pos_start_coh; @@ -513,23 +585,30 @@ ivas_error ivas_qmetadata_enc_encode( hMetaData->nb_bits_tot = bit_pos_start; } - if ( d == 0 ) + IF( EQ_16( d, 0 ) ) { total_bits_1dir = hQMetaData->metadata_max_bits - ( hMetaData->nb_bits_tot - bit_pos_0 ); } /* Save quantized DOAs */ - for ( i = start_band; i < nbands; i++ ) + FOR( i = start_band; i < nbands; i++ ) { - mvr2r( q_direction->band_data[i].azimuth, q_direction->band_data[i].q_azimuth, nblocks ); - mvr2r( q_direction->band_data[i].elevation, q_direction->band_data[i].q_elevation, nblocks ); + Copy32( q_direction->band_data[i].azimuth_fx, q_direction->band_data[i].q_azimuth_fx, nblocks ); + Copy32( q_direction->band_data[i].elevation_fx, q_direction->band_data[i].q_elevation_fx, nblocks ); } /* Copy original DOAs back to q_direction*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS for ( i = start_band; i < nbands; i++ ) { - mvr2r( azimuth_orig[i], q_direction->band_data[i].azimuth, nblocks ); - mvr2r( elevation_orig[i], q_direction->band_data[i].elevation, nblocks ); + floatToFixed_arrL( azimuth_orig_flt[i], azimuth_orig[i], Q22, nblocks ); + floatToFixed_arrL( elevation_orig_flt[i], elevation_orig[i], Q22, nblocks ); + } +#endif + FOR( i = start_band; i < nbands; i++ ) + { + Copy32( azimuth_orig[i], q_direction->band_data[i].azimuth_fx, nblocks ); + Copy32( elevation_orig[i], q_direction->band_data[i].elevation_fx, nblocks ); } } @@ -998,9 +1077,55 @@ ivas_error ivas_qmetadata_enc_encode_hr_384_512( hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands; } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + for ( int k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + { + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = floatToFixed( hQMetaData->q_direction[0].band_data[j].energy_ratio[k], Q30 ); + } + } + if ( EQ_16( hQMetaData->no_directions, 2 ) ) + { + for ( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; ++j ) + { + for ( int k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + { + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = floatToFixed( hQMetaData->q_direction[1].band_data[j].energy_ratio[k], Q30 ); + } + } + } +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + /*Quantization and encoding of the Diffuseness */ + ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx( hQMetaData, bits_diff, bits_sph_idx, hMetaData ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + { + for ( int k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + { + hQMetaData->q_direction[0].band_data[j].energy_ratio[k] = fixedToFloat( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], Q30 ); + } + } + if ( EQ_16( hQMetaData->no_directions, 2 ) ) + { + for ( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; ++j ) + { + for ( int k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + { + hQMetaData->q_direction[1].band_data[j].energy_ratio[k] = fixedToFloat( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], Q30 ); + } + } + } +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else /*Quantization and encoding of the Diffuseness */ ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( hQMetaData, bits_diff, bits_sph_idx, hMetaData ); +#endif // IVAS_FLOAT_FIXED + /* Encode surround coherence */ if ( all_coherence_zero == 0 ) @@ -1029,13 +1154,19 @@ ivas_error ivas_qmetadata_enc_encode_hr_384_512( q_direction->not_in_2D = 0; - +#ifdef IVAS_FLOAT_FIXED + /*Coherence */ + IF( all_coherence_zero == 0 ) + { + ivas_qmetadata_quantize_coherence_hr_512_fx( hQMetaData, d, all_coherence_zero, hMetaData, bits_sp_coh ); + } +#else /*Coherence */ if ( all_coherence_zero == 0 ) { ivas_qmetadata_quantize_coherence_hr_512( hQMetaData, d, all_coherence_zero, hMetaData, bits_sp_coh ); } - +#endif /* write the spherical indexes */ bits_ec = hMetaData->nb_bits_tot; if ( bits_sph_idx == 11 ) @@ -1728,117 +1859,129 @@ int16_t quantize_direction2D( } #ifdef IVAS_FLOAT_FIXED -static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( +static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx( IVAS_QMETADATA_HANDLE hQMetaData, - int16_t *needed_bits, - const int16_t bits_dir_hr, + Word16 *needed_bits, + const Word16 bits_dir_hr, BSTR_ENC_HANDLE hMetaData ) { - int16_t j, k; - int16_t index; + Word16 j, k; + Word16 index; needed_bits[0] = 0; needed_bits[1] = 0; + move16(); + move16(); - for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) { - for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = floatToFixed( hQMetaData->q_direction[0].band_data[j].energy_ratio[k], Q30 ); - /*=====================================flt-2-fix============================================*/ - index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS ); -#else - index = masa_sq( 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[k], diffuseness_thresholds_hr, HR_MASA_ER_LEVELS ); -#endif + push_next_indice( hMetaData, index, MASA_BITS_ER_HR ); hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index; hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index; - hQMetaData->q_direction[0].band_data[j].energy_ratio[k] = 1.0f - diffuseness_reconstructions_hr[index]; - needed_bits[0] += MASA_BITS_ER_HR; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) ); // Q30 + needed_bits[0] = add( needed_bits[0], MASA_BITS_ER_HR ); hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_dir_hr; + move16(); + move16(); + move32(); + move16(); + move16(); } } - if ( hQMetaData->no_directions == 2 ) + IF( EQ_16( hQMetaData->no_directions, 2 ) ) { - float ratioSum; - if ( bits_dir_hr == 16 ) + Word32 ratioSum; + Word16 div_e; + IF( EQ_16( bits_dir_hr, 16 ) ) { - for ( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ ) + FOR( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ ) { - for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = floatToFixed( hQMetaData->q_direction[1].band_data[j].energy_ratio[k], Q30 ); - /*=====================================flt-2-fix============================================*/ - index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS ); -#else - index = masa_sq( 1.0f - hQMetaData->q_direction[1].band_data[j].energy_ratio[k], diffuseness_thresholds_hr, HR_MASA_ER_LEVELS ); -#endif + push_next_indice( hMetaData, index, MASA_BITS_ER_HR ); hQMetaData->q_direction[1].band_data[j].energy_ratio_index[k] = index; - hQMetaData->q_direction[1].band_data[j].energy_ratio[k] = 1.0f - diffuseness_reconstructions_hr[index]; + move16(); + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) ); + move32(); - ratioSum = hQMetaData->q_direction[0].band_data[j].energy_ratio[k] + hQMetaData->q_direction[1].band_data[j].energy_ratio[k]; - if ( ratioSum > 1.0f ) + ratioSum = L_add( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ); + IF( GT_32( ratioSum, ONE_IN_Q30 /*1.0f*/ ) ) { - hQMetaData->q_direction[0].band_data[j].energy_ratio[k] /= ratioSum; - hQMetaData->q_direction[1].band_data[j].energy_ratio[k] /= ratioSum; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_cadence( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], ratioSum, &div_e ); + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) ); + move32(); + move32(); + + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_cadence( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], ratioSum, &div_e ); + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) ); + move32(); + move32(); } - needed_bits[1] += MASA_BITS_ER_HR; + needed_bits[1] = add( needed_bits[1], MASA_BITS_ER_HR ); + move16(); hQMetaData->q_direction[1].band_data[j].bits_sph_idx[k] = bits_dir_hr; + move16(); } } } - else + ELSE { - int16_t pos_2dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 pos_2dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; k = 0; - for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; j++ ) + move16(); + FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; j++ ) { - if ( hQMetaData->twoDirBands[j] == 1 ) + IF( EQ_16( hQMetaData->twoDirBands[j], 1 ) ) { pos_2dir_band[k] = j; - k++; + move16(); + k = add( k, 1 ); } - else + ELSE { pos_2dir_band[k] = 0; + move16(); } } - for ( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ ) + FOR( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ ) { - for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = floatToFixed( hQMetaData->q_direction[1].band_data[j].energy_ratio[k], Q30 ); - /*=====================================flt-2-fix============================================*/ - index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS ); -#else - index = masa_sq( 1.0f - hQMetaData->q_direction[1].band_data[j].energy_ratio[k], diffuseness_thresholds_hr, HR_MASA_ER_LEVELS ); -#endif + push_next_indice( hMetaData, index, MASA_BITS_ER_HR ); hQMetaData->q_direction[1].band_data[j].energy_ratio_index[k] = index; - hQMetaData->q_direction[1].band_data[j].energy_ratio[k] = 1.0f - diffuseness_reconstructions_hr[index]; + move16(); + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) ); + move32(); - ratioSum = hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio[k] + hQMetaData->q_direction[1].band_data[j].energy_ratio[k]; + ratioSum = L_add( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ); - if ( ratioSum > 1.0f ) + IF( GT_32( ratioSum, ONE_IN_Q30 /*1.0f*/ ) ) { - hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio[k] /= ratioSum; - hQMetaData->q_direction[1].band_data[j].energy_ratio[k] /= ratioSum; + hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_cadence( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], ratioSum, &div_e ); + hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], sub( div_e, 1 ) ); + move32(); + move32(); + + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_cadence( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], ratioSum, &div_e ); + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) ); + move32(); + move32(); } - needed_bits[1] += MASA_BITS_ER_HR; + needed_bits[1] = add( needed_bits[1], MASA_BITS_ER_HR ); + move16(); hQMetaData->q_direction[1].band_data[j].bits_sph_idx[k] = bits_dir_hr; + move16(); } } } @@ -1951,16 +2094,16 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512( *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( +static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *needed_bits, int16_t *nbits_diff, int16_t *dfRatioBits, const int16_t hodirac_flag ) { - int16_t j, k, dir2band; - int16_t index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod; - int16_t index_diff; + Word16 j, k, dir2band; + Word16 index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod; + Word16 index_diff; nbits_diff[0] = 0; nbits_diff[1] = 0; @@ -1968,53 +2111,43 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( needed_bits[1] = 0; dir2band = 0; - for ( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) + FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j ) { - if ( hQMetaData->no_directions == 2 && hQMetaData->twoDirBands[j] == 1 ) + IF( hQMetaData->no_directions == 2 && hQMetaData->twoDirBands[j] == 1 ) { - float diffRatio, dfRatio, dfRatioQ, diffRatioQ, dirRatio1Q, dirRatio2Q; -#ifdef IVAS_FLOAT_FIXED - Word32 diffRatio_fx, dirRatio1Q_fx, dirRatio2Q_fx; -#endif - float dirRatio1, dirRatio2, sumRatio; - int16_t dfRatio_index, dfRatio_qsteps, dfRatio_bits; + Word32 diffRatio, dfRatio, dfRatioQ, diffRatioQ, dirRatio1Q, dirRatio2Q; /* Q30 */ + Word32 dirRatio1, dirRatio2, sumRatio; /* Q30 */ + Word16 dfRatio_index, dfRatio_qsteps, dfRatio_bits; /* With 2dir metadata, we quantize and transmit diffuse-to-total ratio (diffRatio) and * distribution factor of direct-to-total ratios (dFRatio). This is more efficient and * accurate than simple separate quantization of each direct-to-total ratio or their * separate inverses. */ - if ( hodirac_flag ) + IF( hodirac_flag ) { /* already encoded as total and ratios in HO-DirAC */ - diffRatio = 1.f - hQMetaData->q_direction[0].band_data[j].energy_ratio[0]; - dfRatio = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[0]; + diffRatio = ( 1 << 30 ) - hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0]; + dfRatio = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0]; } - else + ELSE { - dirRatio1 = hQMetaData->q_direction[0].band_data[j].energy_ratio[0]; - dirRatio2 = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[0]; + // TODO + dirRatio1 = hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0]; + dirRatio2 = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0]; sumRatio = dirRatio1 + dirRatio2; - diffRatio = 1.0f - sumRatio; - dfRatio = sumRatio < EPSILON ? 0.5f : dirRatio1 / sumRatio; + diffRatio = ( 1 << 30 ) - sumRatio; + dfRatio = sumRatio < EPSILON_FIX ? ( 1 << 29 ) : ( (Word32) div_l( dirRatio1, extract_h( sumRatio ) ) << 15 ); } -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - diffRatio_fx = floatToFixed( diffRatio, Q30 ); - /*=====================================flt-2-fix============================================*/ + index_diff = masa_sq_fx( diffRatio, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); + diffRatioQ = diffuseness_reconstructions_fx[index_diff]; - index_diff = masa_sq_fx( diffRatio_fx, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - index_diff = masa_sq( diffRatio, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif - diffRatioQ = diffuseness_reconstructions[index_diff]; - - if ( hodirac_flag ) + IF( hodirac_flag ) { dfRatio_bits = ivas_get_df_ratio_bits_hodirac( index_diff ); } - else + ELSE { dfRatio_bits = ivas_get_df_ratio_bits( index_diff ); } @@ -2022,63 +2155,53 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( dfRatioBits[dir2band] = dfRatio_bits; dfRatio_qsteps = ( 1 << dfRatio_bits ); - if ( hodirac_flag ) + IF( hodirac_flag ) { - dfRatio_index = usquant( dfRatio, &dfRatioQ, 0.0f, 1.f / ( dfRatio_qsteps - 1 ), dfRatio_qsteps ); - dirRatio1Q = 1.f - diffRatioQ; + // TODO + Word16 dfRatioQ16; /* Q14 */ + dfRatio_index = usquant_fx( extract_h( dfRatio ), &dfRatioQ16, 0, ( div_s( 1, ( dfRatio_qsteps - 1 ) ) >> 2 ), dfRatio_qsteps ); + dfRatioQ = (Word32) dfRatioQ16 << 16; + dirRatio1Q = ( 1 << 30 ) - diffRatioQ; dirRatio2Q = dfRatioQ; } - else + ELSE { - dfRatio_index = usquant( dfRatio, &dfRatioQ, 0.5f, 0.5f / ( dfRatio_qsteps - 1 ), dfRatio_qsteps ); + // TODO + Word16 dfRatioQ16; /* Q14 */ + dfRatio_index = usquant_fx( extract_h( dfRatio ), &dfRatioQ16, ( 1 << 13 ), ( div_s( 1, ( dfRatio_qsteps - 1 ) ) >> 3 ), dfRatio_qsteps ); /* Direction quantization requires also separately quantized direct-to-total ratios. Thus, we calculate them. */ - dirRatio1Q = dfRatioQ * ( 1.0f - diffRatioQ ); - dirRatio2Q = ( 1.0f - diffRatioQ ) - dirRatio1Q; + dirRatio1Q = L_shl( Mpy_32_16_1( ( ( 1 << 30 ) - diffRatioQ ), dfRatioQ16 ), 1 ); + dirRatio2Q = ( ( 1 << 30 ) - diffRatioQ ) - dirRatio1Q; } -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - dirRatio1Q_fx = floatToFixed( dirRatio1Q, Q30 ); - /*=====================================flt-2-fix============================================*/ - - index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, dirRatio1Q_fx ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - index_dirRatio1Inv = masa_sq( 1.0f - dirRatio1Q, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif + index_dirRatio1Inv = masa_sq_fx( ( 1 << 30 ) - dirRatio1Q, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); /* Note: To save memory, we store temporarily index_diff and dfRatio_index into first and second direction * energy ratio index variables until they have been encoded. index_dirRatio1Inv and index_dirRatio2Inv are * then later retrieved for further use in encoding. */ - for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_diff; - hQMetaData->q_direction[0].band_data[j].energy_ratio[k] = dirRatio1Q; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = dirRatio1Q; } nbits_diff[0] += MASA_BITS_ER; - if ( hodirac_flag ) + IF( hodirac_flag ) { - float tmp; - index_dirRatio2Inv = usquant( dirRatio2Q, &tmp, 0.0f, 1.f / ( DIRAC_DIFFUSE_LEVELS - 1 ), DIRAC_DIFFUSE_LEVELS ); + // TODO + Word16 tmp; /* Q14 */ + index_dirRatio2Inv = usquant_fx( extract_h( dirRatio2Q ), &tmp, 0, ( div_s( 1, ( DIRAC_DIFFUSE_LEVELS - 1 ) ) >> 2 ), DIRAC_DIFFUSE_LEVELS ); } else { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - dirRatio2Q_fx = floatToFixed( dirRatio2Q, Q30 ); - /*=====================================flt-2-fix============================================*/ - - index_dirRatio2Inv = masa_sq_fx( L_sub( ONE_IN_Q30, dirRatio2Q_fx ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - index_dirRatio2Inv = masa_sq( 1.0f - dirRatio2Q, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif + index_dirRatio2Inv = masa_sq_fx( ( 1 << 30 ) - dirRatio2Q, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); } - for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) { hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[k] = dfRatio_index; - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[k] = dirRatio2Q; + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[k] = dirRatio2Q; } nbits_diff[1] += dfRatio_bits; @@ -2086,20 +2209,16 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( * fact that with 2dir data, it is harder to achieve separate high direct-to-total ratio values * which are assumed by the direction quantization system. In practice, this improves direction * accuracy when it is perceptual meaningful. */ -#ifdef IVAS_FLOAT_FIXED masa_compensate_two_dir_energy_ratio_index_fx( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); -#else - masa_compensate_two_dir_energy_ratio_index( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); -#endif - for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index_dirRatio1Inv_mod; hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_direction_masa[index_dirRatio1Inv_mod]; } needed_bits[0] += hQMetaData->q_direction[0].cfg.nblocks * bits_direction_masa[index_dirRatio1Inv_mod]; - for ( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ ) { hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index_mod[k] = index_dirRatio2Inv_mod; hQMetaData->q_direction[1].band_data[dir2band].bits_sph_idx[k] = bits_direction_masa[index_dirRatio2Inv_mod]; @@ -2108,23 +2227,15 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( dir2band++; } - else + ELSE { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] = floatToFixed( hQMetaData->q_direction[0].band_data[j].energy_ratio[0], Q30 ); - /*=====================================flt-2-fix============================================*/ - - index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - index_dirRatio1Inv = masa_sq( 1.0f - hQMetaData->q_direction[0].band_data[j].energy_ratio[0], diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif + index_dirRatio1Inv = masa_sq_fx( ( 1 << 30 ) - hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0], diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); - for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) + FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_dirRatio1Inv; hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index_dirRatio1Inv; - hQMetaData->q_direction[0].band_data[j].energy_ratio[k] = 1.0f - diffuseness_reconstructions[index_dirRatio1Inv]; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = ( 1 << 30 ) - diffuseness_reconstructions_fx[index_dirRatio1Inv]; hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_direction_masa[index_dirRatio1Inv]; } @@ -2292,7 +2403,33 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( * * *------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_diffuseness_huff_ec_encode_fx( + BSTR_ENC_HANDLE hMetaData, + const UWord16 idx ) +{ + Word16 nbits; + nbits = 0; + move16(); + IF( LE_16( idx, DIFF_EC_HUFF_GR0_LIMIT ) ) + { + IF( idx > 0 ) + { + push_next_indice( hMetaData, ( 1 << idx ) - 1, idx ); + nbits = add( nbits, idx ); + } + push_next_indice( hMetaData, 0, 1 ); + nbits = add( nbits, 1 ); + } + ELSE + { + push_next_indice( hMetaData, 511, DIFF_EC_HUFF_GR0_LIMIT + 1 ); + push_next_indice( hMetaData, idx - DIFF_EC_HUFF_GR0_LIMIT - 1, 2 ); + nbits = add( nbits, DIFF_EC_HUFF_GR0_LIMIT + 3 ); + } + return nbits; +} +#else static int16_t ivas_diffuseness_huff_ec_encode( BSTR_ENC_HANDLE hMetaData, const uint16_t idx ) @@ -2317,14 +2454,98 @@ static int16_t ivas_diffuseness_huff_ec_encode( } return nbits; } - +#endif /*------------------------------------------------------------------------- * ivas_diffuseness_huff_ec_prepare() * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_diffuseness_huff_ec_prepare_fx( + IVAS_QDIRECTION *q_direction, + Word16 *best_av, + UWord16 *avr_idx, + Word16 *diffuseness_bits_huff ) +{ + Word16 bits; + Word16 av_crt; + Word16 av; + Word16 av_e; + Word16 sh_idx; + UWord16 ui_sh_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 b, start_band, nbands; + + start_band = q_direction->cfg.start_band; + move16(); + nbands = q_direction->cfg.nbands; + move16(); + + *diffuseness_bits_huff = 0; + move16(); + av = 0; + move16(); + FOR( b = start_band; b < nbands; b++ ) + { + av = add( av, q_direction->band_data[b].energy_ratio_index[0] ); + } + // av = (int16_t) ( 0.5f + av / (float) nbands ); + av = BASOP_Util_Divide1616_Scale( av, nbands, &av_e ); + av = shr_r( av, sub( 15, av_e ) ); + *best_av = av; + move16(); + + *diffuseness_bits_huff = MAX16B; + move16(); + FOR( av_crt = av - 1; av_crt <= av + 1; av_crt++ ) + { + bits = 0; + move16(); + FOR( b = start_band; b < nbands; b++ ) + { + sh_idx = sub( q_direction->band_data[b].energy_ratio_index[0], av_crt ); + // ui_sh_idx[b] = ( sh_idx <= 0 ) ? ( -2 * sh_idx ) : sh_idx * 2 - 1; + IF( sh_idx <= 0 ) + { + ui_sh_idx[b] = negate( shl( sh_idx, 1 ) ); + } + ELSE + { + ui_sh_idx[b] = sub( shl( sh_idx, 1 ), 1 ); + } + if ( GE_32( ui_sh_idx[b], 2 * DIRAC_DIFFUSE_LEVELS - 3 ) ) + { + bits = 100; /* to avoid difference larger than 6 in absolute value */ + move16(); + } + + // bits += ( ui_sh_idx[b] <= DIFF_EC_HUFF_GR0_LIMIT ) ? ( ui_sh_idx[b] + 1 ) : 11; + IF( LE_32( ui_sh_idx[b], DIFF_EC_HUFF_GR0_LIMIT ) ) + { + bits = add( bits, add( ui_sh_idx[b], 1 ) ); + } + ELSE + { + bits = add( bits, 11 ); + } + } + + IF( LT_16( bits, *diffuseness_bits_huff ) ) + { + *diffuseness_bits_huff = bits; + move16(); + Copy( (Word16 *) ui_sh_idx, (Word16 *) avr_idx, nbands ); + *best_av = av_crt; + move16(); + } + } + + *diffuseness_bits_huff = add( *diffuseness_bits_huff, MASA_BITS_ER ); /* for the average */ + move16(); + return; +} +#else static void ivas_diffuseness_huff_ec_prepare( IVAS_QDIRECTION *q_direction, int16_t *best_av, @@ -2378,13 +2599,147 @@ static void ivas_diffuseness_huff_ec_prepare( return; } +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_entropy_encode_diffuseness() * * encode diffuseness *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_encode_diffuseness_fx( + BSTR_ENC_HANDLE hMetaData, + IVAS_QDIRECTION *q_direction, + UWord16 *diffuseness_index_max_ec_frame ) +{ + Word16 start_bit_pos; + Word16 diffuseness_bits_raw; + Word16 b; + Word16 min_diffuseness_m_index, max_diffuseness_m_index; + Word16 nbands; + Word16 start_band; + + nbands = q_direction->cfg.nbands; + move16(); + start_band = q_direction->cfg.start_band; + move16(); + + start_bit_pos = hMetaData->nb_bits_tot; + move16(); + + IF( EQ_16( nbands, 1 ) ) + { + /* If there is only one band, diffuseness should be coded directly as raw with no signaling. */ + push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], MASA_BITS_ER ); + *diffuseness_index_max_ec_frame = 5; + move16(); + return sub( hMetaData->nb_bits_tot, start_bit_pos ); + } + + /* compute the number of raw coding bits */ + diffuseness_bits_raw = 0; + move16(); + FOR( b = start_band; b < nbands; b++ ) + { + diffuseness_bits_raw = add( diffuseness_bits_raw, ivas_qmetadata_encode_quasi_uniform_length( q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ) ); + } + + min_diffuseness_m_index = q_direction->band_data[start_band].energy_ratio_index[0]; + move16(); + max_diffuseness_m_index = q_direction->band_data[start_band].energy_ratio_index[0]; + move16(); + + FOR( b = start_band; b < nbands; b++ ) + { + if ( LT_16( q_direction->band_data[b].energy_ratio_index[0], min_diffuseness_m_index ) ) + { + min_diffuseness_m_index = q_direction->band_data[b].energy_ratio_index[0]; + move16(); + } + + if ( GT_16( q_direction->band_data[b].energy_ratio_index[0], max_diffuseness_m_index ) ) + { + max_diffuseness_m_index = q_direction->band_data[b].energy_ratio_index[0]; + move16(); + } + } + + IF( LT_16( nbands, DIFF_EC_HUFF_BAND_LIMIT ) ) + { + /* Use similarity coding approach or raw coding when there is a low number of bands. */ + /* one bit is used to indicate whether diffuseness values are entropy coded or coded raw */ + IF( EQ_16( min_diffuseness_m_index, max_diffuseness_m_index ) ) /* all values are equal */ + { + push_next_indice( hMetaData, 0, 1 ); /* dif_use_raw_coding */ + push_next_indice( hMetaData, 1, 1 ); /* dif_have_unique_value */ + ivas_qmetadata_encode_quasi_uniform( hMetaData, min_diffuseness_m_index, DIRAC_DIFFUSE_LEVELS ); /* dif_unique_value */ + } + ELSE IF( EQ_16( add( min_diffuseness_m_index, 1 ), max_diffuseness_m_index ) ) /* only two consecutive values are present */ + { + push_next_indice( hMetaData, 0, 1 ); /* dif_use_raw_coding */ + push_next_indice( hMetaData, 0, 1 ); /* dif_have_unique_value */ + ivas_qmetadata_encode_quasi_uniform( hMetaData, min_diffuseness_m_index, DIRAC_DIFFUSE_LEVELS - 1 ); /* dif_min_value */ + + FOR( b = start_band; b < nbands; b++ ) + { + push_next_indice( hMetaData, sub( q_direction->band_data[b].energy_ratio_index[0], min_diffuseness_m_index ), 1 ); /* dif_bit_offset_values */ + } + } + ELSE /* raw coding */ + { + push_next_indice( hMetaData, 1, 1 ); /* dif_use_raw_coding */ + + FOR( b = start_band; b < nbands; b++ ) + { + ivas_qmetadata_encode_quasi_uniform( hMetaData, q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ); /* dif_values */ + } + } + } + ELSE + { + /* Use Huffman-coding approach or raw coding when there is a high number of bands. */ + Word16 diffuseness_bits_huff; + Word16 best_av; + UWord16 avr_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + + /* First, obtain average indices and bit usage for Huffman-coding. */ + ivas_diffuseness_huff_ec_prepare_fx( q_direction, &best_av, avr_idx, &diffuseness_bits_huff ); + /* If there is benefit, use Huffman-coding. Otherwise, use raw coding. */ + IF( LT_16( diffuseness_bits_huff, diffuseness_bits_raw ) ) + { + /* Signal Huffman EC */ + push_next_indice( hMetaData, 0, 1 ); + push_next_indice( hMetaData, best_av, MASA_BITS_ER ); + FOR( b = start_band; b < nbands; b++ ) + { + ivas_diffuseness_huff_ec_encode_fx( hMetaData, avr_idx[b] ); + } + } + ELSE + { + /* Signal raw */ + push_next_indice( hMetaData, 1, 1 ); + FOR( b = start_band; b < nbands; b++ ) + { + ivas_qmetadata_encode_quasi_uniform( hMetaData, q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ); /* dif_values */ + } + } + } + + *diffuseness_index_max_ec_frame = 5; + move16(); + /* adaptively select the diffuseness_index_max_ec threshold */ + if ( GT_16( min_diffuseness_m_index, 5 ) ) + { + *diffuseness_index_max_ec_frame = DIRAC_DIFFUSE_LEVELS - 1; + move16(); + } + + + return sub( hMetaData->nb_bits_tot, start_bit_pos ); +} +#else static int16_t ivas_qmetadata_entropy_encode_diffuseness( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, @@ -2506,14 +2861,131 @@ static int16_t ivas_qmetadata_entropy_encode_diffuseness( return ( hMetaData->nb_bits_tot - start_bit_pos ); } - +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_entropy_encode_df_ratio() * * encode dfRatio *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_encode_df_ratio_fx( + BSTR_ENC_HANDLE hMetaData, + IVAS_QDIRECTION *q_direction, + Word16 *df_ratio_bits ) +{ + Word16 start_bit_pos; + Word16 bits_raw; + Word16 b; + Word16 min_index, max_index; + Word16 nbands, start_band; + Word16 max_df_ratio_bits; + Word16 ec_mode = 0; + move16(); + Word16 max_alphabet_size; + + nbands = q_direction->cfg.nbands; + move16(); + start_band = q_direction->cfg.start_band; + move16(); + + start_bit_pos = hMetaData->nb_bits_tot; + move16(); + + IF( EQ_16( nbands, 1 ) ) + { + /* If there is only one band, ratio should be coded directly as raw with no signaling. */ + push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], df_ratio_bits[0] ); + + return sub( hMetaData->nb_bits_tot, start_bit_pos ); + } + /* compute the number of raw coding bits */ + bits_raw = 0; + move16(); + max_df_ratio_bits = 0; + move16(); + FOR( b = start_band; b < nbands; b++ ) + { + bits_raw = add( bits_raw, df_ratio_bits[b] ); + max_df_ratio_bits = s_max( df_ratio_bits[b], max_df_ratio_bits ); + } + + min_index = q_direction->band_data[start_band].energy_ratio_index[0]; + move16(); + max_index = q_direction->band_data[start_band].energy_ratio_index[0]; + move16(); + FOR( b = start_band; b < nbands; b++ ) + { + if ( LT_16( q_direction->band_data[b].energy_ratio_index[0], min_index ) ) + { + min_index = q_direction->band_data[b].energy_ratio_index[0]; + move16(); + } + + if ( GT_16( q_direction->band_data[b].energy_ratio_index[0], max_index ) ) + { + max_index = q_direction->band_data[b].energy_ratio_index[0]; + move16(); + } + } + + /* Decide what modes are possible */ + IF( GE_16( bits_raw, add( add( max_df_ratio_bits, 2 ), nbands ) ) ) + { + ec_mode = 2; + } + ELSE IF( GE_16( bits_raw, add( max_df_ratio_bits, 1 ) ) ) + { + ec_mode = 1; + } + ELSE + { + ec_mode = 0; + } + move16(); + max_alphabet_size = shl( 1, max_df_ratio_bits ); + + test(); + test(); + IF( EQ_16( min_index, max_index ) && ec_mode > 0 ) /* all values are equal */ + { + push_next_indice( hMetaData, 0, 1 ); /* Signal between EC and raw */ + if ( GT_16( ec_mode, 1 ) ) + { + /* Only use bit for signaling if necessary */ + push_next_indice( hMetaData, 0, 1 ); /* Signal between one value or bandwise diff mode */ + } + + ivas_qmetadata_encode_quasi_uniform( hMetaData, min_index, max_alphabet_size ); + } + ELSE IF( EQ_16( add( min_index, 1 ), max_index ) && GT_16( ec_mode, 1 ) ) /* only two consecutive values are present */ + { + push_next_indice( hMetaData, 0, 1 ); + push_next_indice( hMetaData, 1, 1 ); + ivas_qmetadata_encode_quasi_uniform( hMetaData, min_index, max_alphabet_size - 1 ); + + FOR( b = start_band; b < nbands; b++ ) + { + push_next_indice( hMetaData, q_direction->band_data[b].energy_ratio_index[0] - min_index, 1 ); /* Band-wise offset values */ + } + } + ELSE /* raw coding */ + { + IF( ec_mode > 0 ) + { + push_next_indice( hMetaData, 1, 1 ); /* Only signal raw mode if not implicitly using it */ + } + + FOR( b = start_band; b < nbands; b++ ) + { + ivas_qmetadata_encode_quasi_uniform( hMetaData, q_direction->band_data[b].energy_ratio_index[0], shl( 1, df_ratio_bits[b] ) ); /* dif_values */ + } + } + + return sub( hMetaData->nb_bits_tot, start_bit_pos ); +} +#else static int16_t ivas_qmetadata_entropy_encode_df_ratio( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, @@ -2617,7 +3089,7 @@ static int16_t ivas_qmetadata_entropy_encode_df_ratio( return ( hMetaData->nb_bits_tot - start_bit_pos ); } - +#endif /*------------------------------------------------------------------------- * restore_metadata_buffer() @@ -2648,7 +3120,7 @@ void restore_metadata_buffer( * * encode value using a quasi-uniform code of b or b + 1 bits, where b = floor(log2(alphabet_size)) *------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void ivas_qmetadata_encode_quasi_uniform( BSTR_ENC_HANDLE hMetaData, const uint16_t value, @@ -2671,6 +3143,30 @@ static void ivas_qmetadata_encode_quasi_uniform( return; } +#else +static void ivas_qmetadata_encode_quasi_uniform( + BSTR_ENC_HANDLE hMetaData, + const UWord16 value, + const UWord16 alphabet_size ) +{ + Word16 bits; + UWord16 tresh; + + bits = sub( 30, norm_l( alphabet_size ) ); /* bits = floor(log2(alphabet_size)) */ + tresh = (UWord16) L_sub( L_shl( 1U, add( bits, 1 ) ), alphabet_size ); + + IF( LT_32( value, tresh ) ) + { + push_next_indice( hMetaData, value, bits ); + } + ELSE /* value >= tresh */ + { + push_next_indice( hMetaData, (UWord16) L_add( value, tresh ), add( bits, 1 ) ); + } + + return; +} +#endif /*-----------------------------------------------------------------------* @@ -2681,7 +3177,59 @@ static void ivas_qmetadata_encode_quasi_uniform( * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/*! r: number of bits using Golomb Rice code */ +static Word16 GR_bits_new( + UWord16 *data, /* i : data to encode with GR */ + Word16 *no_symb, /* i : number of symbols for each component*/ + const Word16 no_data, /* i : number of input data */ + const Word16 GR_order, /* i : GR order to be used */ + const Word16 check_two_orders, /* i : check also coding with GR_order-1 */ + Word16 *real_GR_ord /* o : the GR order that has been used */ +) +{ + Word16 nbits = 0, i; + Word16 nbits1 = 0; + Word16 nb; + move16(); + move16(); + + FOR( i = 0; i < no_data; i++ ) + { + nb = ivas_qmetadata_encode_extended_gr_length( data[i], no_symb[i], GR_order ); + nbits = add( nbits, nb ); + } + + IF( EQ_16( check_two_orders, 1 ) ) + { + FOR( i = 0; i < no_data; i++ ) + { + nb = ivas_qmetadata_encode_extended_gr_length( data[i], no_symb[i], GR_order - 1 ); + nbits1 = add( nbits1, nb ); + } + IF( nbits1 < nbits ) + { + nbits = add( nbits1, 1 ); + *real_GR_ord = sub( GR_order, 1 ); + move16(); + } + ELSE + { + nbits = add( nbits, 1 ); + *real_GR_ord = GR_order; + move16(); + } + } + ELSE + { + *real_GR_ord = GR_order; + move16(); + } + + return nbits; +} +#else /*! r: number of bits using Golomb Rice code */ static int16_t GR_bits_new( uint16_t *data, /* i : data to encode with GR */ @@ -2728,6 +3276,7 @@ static int16_t GR_bits_new( return nbits; } +#endif /*------------------------------------------------------------------------- @@ -2833,7 +3382,60 @@ static int16_t GR_bits_azimuth_context( * * Golomb Rice encoding with mean removing *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/*! r: number of bits used */ +static Word16 mean_removed_GR_new( + const UWord16 *idx, /* i : data to encode */ + const Word16 max_no_symb, + const Word16 len, /* i : number of data */ + const Word16 adapt_GR, /* i : flag for telling to use or nor two GR order values */ + Word16 *GR_ord, /* i/o: GR order */ + UWord16 *p_av, /* o : average index */ + UWord16 *mr_idx /* o : mean removed indexes */ +) +{ + Word16 av, i, nbits; + Word16 sh_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 max_ns[MASA_MAXIMUM_CODING_SUBBANDS]; + + /* av = (Word16) ( 0.5f + sum_s( (const Word16 *) idx, len ) / (float) len ); */ + av = div_l( L_add( L_shl( sum16_fx( (const Word16 *) idx, len ), 1 ), 1 ), len ); + *p_av = av; + move16(); + FOR( i = 0; i < len; i++ ) + { + max_ns[i] = shl( max_no_symb, 1 ); + sh_idx[i] = sub( idx[i], av ); + move16(); + move16(); + } + + FOR( i = 0; i < len; i++ ) + { + IF( sh_idx[i] < 0 ) + { + sh_idx[i] = -2 * sh_idx[i]; + } + ELSE IF( sh_idx[i] > 0 ) + { + sh_idx[i] = sub( shl( sh_idx[i], 1 ), 1 ); + move16(); + } + ELSE + { + sh_idx[i] = 0; + move16(); + } + mr_idx[i] = (UWord16) sh_idx[i]; + move16(); + } + + nbits = GR_bits_new( mr_idx, max_ns, len, *GR_ord, adapt_GR, GR_ord ); + + return nbits; +} +#else /*! r: number of bits used */ static int16_t mean_removed_GR_new( const uint16_t *idx, /* i : data to encode */ @@ -2878,13 +3480,31 @@ static int16_t mean_removed_GR_new( return nbits; } - +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_encode_quasi_uniform_length() * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_encode_quasi_uniform_length( + const UWord16 value, + const UWord16 alphabet_size ) +{ + Word16 bits; + UWord16 tresh; + bits = sub( 30, norm_l( alphabet_size ) ); /* bits = floor(log2(alphabet_size)) */ + tresh = (UWord16) L_sub( L_shl( 1U, add( bits, 1 ) ), alphabet_size ); + + IF( GE_32( value, tresh ) ) + { + bits = add( bits, 1 ); + } + + return bits; +} +#else static int16_t ivas_qmetadata_encode_quasi_uniform_length( const uint16_t value, const uint16_t alphabet_size ) @@ -2902,7 +3522,7 @@ static int16_t ivas_qmetadata_encode_quasi_uniform_length( return bits; } - +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_entropy_encode_dir() @@ -4111,7 +4731,45 @@ static int16_t ivas_qmetadata_get_optimal_gr_param( * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word16 +ivas_qmetadata_encode_extended_gr_length( + const UWord16 value, + const UWord16 alphabet_size, + const Word16 gr_param ) +{ + UWord16 msb_alphabet_size; + Word16 bits; + UWord16 msb, lsb; + + + msb_alphabet_size = (UWord16) L_shr( L_add( alphabet_size, L_sub( L_shl( 1U, gr_param ), 1 ) ), gr_param ); + + IF( LE_32( msb_alphabet_size, 3 ) ) + { + /* EncodeQuasiUniform is always equal or better than Limited GR with up to 3 msb values */ + bits = ivas_qmetadata_encode_quasi_uniform_length( value, alphabet_size ); + } + ELSE + { + msb = (UWord16) L_shr( value, gr_param ); + bits = msb; /* leading one bits */ + move16(); + IF( LT_32( msb, L_sub( msb_alphabet_size, 1 ) ) ) + { + bits = add( bits, add( 1, gr_param ) ); /* terminating zero bit, if not the largest msb (Limited GR), and the lsb bits */ + } + ELSE + { + lsb = (UWord16) L_and( value, L_sub( L_shl( 1U, gr_param ), 1 ) ); + bits = add( bits, ivas_qmetadata_encode_quasi_uniform_length( lsb, (UWord16) L_sub( alphabet_size, L_shl( L_sub( msb_alphabet_size, 1 ), gr_param ) ) ) ); + } + } + + return bits; +} +#else int16_t ivas_qmetadata_encode_extended_gr_length( const uint16_t value, @@ -4148,7 +4806,7 @@ ivas_qmetadata_encode_extended_gr_length( return bits; } - +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_reorder_elevation_index() @@ -4234,7 +4892,52 @@ static int16_t ivas_qmetadata_reorder_azimuth_index( * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_qmetadata_encode_extended_gr( + BSTR_ENC_HANDLE hMetaData, + const UWord16 value, + const UWord16 alphabet_size, + const Word16 gr_param ) +{ + UWord16 msb_alphabet_size; + UWord16 msb, lsb, cnt; + + + msb_alphabet_size = (UWord16) L_shr( L_add( alphabet_size, L_sub( L_shl( 1U, gr_param ), 1 ) ), gr_param ); + IF( LE_32( msb_alphabet_size, 3 ) ) + { + /* EncodeQuasiUniform is always equal or better than Limited GR with up to 3 msb values */ + ivas_qmetadata_encode_quasi_uniform( hMetaData, value, alphabet_size ); + } + ELSE + { + msb = (UWord16) L_shr( value, gr_param ); + lsb = (UWord16) L_and( value, L_sub( L_shl( 1U, gr_param ), 1 ) ); + + FOR( cnt = 0; cnt < msb; cnt++ ) + { + /* leading one bits */ + push_next_indice( hMetaData, 1, 1 ); + } + + IF( LT_32( msb, L_sub( msb_alphabet_size, 1 ) ) ) + { + push_next_indice( hMetaData, 0, 1 ); /* terminating zero bit, if not the largest msb (Limited GR) */ + IF( gr_param > 0 ) + { + push_next_indice( hMetaData, lsb, gr_param ); + } + } + ELSE + { + ivas_qmetadata_encode_quasi_uniform( hMetaData, lsb, (UWord16) L_sub( alphabet_size, L_shl( L_sub( msb_alphabet_size, 1 ), gr_param ) ) ); + } + } + + return; +} +#else void ivas_qmetadata_encode_extended_gr( BSTR_ENC_HANDLE hMetaData, const uint16_t value, @@ -4279,7 +4982,7 @@ void ivas_qmetadata_encode_extended_gr( return; } - +#endif /*-----------------------------------------------------------------------* * Local functions (EC3, requantize directions) @@ -5591,7 +6294,30 @@ static ivas_error write_ec_direction( /*-----------------------------------------------------------------------* * Local functions (coherence Q and coding) *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/*! r: index */ +static UWord64 create_combined_index( + UWord16 *idx_dct, /* i : indexes to combine */ + const Word16 len, /* i : number of indexes */ + const Word16 *no_cb_vec /* i : how many codewords for each position */ +) +{ + Word16 i; + UWord64 idx, base; + base = 1; + move64(); + idx = 0; + move64(); + FOR( i = 0; i < len; i++ ) + { + idx = W_add( idx, base * idx_dct[i] ); + base *= no_cb_vec[i]; + } + + return idx; +} +#else /*! r: index */ static uint64_t create_combined_index( uint16_t *idx_dct, /* i : indexes to combine */ @@ -5612,7 +6338,7 @@ static uint64_t create_combined_index( return idx; } - +#endif /*-----------------------------------------------------------------------* * encoding DCT0 coeffs with joint index @@ -5668,35 +6394,131 @@ static int16_t encode_coherence_indexesDCT0( if ( nbits1 > 0 ) { - if ( nbits1 % 16 == 0 ) + if ( nbits1 % 16 == 0 ) + { + no_idx16 = nbits1 / 16; + } + else + { + no_idx16 = (int16_t) round_f( ( nbits1 / 16.0f + 0.5f ) ); + } + + k = nbits1; + + for ( j = i + 1; j < no_idx16 + i; j++ ) + { + k -= 16; + hMetaData->ind_list[indice_coherence + j].value = ( ( idx1 >> k ) & 65535 ); /* 16 bits */ + } + hMetaData->ind_list[indice_coherence + j].value = ( idx1 & ( ( 1 << k ) - 1 ) ); + } + + return nbits + nbits1; +} + + +/*-------------------------------------------------------------------* + * coherence_coding_length() + * + * + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 coherence_coding_length( + const UWord16 *idx_sur_coh_shift, + const UWord8 idx_shift_len, + const Word16 coding_subbands, + const Word16 *no_cv, + UWord16 *mr_idx, + Word16 *no_cv_shift, + Word16 *p_min_idx, + Word16 *GR_ord, + Word16 *nbits_fr, + Word16 *nbits_fr1 ) +{ + Word16 half_coding_subbands; + Word16 j; + Word16 nbits; + UWord64 no_cb; + Word16 min_idx; + + half_coding_subbands = 0; + move16(); + + IF( GT_16( sum16_fx( no_cv, coding_subbands ), MASA_COH_LIMIT_2IDX ) ) + { + + no_cb = 1; + move16(); + half_coding_subbands = shr( coding_subbands, 1 ); + move16(); + FOR( j = 0; j < half_coding_subbands; j++ ) + { + no_cb = no_cb * no_cv[j]; + } + //*nbits_fr = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + IF( LE_64( no_cb, 1 ) ) + { + *nbits_fr = 0; + } + ELSE + { + *nbits_fr = sub( 63, W_norm( W_sub( no_cb, 1 ) ) ); + } + move16(); + no_cb = 1; + move16(); + FOR( j = half_coding_subbands; j < coding_subbands; j++ ) + { + no_cb = no_cb * no_cv[j]; + } + //*nbits_fr1 = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + IF( LE_64( no_cb, 1 ) ) + { + *nbits_fr1 = 0; + } + ELSE + { + *nbits_fr1 = sub( 63, W_norm( W_sub( no_cb, 1 ) ) ); + } + move16(); + } + ELSE + { + no_cb = 1; + FOR( j = 0; j < coding_subbands; j++ ) { - no_idx16 = nbits1 / 16; + no_cb = no_cb * no_cv[j]; } - else + //*nbits_fr = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + IF( LE_64( no_cb, 1 ) ) { - no_idx16 = (int16_t) round_f( ( nbits1 / 16.0f + 0.5f ) ); + *nbits_fr = 0; } - - k = nbits1; - - for ( j = i + 1; j < no_idx16 + i; j++ ) + ELSE { - k -= 16; - hMetaData->ind_list[indice_coherence + j].value = ( ( idx1 >> k ) & 65535 ); /* 16 bits */ + *nbits_fr = sub( 63, W_norm( W_sub( no_cb, 1 ) ) ); } - hMetaData->ind_list[indice_coherence + j].value = ( idx1 & ( ( 1 << k ) - 1 ) ); + move16(); + *nbits_fr1 = 0; + move16(); } - return nbits + nbits1; -} - -/*-------------------------------------------------------------------* - * coherence_coding_length() - * - * - *-------------------------------------------------------------------*/ + minimum_s( (const Word16 *) idx_sur_coh_shift, (int16_t) idx_shift_len, &min_idx ); + FOR( j = 0; j < idx_shift_len; j++ ) + { + mr_idx[j] = sub( idx_sur_coh_shift[j], min_idx ); + move16(); + no_cv_shift[j] = sub( no_cv_shift[j], min_idx ); + move16(); + } + nbits = add( add( min_idx, 1 ), GR_bits_new( mr_idx, no_cv_shift, idx_shift_len, *GR_ord, 1, GR_ord ) ); + *p_min_idx = min_idx; + move16(); + return nbits; +} +#else static int16_t coherence_coding_length( const uint16_t *idx_sur_coh_shift, const uint8_t idx_shift_len, @@ -5757,7 +6579,7 @@ static int16_t coherence_coding_length( return nbits; } - +#endif /*-------------------------------------------------------------------* * encode_spread_coherence_1sf() @@ -5955,204 +6777,220 @@ static int16_t encode_spread_coherence_1sf( /*! r: number of bits written */ #ifdef IVAS_FLOAT_FIXED -static int16_t encode_surround_coherence( +static Word16 encode_surround_coherence_fx( IVAS_QMETADATA *hQMetaData, /* i : quantized metadata */ BSTR_ENC_HANDLE hMetaData /* i/o: metadata bitstream handle */ ) { - int16_t i, j, k; - int16_t idx_ER, idx16; - int16_t nbits, nbits_fr; - uint16_t idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; - uint16_t mr_idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t GR_ord, bits_GR; - uint64_t idx, idx1; - int16_t no_idx16; - int16_t no_cv[MASA_MAXIMUM_CODING_SUBBANDS]; - float error_ratio_surr; -#ifdef IVAS_FLOAT_FIXED - Word32 error_ratio_surr_fx; -#endif + Word16 i, j, k; + Word16 idx_ER, idx16; + Word16 nbits, nbits_fr; + UWord16 idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 mr_idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 GR_ord, bits_GR; + UWord64 idx, idx1; + Word16 no_idx16; + Word16 no_cv[MASA_MAXIMUM_CODING_SUBBANDS]; + Word32 error_ratio_surr; // Q30 IVAS_QDIRECTION *q_direction; - int16_t half_coding_subbands, nbits_fr1, coding_subbands; - int16_t all_coherence_zero; - uint16_t idx_sur_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS]; - uint8_t idx_shift; - int16_t max_val = 0, nbits_max; - int16_t no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx; + Word16 half_coding_subbands, nbits_fr1, coding_subbands; + Word16 all_coherence_zero; + UWord16 idx_sur_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord8 idx_shift; + Word16 max_val = 0, nbits_max; + move16(); + Word16 no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx; coding_subbands = hQMetaData->q_direction[0].cfg.nbands; + move16(); all_coherence_zero = hQMetaData->all_coherence_zero; + move16(); q_direction = &( hQMetaData->q_direction[0] ); nbits = 0; + move16(); - if ( all_coherence_zero == 1 ) + IF( EQ_16( all_coherence_zero, 1 ) ) { nbits = 0; + move16(); } - else + ELSE { GR_ord = 1; + move16(); k = 0; + move16(); idx_shift = 0; - for ( j = 0; j < coding_subbands; j++ ) + move16(); + FOR( j = 0; j < coding_subbands; j++ ) { - if ( hQMetaData->no_directions == 2 ) + IF( EQ_16( hQMetaData->no_directions, 2 ) ) { - k += hQMetaData->twoDirBands[j]; - idx16 = max( k - 1, 0 ); - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0] - q_direction[1].band_data[idx16].energy_ratio[0] * hQMetaData->twoDirBands[j]; + k = add( k, hQMetaData->twoDirBands[j] ); + idx16 = s_max( sub( k, 1 ), 0 ); + error_ratio_surr = W_sat_l( W_sub( W_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ), W_mult0_32_32( q_direction[1].band_data[idx16].energy_ratio_fx[0], hQMetaData->twoDirBands[j] ) ) ); } - else + ELSE { - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[0]; + error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ); } - if ( error_ratio_surr <= 0 ) + IF( error_ratio_surr <= 0 ) { error_ratio_surr = 0; + move16(); idx_sur_coh[j] = 0; + move16(); no_cv[j] = 1; + move16(); hQMetaData->surcoh_band_data[j].surround_coherence[0] = 0; /* sur_coherence_cb_masa[idx_cb_sur_coh_masa[DIRAC_DIFFUSE_LEVELS - 1] * MASA_MAX_NO_CV_SUR_COH]; */ + move16(); } - else + ELSE { -#ifdef IVAS_FLOAT_FIXED - /*=====================================flt-2-fix============================================*/ - error_ratio_surr_fx = floatToFixed( error_ratio_surr, Q30 ); - /*=====================================flt-2-fix============================================*/ - - idx_ER = masa_sq_fx( error_ratio_surr_fx, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); -#else - idx_ER = masa_sq( error_ratio_surr, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); -#endif + idx_ER = masa_sq_fx( error_ratio_surr, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); - idx_sur_coh[j] = squant_int( hQMetaData->surcoh_band_data[j].surround_coherence[0], &hQMetaData->surcoh_band_data[j].surround_coherence[0], - &sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER] * MASA_MAX_NO_CV_SUR_COH], idx_cb_sur_coh_masa[idx_ER] + 2 ); + idx_sur_coh[j] = squant_int_fx( hQMetaData->surcoh_band_data[j].surround_coherence[0], &hQMetaData->surcoh_band_data[j].surround_coherence[0], + &sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER] * MASA_MAX_NO_CV_SUR_COH], add( idx_cb_sur_coh_masa[idx_ER], 2 ) ); + move16(); - no_cv[j] = idx_cb_sur_coh_masa[idx_ER] + 2; + no_cv[j] = add( idx_cb_sur_coh_masa[idx_ER], 2 ); + move16(); no_cv_shift[idx_shift] = no_cv[j]; + move16(); idx_sur_coh_shift[idx_shift++] = idx_sur_coh[j]; + move16(); } } - if ( sum_s( no_cv, coding_subbands ) == coding_subbands ) + IF( EQ_16( sum16_fx( no_cv, coding_subbands ), coding_subbands ) ) { return 0; } nbits_max = 0; - if ( coding_subbands > MASA_LIMIT_NO_BANDS_SUR_COH ) + move16(); + IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) ) { - j = maximum_s( (int16_t *) idx_sur_coh, coding_subbands, &max_val ); - for ( j = 0; j < coding_subbands; j++ ) + j = maximum_s( (Word16 *) idx_sur_coh, coding_subbands, &max_val ); + FOR( j = 0; j < coding_subbands; j++ ) { - if ( no_cv[j] > max_val + 1 ) + if ( GT_16( no_cv[j], add( max_val, 1 ) ) ) { - no_cv[j] = max_val + 1; + no_cv[j] = add( max_val, 1 ); + move16(); } } - nbits_max = MASA_MAX_NO_CV_SUR_COH - max_val; /* encoded with GR0 as max_no_vals - no_vals*/ + nbits_max = sub( MASA_MAX_NO_CV_SUR_COH, max_val ); /* encoded with GR0 as max_no_vals - no_vals*/ } nbits = coherence_coding_length( idx_sur_coh_shift, idx_shift, coding_subbands, no_cv, mr_idx_sur_coh, no_cv_shift, &min_idx, &GR_ord, &nbits_fr, &nbits_fr1 ); - half_coding_subbands = coding_subbands / 2; + half_coding_subbands = shr( coding_subbands, 1 ); idx1 = 0; + move16(); /* should check how to encode the average - check distribution */ - if ( nbits_fr + nbits_fr1 + nbits_max < nbits ) + IF( LT_16( add( add( nbits_fr, nbits_fr1 ), nbits_max ), nbits ) ) { /* write flag*/ push_next_indice( hMetaData, 0, 1 ); /* create combined index */ - nbits = nbits_fr + nbits_fr1 + 1; - if ( coding_subbands > MASA_LIMIT_NO_BANDS_SUR_COH ) + nbits = add( add( nbits_fr, nbits_fr1 ), 1 ); + IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) ) { /* write max value*/ bits_GR = hMetaData->nb_bits_tot; + move16(); ivas_qmetadata_encode_extended_gr( hMetaData, MASA_MAX_NO_CV_SUR_COH - max_val - 1, MASA_MAX_NO_CV_SUR_COH, 0 ); - nbits += hMetaData->nb_bits_tot - bits_GR; + nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) ); } - if ( nbits_fr1 > 0 ) + IF( nbits_fr1 > 0 ) { idx = create_combined_index( idx_sur_coh, half_coding_subbands, no_cv ); idx1 = create_combined_index( &idx_sur_coh[half_coding_subbands], half_coding_subbands, &no_cv[half_coding_subbands] ); } - else + ELSE { idx = create_combined_index( idx_sur_coh, coding_subbands, no_cv ); } - if ( nbits_fr % 16 == 0 ) + /*if ( nbits_fr % 16 == 0 ) { no_idx16 = nbits_fr / 16; } else { no_idx16 = (int16_t) round_f( ( nbits_fr / 16.0f + 0.5f ) ); - } + }*/ + no_idx16 = shr_r( nbits_fr, 4 ); /* write combined index */ k = nbits_fr; - for ( i = 0; i < no_idx16 - 1; i++ ) + move16(); + FOR( i = 0; i < no_idx16 - 1; i++ ) { - k -= 16; + k = sub( k, 16 ); push_next_indice( hMetaData, ( ( idx >> k ) & 65535 ), 16 ); /* 16 bits */ } push_next_indice( hMetaData, ( idx & ( ( 1 << k ) - 1 ) ), k ); - if ( nbits_fr1 > 0 ) + IF( nbits_fr1 > 0 ) { - if ( nbits_fr1 % 16 == 0 ) + /*if ( nbits_fr1 % 16 == 0 ) { no_idx16 = nbits_fr1 / 16; } else { no_idx16 = (int16_t) round_f( ( nbits_fr1 / 16.0f + 0.5f ) ); - } + }*/ + no_idx16 = shr_r( nbits_fr1, 4 ); assert( no_idx16 <= 4 ); k = nbits_fr1; - for ( i = 0; i < no_idx16 - 1; i++ ) + move16(); + FOR( i = 0; i < no_idx16 - 1; i++ ) { - k -= 16; + k = sub( k, 16 ); push_next_indice( hMetaData, ( ( idx1 >> k ) & 65535 ), 16 ); /* 16 bits */ } push_next_indice( hMetaData, ( idx1 & ( ( 1 << k ) - 1 ) ), k ); } } - else + ELSE { /* write flag */ nbits = 1; + move16(); /* write flag*/ push_next_indice( hMetaData, 1, 1 ); /* write GR_ord */ push_next_indice( hMetaData, GR_ord, 1 ); - nbits += 1; + nbits = add( nbits, 1 ); /* write the min */ bits_GR = hMetaData->nb_bits_tot; + move16(); ivas_qmetadata_encode_extended_gr( hMetaData, min_idx, MASA_MAX_NO_CV_SUR_COH, 0 ); - nbits += hMetaData->nb_bits_tot - bits_GR; + nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) ); /* write GR data */ - for ( j = 0; j < idx_shift; j++ ) + FOR( j = 0; j < idx_shift; j++ ) { bits_GR = hMetaData->nb_bits_tot; + move16(); ivas_qmetadata_encode_extended_gr( hMetaData, mr_idx_sur_coh[j], no_cv_shift[j], GR_ord ); - nbits += hMetaData->nb_bits_tot - bits_GR; + nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) ); } } } @@ -6682,7 +7520,132 @@ static void dct4_transform( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_quantize_coherence_hr_512_fx( + IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata */ + const Word16 idx_d, /* i : current direction index */ + const Word16 all_coherence_zero, /* i : all coherence is zero - flag */ + BSTR_ENC_HANDLE hMetaData, /* i : metadata handle */ + const Word16 bits_coh ) +{ + Word16 j, k; + Word16 nbands, nblocks; + Word16 nbits; + Word16 nbits1, nbits0, nbits_av; + UWord16 idx_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + IVAS_QDIRECTION *q_direction; + Word16 cbsize; + Word16 delta, tmp; + Word16 min_idx, GR_param, GR_param_av; + UWord16 av, mr_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + + q_direction = &( hQMetaData->q_direction[idx_d] ); + nbands = q_direction->cfg.nbands; + nblocks = q_direction->cfg.nblocks; + nbits = 0; + move16(); + move16(); + move16(); + + IF( EQ_16( all_coherence_zero, 1 ) ) + { + return nbits; + } + nbits = hMetaData->nb_bits_tot; + move16(); + + cbsize = shl( 1, bits_coh ); + // delta = 256.0f / cbsize; + delta = div_l( 256, shr( cbsize, 1 ) ); + + FOR( k = 0; k < nblocks; k++ ) + { + min_idx = 0; + move16(); + FOR( j = 0; j < nbands; j++ ) + { + idx_coh[j] = usquant_fx( (Word16) ( q_direction->coherence_band_data[j].spread_coherence[k] ), &tmp, shr( delta, 1 ), shr( delta, 1 ) /* Q-1 */, cbsize ); + move16(); + q_direction->coherence_band_data[j].spread_coherence[k] = (UWord8) add( imult1616( idx_coh[j], delta ), shr( delta, 1 ) ); + if ( LT_16( idx_coh[j], min_idx ) ) + { + min_idx = idx_coh[j]; + move16(); + } + } + + nbits0 = 0; + nbits1 = 0; + move16(); + move16(); + + FOR( j = 0; j < nbands; j++ ) + { + idx_coh[j] = sub( idx_coh[j], min_idx ); + move16(); + nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length( idx_coh[j], sub( cbsize, min_idx ), 0 ) ); + nbits1 = add( nbits1, ivas_qmetadata_encode_extended_gr_length( idx_coh[j], sub( cbsize, min_idx ), 1 ) ); + } + IF( nbits0 < nbits1 ) + { + GR_param = 0; + nbits1 = nbits0; + move16(); + move16(); + } + ELSE + { + GR_param = 1; + move16(); + } + + GR_param_av = 1; + move16(); + nbits_av = mean_removed_GR_new( idx_coh, cbsize, nbands, 1, &GR_param_av, &av, mr_idx ); + + IF( LT_16( nbits_av, nbits1 ) ) + { + nbits1 = nbits_av; + GR_param = GR_param_av; + move16(); + move16(); + + /* use average removed */ + push_next_indice( hMetaData, 1, 1 ); + + /* write average */ + push_next_indice( hMetaData, av, bits_coh ); + + /* write GR param */ + push_next_indice( hMetaData, GR_param, 1 ); + + FOR( j = 0; j < nbands; j++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, mr_idx[j], imult1616( 2, cbsize ), GR_param ); + } + } + ELSE + { + /* use min removed */ + push_next_indice( hMetaData, 0, 1 ); + + /* write min index */ + push_next_indice( hMetaData, min_idx, bits_coh ); + + /* write GR param */ + push_next_indice( hMetaData, GR_param, 1 ); + + FOR( j = 0; j < nbands; j++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, idx_coh[j], sub( cbsize, min_idx ), GR_param ); + } + } + } + nbits = sub( hMetaData->nb_bits_tot, nbits ); + return nbits; +} +#else static int16_t ivas_qmetadata_quantize_coherence_hr_512( IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata */ const int16_t idx_d, /* i : current direction index */ @@ -6789,7 +7752,7 @@ static int16_t ivas_qmetadata_quantize_coherence_hr_512( nbits = hMetaData->nb_bits_tot - nbits; return nbits; } - +#endif /*-------------------------------------------------------------------* * ivas_qmetadata_quantize_coherence() @@ -7208,7 +8171,88 @@ static int16_t ivas_qmetadata_quantize_coherence( * Reorders metadata on 2dir bands such that direct-to-total ratio of first direction is * always larger or equal to direct-to-total ratio of second direction. *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_qmetadata_reorder_2dir_bands_fx( + IVAS_QMETADATA_HANDLE hQMetaData ) +{ + Word16 nbands; + Word16 nsubframes; + Word16 band, sf; + + nbands = hQMetaData->q_direction[0].cfg.nbands; + move16(); + nsubframes = hQMetaData->q_direction[0].cfg.nblocks; + move16(); + + FOR( band = 0; band < nbands; band++ ) + { + IF( EQ_16( hQMetaData->twoDirBands[band], 1 ) ) + { + IF( LT_32( hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0], hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0] ) ) + { + UWord16 uint16_tmp = 0; + move16(); + Word32 fx_tmp = 0; + move32(); + UWord8 uint8_tmp = 0; + move16(); + + FOR( sf = 0; sf < nsubframes; sf++ ) + { + uint16_tmp = hQMetaData->q_direction[0].band_data[band].spherical_index[sf]; + move16(); + hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[1].band_data[band].spherical_index[sf]; + move16(); + hQMetaData->q_direction[1].band_data[band].spherical_index[sf] = uint16_tmp; + move16(); + + fx_tmp = hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf]; + move32(); + hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf]; + move32(); + hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf] = fx_tmp; + move32(); + + fx_tmp = hQMetaData->q_direction[0].band_data[band].elevation_fx[sf]; + move32(); + hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[1].band_data[band].elevation_fx[sf]; + move32(); + hQMetaData->q_direction[1].band_data[band].elevation_fx[sf] = fx_tmp; + move32(); + + uint8_tmp = hQMetaData->q_direction[0].band_data[band].distance[sf]; + move16(); + hQMetaData->q_direction[0].band_data[band].distance[sf] = hQMetaData->q_direction[1].band_data[band].distance[sf]; + move16(); + hQMetaData->q_direction[1].band_data[band].distance[sf] = uint8_tmp; + move16(); + + IF( hQMetaData->coherence_flag ) + { + uint8_tmp = hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf]; + move16(); + hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf]; + move16(); + hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = uint8_tmp; + move16(); + } + } + IF( hQMetaData->coherence_flag ) + { + fx_tmp = hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0]; + move32(); + hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0] = hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0]; + move32(); + hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0] = fx_tmp; + move32(); + } + } + } + } + return; +} +#else static void ivas_qmetadata_reorder_2dir_bands( IVAS_QMETADATA_HANDLE hQMetaData ) { @@ -7266,14 +8310,58 @@ static void ivas_qmetadata_reorder_2dir_bands( return; } - +#endif /*-------------------------------------------------------------------* * write_2dir_info() * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 write_2dir_info( + BSTR_ENC_HANDLE hMetaData, + UWord8 *twoDirBands, + const Word16 n, + const Word16 k ) +{ + Word16 nbits; + Word16 p[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 dif_p[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 i, j; + + j = 0; + p[0] = 0; + move16(); + move16(); + FOR( i = 0; i < n; i++ ) + { + IF( EQ_16( twoDirBands[i], 1 ) ) + { + p[j] = i; + j = add( j, 1 ); + move16(); + } + } + + dif_p[0] = p[0]; + move16(); + FOR( i = 1; i < j; i++ ) + { + dif_p[i] = sub( sub( p[i], p[i - 1] ), 1 ); + move16(); + } + + j = hMetaData->nb_bits_tot; + move16(); + FOR( i = 0; i < k; i++ ) + { + ivas_qmetadata_encode_extended_gr( hMetaData, dif_p[i], 24, 0 ); + } + nbits = sub( hMetaData->nb_bits_tot, j ); + return nbits; +} +#else static int16_t write_2dir_info( BSTR_ENC_HANDLE hMetaData, uint8_t *twoDirBands, @@ -7311,14 +8399,56 @@ static int16_t write_2dir_info( return nbits; } - +#endif /*-------------------------------------------------------------------* * transform_azimuth_dir2() * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void transform_azimuth_dir2_fx( + IVAS_QMETADATA_HANDLE hQMetaData, + Word16 *dir2_bands ) +{ + Word16 i, b; + + FOR( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ ) + { + IF( LT_16( hQMetaData->q_direction[0].band_data[dir2_bands[i]].energy_ratio_index[0], 7 ) ) + { + /* transform azimuth */ + FOR( b = 0; b < hQMetaData->q_direction[1].cfg.nblocks; b++ ) + { + Word64 azimuth; + azimuth = W_add( W_deposit32_l( L_sub( hQMetaData->q_direction[1].band_data[i].azimuth_fx[b], hQMetaData->q_direction[0].band_data[dir2_bands[i]].azimuth_fx[b] ) ), 180 << Q22 ); + + if ( GE_64( azimuth, 180 << Q22 ) ) + { + azimuth = W_sub( azimuth, 360 << Q22 ); + } + if ( LT_64( azimuth, -( 180 << Q22 ) ) ) + { + azimuth = W_add( azimuth, 360 << Q22 ); + } + if ( GE_64( azimuth, 180 << Q22 ) ) + { + azimuth = W_sub( azimuth, 360 << Q22 ); + } + if ( LT_64( azimuth, -( 180 << Q22 ) ) ) + { + azimuth = W_add( azimuth, 360 << Q22 ); + } + + hQMetaData->q_direction[1].band_data[i].azimuth_fx[b] = W_extract_l( azimuth ); + move32(); + } + } + } + return; +} +#else static void transform_azimuth_dir2( IVAS_QMETADATA_HANDLE hQMetaData, int16_t *dir2_bands ) @@ -7355,7 +8485,7 @@ static void transform_azimuth_dir2( return; } - +#endif static int16_t divide_GR_orders( const int16_t *q_idx, diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index b318fd6951d8906afb9f09babfbf3906c82ec303..2f18205b0bf7e589f490786729f702750ef83772 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -43,9 +43,33 @@ /*----------------------------------------------------------------------------------* * Stereo classifiers ROM tables *----------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/* UNCLR classifier in TD stereo: list of selected features */ +const Word16 unclr_isel_td[SIZE_UNCLR_ISEL_TD] = +{ + E_corrLagStats0, E_ica_instTargetGain, E_sum_prod, E_tdm_es_em, E_m_corrL_corrR, E_d_corrL_corrR, E_corrEst0, E_corrLagMax, E_corrEstMax, E_corrEst_ncorr +}; + +/* UNCLR classifier in TD stereo:: mean & scale for feature normalization */ +const Word32 unclr_mean_td[SIZE_UNCLR_ISEL_TD] = /*Q15*/ +{ + 166277, 163748, 209465, 50557, 34744, 239251, 21, 1277892, 44, 19270 +}; + +const Word32 unclr_scale_td[SIZE_UNCLR_ISEL_TD] = /*Q15*/ +{ + 1385482, 31474, 60505, 77687, 24209, 42641, 39, 676271, 304, 11428 +}; + +/* UNCLR classifier in TD stereo: classifier parameters for logistic regression */ +const Word32 unclr_coef_td[SIZE_UNCLR_ISEL_TD] = /*Q15*/ +{ + -5875, -80055, -115720, 47164, 22570, 95476, 1290, -1332, -148091, -14371 +}; +#else /* UNCLR classifier in TD stereo: list of selected features */ -const int16_t unclr_isel_td[SIZE_UNCLR_ISEL_TD] = +const Word16 unclr_isel_td[SIZE_UNCLR_ISEL_TD] = { E_corrLagStats0, E_ica_instTargetGain, E_sum_prod, E_tdm_es_em, E_m_corrL_corrR, E_d_corrL_corrR, E_corrEst0, E_corrLagMax, E_corrEstMax, E_corrEst_ncorr }; @@ -66,6 +90,7 @@ const float unclr_coef_td[SIZE_UNCLR_ISEL_TD] = { -0.179304f, -2.443089f, -3.531498f, 1.439316f, 0.688796f, 2.913693f, 0.039382f, -0.040637f, -4.519369f, -0.438573f }; +#endif /* UNCLR classifier in DFT stereo: list of selected features */ const int16_t unclr_isel_dft[SIZE_UNCLR_ISEL_DFT] = @@ -116,7 +141,22 @@ const int16_t xtalk_isel_td[SIZE_XTALK_ISEL_TD] = { E_d_clas, E_d_voicing, E_sum_d_LSF, E_d_lepsP_13, E_d_cor_map_sum, E_d_nchar, E_d_non_sta, E_d_sp_div, E_sum_prod, E_tdm_es_em, E_m_corrL_corrR, E_corrEst0, E_corrEst_ncorr, E_corrLagStats0, E_ica_corr_value0, E_diff_corrLM_corrRM, E_tdm_LT_es_em }; +#ifdef IVAS_FLOAT_FIXED +const Word32 xtalk_mean_td[SIZE_XTALK_ISEL_TD] = /*Q15*/ +{ + 19572, 4323, 44674958, 20928, 248554, 5077, 123099, 19205, 217973, 57391, 22648, 21, 23142, 342411, 59, 612, -71224 +}; + +const Word32 xtalk_scale_td[SIZE_XTALK_ISEL_TD] = /*Q15*/ +{ + 37220, 2553, 16147962, 18786, 191263, 13110, 139310, 20547, 45408, 60617, 17627, 43, 9123, 2070239, 88, 21549, 68968 +}; +const Word32 xtalk_coef_td[SIZE_XTALK_ISEL_TD] = /*Q15*/ +{ + 1841, 4353, 3322, -5411, 1061, 2716, -2453, 1046, 45199, -51474, -2431, -2245, 2194, -542, -135853, 99, 18138 +}; +#else const float xtalk_mean_td[SIZE_XTALK_ISEL_TD] = { 0.597295f, 0.131934f, 1363.371521f, 0.638677f, 7.585252f, 0.154930f, 3.756674f, 0.586091f, @@ -137,7 +177,7 @@ const float xtalk_coef_td[SIZE_XTALK_ISEL_TD] = 1.379376f, -1.570864f, -0.074181f, -0.068519f, 0.066952f, -0.016555f, -4.145916f, 0.003024f, 0.553536f }; - +#endif const int16_t xtalk_isel_dft[SIZE_XTALK_ISEL_DFT] = { E_clas, E_gainILD, E_gainIPD, E_angle_rot, E_g_pred, E_d_prodL_prodR, E_sum_xcorr, E_xcorr_itd_value, E_gphat_d_itd2, E_gphat_ratio_m1_m2, E_gphat_m2_m2 @@ -185,6 +225,24 @@ const float icbwe_thr_DFT[7] = { -1.19952f, -1.42293f, -1.074940f, -1.63089f, 0. const float icbwe_regressionValuesTDM[8] = { 0.104430f, 0.025943f, 0.50332f, 0.12767f, 0.80566f, 0.27640f, 0.98366f, 0.35556f }; const float icbwe_regressionValuesDFT[8] = { 0.030371f, 0.155500f, 0.52510f, 0.10623f, 0.79167f, 0.23188f, 0.98325f, 0.00000f }; +#ifdef IVAS_FLOAT_FIXED +#define FLOAT_2_FIX_Q30(a) ((Word32)(a * 1024.0 * 1024.0 * 1024.0)) +#define FLOAT_2_FIX_Q31(a) ((Word32)(a * 1024.0 * 1024.0 * 1024.0 * 2.0)) +/* Q30Value >> Q5 */ +const Word32 icbwe_thr_TDM_fx[7] = {-1318855552 >> 5, -1667671424 >> 5, -1072553216 >> 5, + 920192448 >> 5, 897910144 >> 5, 936654016 >> 5, + 1043856384 >> 5}; +/* Q30Value >> Q5*/ +const Word32 icbwe_thr_DFT_fx[7] = {-1287974784 >> 5, -1527859456 >> 5, -1154208000 >> 5, + -1751154816 >> 5, 955618432 >> 5, 959420544 >> 5, + 1047207488 >> 5}; +/* Q31 */ +const Word32 icbwe_regressionValuesTDM_fx[8] = {224261712, 55712168, 1080871424, 274169248, + 1730141696, 593564480, 2112393728, 763559296}; +/* Q31 */ +const Word32 icbwe_regressionValuesDFT_fx[8] = {65221224, 333933696, 1127643648, 228127184, + 1700098432, 497958496, 2111513344, 0}; +#endif /*----------------------------------------------------------------------------------* * DFT stereo ROM tables @@ -715,12 +773,22 @@ const float log2TB[ECSQ_log2TB_SIZE] = 0.858721f, 0.232908f, 0.059619f, 0.014997f, 0.003755f, 0.000939f, 0.000235f, 0.000059f, 0.000015f, 0.000004f, 0.000001f, 0.000000f, 0.000000f }; +const Word32 log2TB_Q31[ECSQ_log2TB_SIZE] = +{ + 1844089344, 500166112, 128030824, 32205812, 8063801, 2016487, 504658, 126701, 32212, 8589, 2147, 0, 0 +}; + /* precomuputed table for log_2(factorial(i)), for i in {0, .., ECSQ_SEGMENT_SIZE} */ const float ECSQ_log2_fact[1 + ECSQ_SEGMENT_SIZE] = { 0.0000000f, 0.0000000f, 1.0000000f, 2.5849625f, 4.5849625f, 6.9068906f, 9.4918531f, 12.2992080f, 15.2992080f }; +const Word16 ECSQ_log2_fact_Q10[1 + ECSQ_SEGMENT_SIZE] = +{ + 0, 0, 1024, 2647, 4695, 7072, 9719, 12594, 15666 +}; + const uint16_t ECSQ_tab_param[ECSQ_CONFIG_COUNT][1 + ECSQ_PARAM_COUNT] = { { 16384, 15360, 14336, 13312, 12288, 11264, 10240, 9216, 8192, 7168, 6144, 5120, 4096, 3072, 2048, 1024, 0 }, /* un-optimized (reserved) */ diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index 6b6fa1c78e67af73cba946d7ca127d345407b82a..e3164aa116a6c3562c27ed59e56caed4ce2d74ff 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -43,15 +43,28 @@ * Stereo classifiers *----------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +extern const Word16 unclr_isel_td[]; +extern const Word32 unclr_mean_td[]; +extern const Word32 unclr_scale_td[]; +extern const Word32 unclr_coef_td[]; +#else extern const int16_t unclr_isel_td[]; extern const float unclr_mean_td[]; extern const float unclr_scale_td[]; extern const float unclr_coef_td[]; +#endif extern const int16_t xtalk_isel_td[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 xtalk_mean_td[]; +extern const Word32 xtalk_scale_td[]; +extern const Word32 xtalk_coef_td[]; +#else extern const float xtalk_mean_td[]; extern const float xtalk_scale_td[]; extern const float xtalk_coef_td[]; +#endif extern const int16_t xtalk_isel_dft[]; extern const float xtalk_mean_dft[]; @@ -81,6 +94,13 @@ extern const float icbwe_thr_DFT[]; extern const float icbwe_regressionValuesTDM[]; extern const float icbwe_regressionValuesDFT[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 icbwe_thr_TDM_fx[]; +extern const Word32 icbwe_thr_DFT_fx[]; +extern const Word32 icbwe_regressionValuesTDM_fx[]; +extern const Word32 icbwe_regressionValuesDFT_fx[]; +#endif + /*----------------------------------------------------------------------------------* * DFT stereo ROM tables *----------------------------------------------------------------------------------*/ @@ -137,7 +157,9 @@ extern const Word32 ari_bit_estimate_s17_LC_fx[RANGE_N_CONTEXT][RANGE_N_SYMBOLS] extern const int16_t log2_1px_table[65]; extern const float log2TB[ECSQ_log2TB_SIZE]; +extern const Word32 log2TB_Q31[ECSQ_log2TB_SIZE]; extern const float ECSQ_log2_fact[1 + ECSQ_SEGMENT_SIZE]; +extern const Word16 ECSQ_log2_fact_Q10[1 + ECSQ_SEGMENT_SIZE]; extern const uint16_t ECSQ_tab_param[ECSQ_CONFIG_COUNT][1 + ECSQ_PARAM_COUNT]; extern const uint16_t *const ECSQ_tab_abs_lsbs[1 + 4]; extern const uint16_t ECSQ_tab_vals[ECSQ_PARAM_COUNT - 1][1 + ECSQ_TAB_VALS_SIZE]; diff --git a/lib_enc/ivas_sba_enc.c b/lib_enc/ivas_sba_enc.c index 21953637ef9b204fdf08e3e5e6f608c5c8f68213..549b7ccdca1119b7af8282c7ae00822fd17177dc 100644 --- a/lib_enc/ivas_sba_enc.c +++ b/lib_enc/ivas_sba_enc.c @@ -321,7 +321,7 @@ ivas_error ivas_sba_enc_reconfigure( * Allocate, initialize, and configure SCE/CPE/MCT handles *-----------------------------------------------------------------*/ - if ( ( error = ivas_corecoder_enc_reconfig( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, ivas_total_brate / st_ivas->nchan_transport, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS, MC_MODE_NONE ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_corecoder_enc_reconfig_fx( st_ivas, nSCE_old, nCPE_old, nchan_transport_old, ivas_total_brate / st_ivas->nchan_transport, ( ivas_total_brate / st_ivas->nchan_transport ) * CPE_CHANNELS, MC_MODE_NONE ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index ef5328d2b9641565559e752c8cf1720dbf1e2b43..8ed19413efdbc8cd7f9b053fd46ba121961fe4ed 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -47,6 +47,7 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "prot_fx_enc.h" #endif @@ -68,14 +69,20 @@ ivas_error ivas_sce_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion float old_inp_12k8[1][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ float old_inp_16k[1][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ + Word16 old_inp_12k8_fx[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ +#else + float old_inp_12k8[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + float old_inp_16k[1][L_INP]; /* buffer of input signal @ 16kHz */ +#endif + float ener[1]; /* residual energy from Levinson-Durbin */ + float relE[1]; /* frame relative energy */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion + float A[1][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* A(z) unquantized for subframes */ + float Aw[1][NB_SUBFR16k * ( M + 1 )] = { 0 }; /* weighted A(z) unquantized for subframes */ #else - float old_inp_12k8[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ - float old_inp_16k[1][L_INP]; /* buffer of input signal @ 16kHz */ + float A[1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ + float Aw[1][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ #endif - float ener[1]; /* residual energy from Levinson-Durbin */ - float relE[1]; /* frame relative energy */ - float A[1][NB_SUBFR16k * ( M + 1 )]; /* A(z) unquantized for subframes */ - float Aw[1][NB_SUBFR16k * ( M + 1 )]; /* weighted A(z) unquantized for subframes */ float epsP[1][M + 1]; /* LP prediction errors */ float lsp_new[1][M]; /* LSPs at the end of the frame */ float lsp_mid[1][M]; /* ISPs in the middle of the frame */ @@ -92,6 +99,7 @@ ivas_error ivas_sce_enc( float enerBuffer[1][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ float currFlatness[1]; /* flatness parameter */ float fft_buff[1][2 * L_FFT]; /* FFT buffer */ + Word16 fft_buff_fx[1][2 * L_FFT]; /* FFT buffer */ float fr_bands[1][2 * NB_BANDS]; /* energy in frequency bands */ float Etot_LR[1]; /* total energy */ float lf_E[1][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ @@ -136,7 +144,61 @@ ivas_error ivas_sce_enc( if ( ivas_format != MC_FORMAT || st_ivas->mc_mode != MC_MODE_PARAMMC ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTranDet->subblockEnergies.firState1 = (Word16) floatToFixed( st->hTranDet->subblockEnergies.firState1_flt, -1 ); + st->hTranDet->subblockEnergies.firState2 = (Word16) floatToFixed( st->hTranDet->subblockEnergies.firState2_flt, -1 ); + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st->hTranDet->subblockEnergies.accSubblockNrg[i] = floatToFixed( st->hTranDet->subblockEnergies.accSubblockNrg_flt[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st->hTranDet->subblockEnergies.subblockNrg[i] = floatToFixed( st->hTranDet->subblockEnergies.subblockNrg_flt[i], 7 ); + st->hTranDet->subblockEnergies.subblockNrgChange[i] = (Word16) floatToFixed( st->hTranDet->subblockEnergies.subblockNrgChange_flt[i], 7 ); + } + + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st->hTranDet->delayBuffer.buffer[i] = (Word16) floatToFixed( st->hTranDet->delayBuffer.buffer_flt[i], -1 ); + } + + st->hTranDet->transientDetector.attackRatioThreshold = (Word16) floatToFixed( st->hTranDet->transientDetector.attackRatioThreshold_flt, 11 ); + + floatToFixed_arr16( st->input, st->input_fx, -1, input_frame ); + + st->hTranDet->subblockEnergies.facAccSubblockNrg = float_to_fix16( st->hTranDet->subblockEnergies.facAccSubblockNrg_flt, 15 ); + +#endif + + RunTransientDetection_ivas_fx( st->input_fx, input_frame, st->hTranDet ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st->hTranDet->subblockEnergies.firState1_flt = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.firState1, -1 ); + st->hTranDet->subblockEnergies.firState2_flt = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.firState2, -1 ); + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY; i++ ) + { + st->hTranDet->subblockEnergies.subblockNrg_flt[i] = fixedToFloat( st->hTranDet->subblockEnergies.subblockNrg[i], 7 ); + st->hTranDet->subblockEnergies.subblockNrgChange_flt[i] = fixedToFloat( (Word32) st->hTranDet->subblockEnergies.subblockNrgChange[i], 7 ); + } + + FOR( Word16 i = 0; i < NSUBBLOCKS + MAX_TD_DELAY + 1; i++ ) + { + st->hTranDet->subblockEnergies.accSubblockNrg_flt[i] = fixedToFloat( st->hTranDet->subblockEnergies.accSubblockNrg[i], 7 ); + } + + FOR( Word16 i = 0; i < L_FRAME_MAX / NSUBBLOCKS; i++ ) + { + st->hTranDet->delayBuffer.buffer_flt[i] = fixedToFloat( (Word32) st->hTranDet->delayBuffer.buffer[i], -1 ); + } +#endif +#else RunTransientDetection( st->input, input_frame, st->hTranDet ); +#endif } currFlatness[0] = GetTCXAvgTemporalFlatnessMeasure( st->hTranDet, NSUBBLOCKS, 0 ); @@ -189,10 +251,10 @@ ivas_error ivas_sce_enc( * Front Pre-processing *----------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED - error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8[0], old_inp_16k[0], + error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8_fx[0], old_inp_12k8[0], old_inp_16k[0], &ener[0], &relE[0], A[0], Aw[0], epsP[0], lsp_new[0], lsp_mid[0], &vad_hover_flag[0], &attack_flag[0], realBuffer[0], imagBuffer[0], old_wsp[0], pitch_fr[0], voicing_fr[0], &loc_harm[0], &cor_map_sum[0], &vad_flag_dtx[0], enerBuffer[0], - fft_buff[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, flag_16k_smc, + fft_buff[0], fft_buff_fx[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, flag_16k_smc, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->force_front_vad : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_dtx_flag : 0, ivas_format, 0, st_ivas->hEncoderConfig->ivas_total_brate ); #else error = pre_proc_front_ivas( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8[0], old_inp_16k[0], @@ -247,27 +309,43 @@ ivas_error ivas_sce_enc( { ivas_write_format_sid( ivas_format, IVAS_SCE, st->hBstr ); } + + /*----------------------------------------------------------------* + * Core codec configuration + *----------------------------------------------------------------*/ + + /* IGF reconfiguration */ + if ( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) + { + int16_t igf; + igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->rf_mode ); + if ( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->element_mode, st->rf_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } #else IF( EQ_32( st->core_brate, SID_2k40 ) ) { ivas_write_format_sid_fx( ivas_format, IVAS_SCE, st->hBstr ); } -#endif /*----------------------------------------------------------------* * Core codec configuration *----------------------------------------------------------------*/ /* IGF reconfiguration */ - if ( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) + test(); + IF( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) { - int16_t igf; - igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->rf_mode ); - if ( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->element_mode, st->rf_mode ) ) != IVAS_ERR_OK ) + Word16 igf; + igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->rf_mode ); + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) { return error; } } +#endif /* set ACELP@12k8 / ACELP@16k flag for flexible ACELP core */ if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) diff --git a/lib_enc/ivas_sns_enc.c b/lib_enc/ivas_sns_enc.c index 1373e8a6238339c24c7b06f06faa6f1068f7a031..5419544c20573f898df401f6091a84890110fce8 100644 --- a/lib_enc/ivas_sns_enc.c +++ b/lib_enc/ivas_sns_enc.c @@ -41,6 +41,7 @@ #include "prot_fx.h" #include "rom_com.h" #include "ivas_rom_com.h" +#include "ivas_rom_com_fx.h" #include "ivas_cnst.h" #include "wmc_auto.h" #include "prot_fx_enc.h" @@ -805,7 +806,254 @@ void sns_avq_cod_stereo( return; } #endif +#ifdef IVAS_FLOAT_FIXED +Word16 quantize_sns_fx( + Word32 sns_in_fx[CPE_CHANNELS][NB_DIV][M], /* sns_e */ + Word32 snsQ_out_fx[CPE_CHANNELS][NB_DIV][M], /* sns_e */ + Word16 *sns_e, + Encoder_State **sts, + Word16 *indices, /* Q0 */ + Word16 *zero_side_flag, /* Q0 */ + Word16 *sns_stereo_mode ) /* Q0 */ +{ + Word16 nSubframes, k, ch, i; + Word16 nbits, idxIndices; + Encoder_State *st; + + Word16 weights_fx[M]; + Word16 sns_e_tmp[CPE_CHANNELS][NB_DIV]; + + nbits = 0; + move16(); + idxIndices = 0; + move16(); + set16_fx( weights_fx, ONE_IN_Q8, M ); + + sns_stereo_mode[0] = SNS_STEREO_MODE_LR; + move16(); + sns_stereo_mode[1] = SNS_STEREO_MODE_LR; + move16(); + zero_side_flag[0] = 0; + move16(); + zero_side_flag[1] = 0; + move16(); + + /* use snsQ_out as buffer, move input vectors */ + FOR( ch = 0; ch < CPE_CHANNELS; ++ch ) + { + IF( EQ_16( sts[ch]->core, TCX_20_CORE ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; ++k ) + { + Copy32( sns_in_fx[ch][k], snsQ_out_fx[ch][k], M ); // sns_e + } + + sns_e_tmp[ch][0] = *sns_e; + move16(); + sns_e_tmp[ch][1] = *sns_e; + move16(); + } + + /* stereo mode decision */ + IF( EQ_16( sts[0]->core, sts[1]->core ) ) + { + IF( EQ_16( sts[0]->core, TCX_20_CORE ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; ++k ) + { + Word32 side_fx[M]; + Word32 ener_side_fx; + Word16 ener_side_q; + + v_sub_fixed( snsQ_out_fx[0][k], snsQ_out_fx[1][k], side_fx, M, 0 ); + + Word64 L64_sum; + L64_sum = 1; + move64(); + FOR( i = 0; i < M; i++ ) + { + L64_sum = W_mac_32_32( L64_sum, side_fx[i], side_fx[i] ); + } + i = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, i ); + ener_side_fx = W_extract_h( L64_sum ); // ener_side_q + ener_side_q = sub( add( shl( sub( 31, *sns_e ), 1 ), add( 1, i ) ), 32 ); + + sns_stereo_mode[k] = 0; + move16(); + zero_side_flag[k] = 0; + move16(); + + IF( LT_32( L_shl( ener_side_fx, sub( s_min( Q27, ener_side_q ), ener_side_q ) ), L_shl( 1610612736 /* 12.0 if Q27*/, sub( s_min( Q27, ener_side_q ), Q27 ) ) ) ) + { + sns_stereo_mode[k] = 1; + move16(); + } + + IF( LT_32( L_shl( ener_side_fx, sub( s_min( Q30, ener_side_q ), ener_side_q ) ), L_shl( 1, s_min( Q30, ener_side_q ) ) ) ) + { + zero_side_flag[k] = 1; + move16(); + } + + + IF( EQ_16( sns_stereo_mode[k], SNS_STEREO_MODE_MS ) ) + { + convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], ONE_IN_Q30 ); + } + } + } + + /* run MSVQ */ + FOR( ch = 0; ch < CPE_CHANNELS; ++ch ) + { + st = sts[ch]; + IF( EQ_16( st->core, TCX_20_CORE ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; ++k ) + { + Word16 is_side = 0; + move16(); + IF( EQ_16( ch, 1 ) && EQ_16( sns_stereo_mode[k], SNS_STEREO_MODE_MS ) ) + { + is_side = 1; + move16(); + } + + const Word16 *const *cdbks_fx; + const Word16 *levels; + const Word16 *bits; + Word16 nStages; + IF( EQ_16( nSubframes, 1 ) ) + { + cdbks_fx = ivas_sns_cdbks_tcx20_fx; + levels = ivas_sns_cdbks_tcx20_levels; + bits = ivas_sns_cdbks_tcx20_bits; + nStages = SNS_MSVQ_NSTAGES_TCX20; + } + ELSE + { + cdbks_fx = ivas_sns_cdbks_tcx10_fx; + levels = ivas_sns_cdbks_tcx10_levels; + bits = ivas_sns_cdbks_tcx10_bits; + nStages = SNS_MSVQ_NSTAGES_TCX10; + } + move16(); + + Word32 *snsQ_fx = snsQ_out_fx[ch][k]; + const Word32 *sns_ptr_fx = snsQ_out_fx[ch][k]; + + IF( is_side ) + { + const Word16 *const *side_cdbks_fx; + const Word16 *side_levels; + + IF( EQ_16( st->core, TCX_20_CORE ) ) + { + side_cdbks_fx = ivas_sns_cdbks_side_tcx20_fx; + side_levels = ivas_sns_cdbks_side_tcx20_levels; + bits = ivas_sns_cdbks_side_tcx20_bits; + } + ELSE + { + side_cdbks_fx = ivas_sns_cdbks_side_tcx10_fx; + side_levels = ivas_sns_cdbks_side_tcx10_levels; + bits = ivas_sns_cdbks_side_tcx10_bits; + } + + + IF( zero_side_flag[k] ) + { + set32_fx( snsQ_fx, 0, M ); + continue; + } + + nStages = SNS_MSVQ_NSTAGES_SIDE; + move16(); + + msvq_enc_ivas_fx( side_cdbks_fx, Q15, NULL, NULL, snsQ_fx, *sns_e, side_levels, 3, nStages, weights_fx, M, M, 0, NULL, &indices[idxIndices] ); + msvq_dec_fx( side_cdbks_fx, NULL, NULL, nStages, M, M, &indices[idxIndices], 0, NULL, snsQ_fx, NULL, Q15 ); + } + ELSE + { + msvq_enc_ivas_fx( cdbks_fx, Q12, NULL, NULL, sns_ptr_fx, *sns_e, levels, 3, nStages, weights_fx, M, M, 0, NULL, &indices[idxIndices] ); + msvq_dec_fx( cdbks_fx, NULL, NULL, nStages, M, M, &indices[idxIndices], 0, NULL, snsQ_fx, NULL, Q12 ); + } + Word16 shift = find_guarded_bits_fx( M ); + sns_e_tmp[ch][k] = sub( 31, sub( 20, shift ) ); + idxIndices = add( idxIndices, nStages ); + + FOR( i = 0; i < nStages; ++i ) + { + nbits = add( nbits, bits[i] ); + } + } + } + /* Re-Scaling Buffers*/ + *sns_e = sns_e_tmp[0][0]; + move16(); + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + *sns_e = s_max( *sns_e, sns_e_tmp[ch][0] ); + *sns_e = s_max( *sns_e, sns_e_tmp[ch][1] ); + } + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + scale_sig32( snsQ_out_fx[ch][0], M, sub( sns_e_tmp[ch][0], *sns_e ) ); + scale_sig32( snsQ_out_fx[ch][1], M, sub( sns_e_tmp[ch][1], *sns_e ) ); + } + /* get back to L/F representation */ + test(); + IF( EQ_16( sns_stereo_mode[0], SNS_STEREO_MODE_MS ) || EQ_16( sns_stereo_mode[1], SNS_STEREO_MODE_MS ) ) + { + IF( EQ_16( sts[0]->core, TCX_20_CORE ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + + FOR( k = 0; k < nSubframes; ++k ) + { + IF( EQ_16( sns_stereo_mode[k], SNS_STEREO_MODE_MS ) ) + { + convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], ONE_IN_Q31 ); + } + } + } + + return nbits; +} + +#else int16_t quantize_sns( float sns_in[CPE_CHANNELS][NB_DIV][M], float snsQ_out[CPE_CHANNELS][NB_DIV][M], @@ -891,6 +1139,9 @@ int16_t quantize_sns( if ( is_side ) { +#ifdef IVAS_FLOAT_FIXED + const Word16 *const *side_cdbks_fx = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_fx : ivas_sns_cdbks_side_tcx10_fx; +#endif const float *const *side_cdbks = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20 : ivas_sns_cdbks_side_tcx10; const int16_t *side_levels = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_levels : ivas_sns_cdbks_side_tcx10_levels; @@ -902,7 +1153,21 @@ int16_t quantize_sns( nStages = SNS_MSVQ_NSTAGES_SIDE; bits = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_bits : ivas_sns_cdbks_side_tcx10_bits; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 snsQ_fx[32]; + Word16 sns_e; + Word16 weights_fx[24]; + + f2me_buf( snsQ, snsQ_fx, &sns_e, M ); + Scale_sig32( snsQ_fx, M, sns_e - s_max( 0, sns_e + 1 ) ); + sns_e = s_max( sns_e + 1, 0 ); + floatToFixed_arr( weights, weights_fx, Q8, 24 ); +#endif + msvq_enc_ivas_fx( side_cdbks_fx, Q15, NULL, NULL, snsQ_fx, sns_e, side_levels, 3, nStages, weights_fx, M, M, 0, NULL, &indices[idxIndices] ); +#else msvq_enc( side_cdbks, NULL, NULL, snsQ, side_levels, 3, nStages, weights, M, M, 0, NULL, &indices[idxIndices] ); +#endif msvq_dec_float( side_cdbks, NULL, NULL, nStages, M, M, &indices[idxIndices], 0, NULL, snsQ, NULL ); } else @@ -946,3 +1211,4 @@ int16_t quantize_sns( return nbits; } +#endif diff --git a/lib_enc/ivas_spar_encoder.c b/lib_enc/ivas_spar_encoder.c index ead9c4d2598cb84ee2b32fd8ab5154ff17162e6e..97c5a0d6e6de5d2b59194b941c7c78a650e00c63 100644 --- a/lib_enc/ivas_spar_encoder.c +++ b/lib_enc/ivas_spar_encoder.c @@ -916,6 +916,15 @@ static ivas_error ivas_spar_enc_process( // Word16 q_pcm_tmp_fx[DIRAC_MAX_ANA_CHANS][L_FRAME48k * 2]; // Word16 *q_p_pcm_tmp_fx[DIRAC_MAX_ANA_CHANS]; Word16 q_pcm_fx[DIRAC_MAX_ANA_CHANS]; +#endif +#ifdef IVAS_FLOAT_FIXED + // Word32 *ppIn_FR_real_fx[IVAS_SPAR_MAX_CH], *ppIn_FR_imag_fx[IVAS_SPAR_MAX_CH]; + // Word32 wyzx_del_buf_fx[FOA_CHANNELS][IVAS_FB_1MS_48K_SAMP]; + Word32 data_fix[MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS][L_FRAME48k]; + Word16 q_data_fix[MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS]; + Word32 *data_fx[MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS]; + // Word16 q_cmplx[IVAS_SPAR_MAX_CH]; + Word16 q_p_pcm_tmp_fx[DIRAC_MAX_ANA_CHANS]; #endif int16_t i, j, input_frame, dtx_vad; int16_t transient_det[2]; @@ -930,6 +939,7 @@ static ivas_error ivas_spar_enc_process( int16_t ts, l_ts, num_del_samples, b, i_ts; float *ppIn_FR_real[IVAS_SPAR_MAX_CH], *ppIn_FR_imag[IVAS_SPAR_MAX_CH]; + Word32 *ppIn_FR_real_fx[IVAS_SPAR_MAX_CH], *ppIn_FR_imag_fx[IVAS_SPAR_MAX_CH]; float wyzx_del_buf[FOA_CHANNELS][IVAS_FB_1MS_48K_SAMP]; int16_t dyn_active_w_flag; int16_t nchan_fb_in; @@ -968,12 +978,12 @@ static ivas_error ivas_spar_enc_process( *-----------------------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED { - Word32 data_fix[L_FRAME48k]; + // Word32 data_fix[L_FRAME48k]; FOR( i = 0; i < input_frame; i++ ) { - data_fix[i] = (Word32) ( data_f[0][i] * ( 1 << Q14 ) ); + data_fix[0][i] = (Word32) ( data_f[0][i] * ( 1 << Q14 ) ); } - ivas_transient_det_process_fx( hSpar->hTranDet, data_fix, input_frame, transient_det ); + ivas_transient_det_process_fx( hSpar->hTranDet, data_fix[0], input_frame, transient_det ); } #else ivas_transient_det_process( hSpar->hTranDet, data_f[0], input_frame, transient_det ); @@ -1014,33 +1024,152 @@ static ivas_error ivas_spar_enc_process( p_pcm_tmp[i] = pcm_tmp[i]; } - /* run Filter Bank overlapping MDFT analysis first, then we can use the temporary buffer for Parameter MDFT analysis*/ + + FOR( i = 0; i < nchan_fb_in; i++ ) + { + + p_pcm_tmp[i] = pcm_tmp[i]; +#ifdef IVAS_FLOAT_FIXED + p_pcm_tmp_fx[i] = pcm_tmp_fx[i]; + move32(); +#endif + } + /* Need to remove flt to fix conversions */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < hSpar->hFbMixer->fb_cfg->num_in_chans; i++ ) + { + hSpar->hFbMixer->q_ppFilterbank_prior_input_fx[i] = Q_factor_arrL( hSpar->hFbMixer->ppFilterbank_prior_input[i], hSpar->hFbMixer->fb_cfg->prior_input_length ); + + floatToFixed_arrL( hSpar->hFbMixer->ppFilterbank_prior_input[i], + hSpar->hFbMixer->ppFilterbank_prior_input_fx[i], hSpar->hFbMixer->q_ppFilterbank_prior_input_fx[i], hSpar->hFbMixer->fb_cfg->prior_input_length ); + } + /* In order to get the number of channels */ + Word16 num_chs_alloc; + + IF( hSpar->hFbMixer->fb_cfg->active_w_mixing == -1 ) + { + num_chs_alloc = 0; + } + ELSE IF( hSpar->hFbMixer->fb_cfg->active_w_mixing ) + { + num_chs_alloc = hSpar->hFbMixer->fb_cfg->num_in_chans; + } + ELSE + { + num_chs_alloc = 1; /* only W channel processed for predicting YZX */ + } + FOR( Word16 m = 0; m < MAX_INPUT_CHANNELS + MAX_NUM_OBJECTS; m++ ) + { + IF( data_f[m] != NULL && ( m <= nchan_fb_in + nchan_transport ) ) + { + q_data_fix[m] = Q_factor_arrL( data_f[m], input_frame ); + floatToFixed_arrL( data_f[m], data_fix[m], q_data_fix[m], input_frame ); + data_fx[m] = data_fix[m]; + } + } +#endif + ivas_fb_mixer_pcm_ingest_fx( hSpar->hFbMixer, data_fx, p_pcm_tmp_fx, input_frame, hSpar->hMdEnc->HOA_md_ind, q_data_fix, q_p_pcm_tmp_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < hSpar->hFbMixer->fb_cfg->num_in_chans; i++ ) + { + me2f_buf( p_pcm_tmp_fx[i], 31 - q_p_pcm_tmp_fx[i], p_pcm_tmp[i], input_frame * 2 ); + } + FOR( Word16 x = 0; x < num_chs_alloc; x++ ) + { + me2f_buf( p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], 31 - q_p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], p_pcm_tmp[hSpar->hFbMixer->fb_cfg->remix_order[x]], input_frame * 2 ); + + hSpar->hFbMixer->q_ppFilterbank_inFR_re_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]] = q_p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]]; + hSpar->hFbMixer->q_ppFilterbank_inFR_im_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]] = q_p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]]; + + me2f_buf( hSpar->hFbMixer->ppFilterbank_inFR_re_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], 31 - q_p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], + hSpar->hFbMixer->ppFilterbank_inFR_re[hSpar->hFbMixer->fb_cfg->remix_order[x]], input_frame ); + + me2f_buf( hSpar->hFbMixer->ppFilterbank_inFR_im_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], 31 - q_p_pcm_tmp_fx[hSpar->hFbMixer->fb_cfg->remix_order[x]], + hSpar->hFbMixer->ppFilterbank_inFR_im[hSpar->hFbMixer->fb_cfg->remix_order[x]], input_frame ); + } + /* Need to remove fix to flt conversions */ +#endif +#else ivas_fb_mixer_pcm_ingest( hSpar->hFbMixer, data_f, p_pcm_tmp, input_frame, hSpar->hMdEnc->HOA_md_ind ); +#endif /* prepare Parameter MDFT analysis */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS for ( i = 0; i < nchan_fb_in; i++ ) { ppIn_FR_real[i] = p_pcm_tmp[i]; ppIn_FR_imag[i] = p_pcm_tmp[i] + input_frame; p_pcm_tmp[i] = data_f[i]; } +#endif - l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + for ( i = 0; i < nchan_fb_in; i++ ) + { + ppIn_FR_real_fx[i] = p_pcm_tmp_fx[i]; + ppIn_FR_imag_fx[i] = p_pcm_tmp_fx[i] + input_frame; + p_pcm_tmp_fx[i] = data_fx[i]; + } - for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < nchan_fb_in; i++ ) { - ivas_fb_mixer_get_windowed_fr( hSpar->hFbMixer, p_pcm_tmp, ppIn_FR_real, ppIn_FR_imag, l_ts, l_ts, nchan_fb_in ); + floatToFixed_arrL( p_pcm_tmp[i], p_pcm_tmp_fx[i], Q14, input_frame ); + floatToFixed_arrL( hSpar->hFbMixer->ppFilterbank_prior_input[i], hSpar->hFbMixer->ppFilterbank_prior_input_fx[i], Q14, input_frame ); + } +#endif + l_ts = input_frame / MAX_PARAM_SPATIAL_SUBFRAMES; + Word16 gb = find_guarded_bits_fx( l_ts ); + FOR( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + ivas_fb_mixer_get_windowed_fr_fx( hSpar->hFbMixer, p_pcm_tmp_fx, ppIn_FR_real_fx, ppIn_FR_imag_fx, l_ts, l_ts, nchan_fb_in, gb ); - ivas_fb_mixer_update_prior_input( hSpar->hFbMixer, p_pcm_tmp, l_ts, nchan_fb_in ); + ivas_fb_mixer_update_prior_input_fx( hSpar->hFbMixer, p_pcm_tmp_fx, l_ts, nchan_fb_in ); + + FOR( i = 0; i < nchan_fb_in; i++ ) + { + p_pcm_tmp_fx[i] += l_ts; + ppIn_FR_real_fx[i] += l_ts; + ppIn_FR_imag_fx[i] += l_ts; + } + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*To be removed*/ + FOR( i = 0; i < nchan_fb_in; i++ ) + { + fixedToFloat_arrL( hSpar->hFbMixer->ppFilterbank_prior_input_fx[i], hSpar->hFbMixer->ppFilterbank_prior_input[i], Q14, input_frame ); + } + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + for ( i = 0; i < nchan_fb_in; i++ ) + { + p_pcm_tmp_fx[i] -= l_ts; + ppIn_FR_real_fx[i] -= l_ts; + ppIn_FR_imag_fx[i] -= l_ts; + } + } + for ( ts = 0; ts < MAX_PARAM_SPATIAL_SUBFRAMES; ts++ ) + { + for ( int ch_idx = 0; ch_idx < nchan_fb_in; ch_idx++ ) + { + fixedToFloat_arrL( ppIn_FR_real_fx[ch_idx], ppIn_FR_real[ch_idx], Q14 - gb, l_ts ); + fixedToFloat_arrL( ppIn_FR_imag_fx[ch_idx], ppIn_FR_imag[ch_idx], Q14 - gb, l_ts ); + fixedToFloat_arrL( p_pcm_tmp_fx[ch_idx], p_pcm_tmp[ch_idx], Q14, l_ts ); + } for ( i = 0; i < nchan_fb_in; i++ ) { + p_pcm_tmp_fx[i] += l_ts; + ppIn_FR_real_fx[i] += l_ts; + ppIn_FR_imag_fx[i] += l_ts; + p_pcm_tmp[i] += l_ts; ppIn_FR_real[i] += l_ts; ppIn_FR_imag[i] += l_ts; } } - +#endif /* turn pointers back to the local buffer, needed for the following processing */ for ( i = 0; i < nchan_fb_in; i++ ) { diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index d843afc7078ab19786ed7ad26cb4ebaf44952bd3..2e167fe14c5d2a83e91f8f6641009daa05eb9b82 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -76,9 +76,10 @@ typedef struct stereo_itd_data_struct float prev_avg_max; Word32 prev_avg_max_fx; Word16 prev_avg_max_fx_e; +#ifndef IVAS_FLOAT_FIXED float currFlatness; - Word32 currFlatness_fx; - Word16 currFlatness_fx_e; +#endif + Word16 currFlatness_fx; /* Xtalk classifier */ float prev_m1; @@ -166,7 +167,7 @@ typedef struct stereo_dft_enc_data_struct float DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC]; int16_t dft_ovl; /* Overlap size */ int16_t dft_zp; /* Zero padding */ - +#ifndef IVAS_FLOAT_FIXED const float *win; /* DFT window */ const float *win_8k; /* DFT window */ const float *win_12k8; /* DFT window */ @@ -186,8 +187,8 @@ typedef struct stereo_dft_enc_data_struct const float *dft_trigo_12k8; const float *dft_trigo_16k; const float *dft_trigo_32k; +#endif int16_t dft_trigo_step; - float output_mem_res_8k[STEREO_DFT_OVL_8k]; /*I/O channel buffers */ @@ -196,24 +197,28 @@ typedef struct stereo_dft_enc_data_struct float output_mem_dmx_16k[STEREO_DFT_OVL_16k]; /*can hold 16, 12.8 or 32kHz signals*/ float output_mem_dmx_32k[STEREO_DFT_OVL_32k]; /*can hold 16, 12.8 or 32kHz signals*/ float output_mem_dmx_16k_shb[STEREO_DFT_OVL_16k]; +#ifndef IVAS_FLOAT_FIXED float input_mem_itd[CPE_CHANNELS][STEREO_DFT_OVL_MAX]; - +#endif /*Bands*/ int16_t band_res[STEREO_DFT_ENC_DFT_NB]; int16_t band_limits[STEREO_DFT_BAND_MAX + 1]; int16_t nbands; int16_t band_limits_dmx[STEREO_DFT_BAND_MAX + 1]; int16_t nbands_dmx; - +#ifndef IVAS_FLOAT_FIXED /*Stereo parameters*/ float past_nrgL[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; float past_nrgR[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; float past_dot_prod_real[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; float past_dot_prod_imag[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; +#endif int16_t nrg_past_pos; /*Side Gain*/ +#ifndef IVAS_FLOAT_FIXED float side_gain[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; +#endif 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; @@ -229,21 +234,27 @@ typedef struct stereo_dft_enc_data_struct #endif /* Stereo CNG */ +#ifndef IVAS_FLOAT_FIXED float sidSideGain[STEREO_DFT_ERB4_BANDS]; - Word32 sidSideGain_fx[STEREO_DFT_ERB4_BANDS]; // Q31? +#endif float win_ana_energy; - Word16 win_ana_energy_fx; // Q15 + Word32 sidSideGain_fx[STEREO_DFT_ERB4_BANDS]; // Q31? + Word16 win_ana_energy_fx; // Q15 +#ifndef IVAS_FLOAT_FIXED float xspec_smooth[STEREO_DFT_N_32k_ENC]; + float sid_gipd; + float prev_sid_gipd; float Spd_L_smooth[STEREO_DFT_N_32k_ENC / 2]; float Spd_R_smooth[STEREO_DFT_N_32k_ENC / 2]; - float sid_gipd; +#endif int16_t coh_fade_counter; - float prev_sid_gipd; Word32 prev_sid_gipd_fx; // Q13 int16_t prev_sid_no_ipd_flag; /*IPD*/ +#ifndef IVAS_FLOAT_FIXED float gipd[STEREO_DFT_ENC_DFT_NB]; +#endif int16_t gipd_band_max; int16_t gipd_index; int16_t no_ipd_flag; /* flag to indicate when group IPD gets used */ @@ -252,6 +263,7 @@ typedef struct stereo_dft_enc_data_struct int16_t no_ipd_cnt1; /* counter */ int16_t attackPresent; int16_t wasTransient; +#ifndef IVAS_FLOAT_FIXED float gainIPD_sm; /* long-term gain IPD for NIPD detection */ float sfm; float sum_dot_prod_real; @@ -260,27 +272,30 @@ typedef struct stereo_dft_enc_data_struct float dot_prod_img_smooth[STEREO_DFT_BAND_MAX]; float ipd_buf[STEREO_DFT_BAND_MAX][STEREO_DFT_IPD_BUF_LEN]; float prev_gipd; - +#endif /*ITD*/ ITD_DATA_HANDLE hItd; - +#ifndef IVAS_FLOAT_FIXED float voicing_lt; +#endif Word32 voicing_lt_fx; // Q31 int16_t currentNumUpdates; int16_t expectedNumUpdates; /* Expected number of frames before use of ITD estimate */ int16_t resetFrames; - +#ifndef IVAS_FLOAT_FIXED /* energy buffers for ICBWE */ float nrg_L[2]; float nrg_R[2]; float nrg_DMX[2]; - +#endif /*Residual prediction*/ - int16_t res_pred_mode[STEREO_DFT_ENC_DFT_NB]; /* mode from 0 (off) to 1 (on) */ + int16_t res_pred_mode[STEREO_DFT_ENC_DFT_NB]; /* mode from 0 (off) to 1 (on) */ +#ifndef IVAS_FLOAT_FIXED float res_pred_gain[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; /*prediction gain for the residual HFs */ - int16_t res_pred_band_min; /* Band min for prediction of residual */ +#endif + int16_t res_pred_band_min; /* Band min for prediction of residual */ int16_t res_pred_flag_1; int16_t res_pred_flag_2; int16_t res_pred_counter; @@ -289,11 +304,12 @@ typedef struct stereo_dft_enc_data_struct int16_t res_pred_index_ECDiff[STEREO_DFT_BAND_MAX]; int16_t res_pred_index_ECprevious[STEREO_DFT_BAND_MAX]; int16_t reverb_flag; +#ifndef IVAS_FLOAT_FIXED float pre_sub_nrg_DMX[STEREO_DFT_BAND_MAX]; float diff_l_h_sm; float diff_r_h_sm; float prev_fac2; - +#endif /*Residual coding*/ int16_t res_cod_mode[STEREO_DFT_ENC_DFT_NB]; /* mode from 0 (off) to 3 */ int16_t res_cod_band_max; /* Band max for coding of residual */ @@ -305,18 +321,24 @@ typedef struct stereo_dft_enc_data_struct int16_t first_frm_flag; /* ADAP first frame flag */ /* flags and data for adaptive wideband residual coding */ +#ifndef IVAS_FLOAT_FIXED float res_dmx_ratio_lt; /* long term energy ratio between RES and DMX */ - int16_t hangover_cnt0; /* counter 0 for hangover */ - int16_t hangover_cnt1; /* counter 1 for hangover */ +#endif + int16_t hangover_cnt0; /* counter 0 for hangover */ + int16_t hangover_cnt1; /* counter 1 for hangover */ +#ifndef IVAS_FLOAT_FIXED float dmx_res_all_prev; /* energy of the previous frame */ - +#endif int16_t last_res_cod_mode_modify_flag; /* a flag to indicate whether the res_cod_mode_flag has been modified for the switching frame in which res_cod_mode_flag should be swithced from 1 to 0 */ int16_t res_cod_sw_flag; /* a flag to indicate whether it is a switching frame */ - float switch_fade_factor; /* Adaptive fade factor for switch frame */ - +#ifndef IVAS_FLOAT_FIXED + float switch_fade_factor; /* Adaptive fade factor for switch frame */ +#endif /*misc*/ +#ifndef IVAS_FLOAT_FIXED float icbweRefEner; float lbEner; +#endif #ifdef IVAS_FLOAT_FIXED Word32 icbweRefEner_fx; Word16 icbweRefEner_fx_e; @@ -356,7 +378,7 @@ typedef struct stereo_dft_enc_data_struct Word32 ipd_buf_fx[STEREO_DFT_BAND_MAX][STEREO_DFT_IPD_BUF_LEN]; // Q13 Word32 prev_gipd_fx; // Q13 Word32 xspec_smooth_fx[STEREO_DFT_N_32k_ENC]; // Q(31 - xspec_smooth_fx_e) - Word16 xspec_smooth_fx_e; + Word16 xspec_smooth_fx_e[STEREO_DFT_N_32k_ENC]; Word32 Spd_L_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; // Q(31 - Spd_L_smooth_fx_e) Word16 Spd_L_smooth_fx_e; Word32 Spd_R_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; // Q(31 - Spd_R_smooth_fx_e) @@ -390,7 +412,7 @@ typedef struct stereo_dft_enc_data_struct Word16 res_cod_NRG_S_fx_e[STEREO_DFT_BAND_MAX]; Word32 res_cod_SNR_M_fx[STEREO_DFT_BAND_MAX]; // Q(31 - res_cod_SNR_M_fx_e[]) Word16 res_cod_SNR_M_fx_e[STEREO_DFT_BAND_MAX]; - Word32 old_snr_fx; + Word32 old_snr_fx; // Q25 Word32 past_nrgL_fx[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; // Q(31 - past_nrgL_fx_e[]) Word16 past_nrgL_fx_e[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; Word32 past_nrgR_fx[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; // Q(31 - past_nrgR_fx_e[]) @@ -452,7 +474,7 @@ typedef struct stereo_td_enc_data_structure Word16 tdm_lp_reuse_flag; /* Flag that indicate if it is possible to reuse the LP coefficient from the primary channel or not */ Word16 tdm_low_rate_mode; /* secondary channel low rate mode flag */ float tdm_Pri_pitch_buf[NB_SUBFR]; - +#ifndef IVAS_FLOAT_FIXED float tdm_lt_corr_RM; /* Long term right-mono correlation */ float tdm_lt_corr_LM; /* Long term left-mono correlation */ float tdm_last_diff_lt_corr; /* long term correlation difference mem */ @@ -462,17 +484,18 @@ typedef struct stereo_td_enc_data_structure float tdm_lt_rms_R; /* Right channel long term rms */ float tdm_last_ener_lt_R; /* Right channel long term energy */ float tdm_last_ener_lt_L; /* Left channel long term energy */ +#endif Word16 tdm_Pitch_reuse_flag; Word32 tdm_lt_corr_RM_fx; /* Long term right-mono correlation */ Word32 tdm_lt_corr_LM_fx; /* Long term left-mono correlation */ Word32 tdm_last_diff_lt_corr_fx; /* long term correlation difference mem */ Word16 q_tdm_last_diff_lt_corr; - Word32 tdm_last_ratio_fx; /* Last TDM ratio */ - Word32 tdm_lt_rms_L_fx; /* Left channel long term rms */ - Word32 tdm_lt_rms_R_fx; /* Right channel long term rms */ - Word32 tdm_last_ener_lt_R_fx; /* Right channel long term energy */ - Word32 tdm_last_ener_lt_L_fx; /* Left channel long term energy */ + Word32 tdm_last_ratio_fx; /* Last TDM ratio */ + Word32 tdm_lt_rms_L_fx; /* Left channel long term rms */ /*Q16*/ + Word32 tdm_lt_rms_R_fx; /* Right channel long term rms */ /*Q16*/ + Word32 tdm_last_ener_lt_R_fx; /* Right channel long term energy */ /*Q16*/ + Word32 tdm_last_ener_lt_L_fx; /* Left channel long term energy */ /*Q16*/ Word16 tdm_last_ratio_idx; /* last TDM ratio index */ Word16 tdm_last_SM_flag; /* Flag to signal a SM encoding scheme -> better for some music item */ @@ -481,20 +504,23 @@ typedef struct stereo_td_enc_data_structure Word16 tdm_hyst_cnt; /* Counter */ Word16 tdm_prev_stable_idx; /* Previous Transmitted ratio index*/ Word16 tdm_prev_desired_idx; /* Previous Transmitted ratio index*/ - float tdm_LT_es_em; /* Long term evoluation of the side to mono energy ratio */ - Word32 tdm_LT_es_em_fx; /* Long term evoluation of the side to mono energy ratio */ - Word16 tdm_use_IAWB_Ave_lpc; /* Flag to indicate the usage of mean inactive LP coefficients */ +#ifndef IVAS_FLOAT_FIXED + float tdm_LT_es_em; /* Long term evoluation of the side to mono energy ratio */ +#endif + Word32 tdm_LT_es_em_fx; /* Long term evoluation of the side to mono energy ratio */ /*Q21*/ + Word16 tdm_use_IAWB_Ave_lpc; /* Flag to indicate the usage of mean inactive LP coefficients */ /* NOOP parameters */ +#ifndef IVAS_FLOAT_FIXED float tdm_lt_corr_RM_SM; /* Long term right-mono correlation in SM mode*/ float tdm_lt_corr_LM_SM; /* Long term left-mono correlation in SM mode*/ float tdm_last_diff_lt_corr_SM; /* long term correlation difference mem in SM mode*/ float tdm_last_ratio_SM; /* Last TDM ratio in SM mode*/ - - float tdm_lt_rms_L_SM; /* Left channel long term rms in SM mode*/ - float tdm_lt_rms_R_SM; /* Right channel long term rms in SM mode*/ - float tdm_last_ener_lt_R_SM; /* Right channel long term energy in SM mode*/ - float tdm_last_ener_lt_L_SM; /* Left channel long term energy in SM mode*/ + float tdm_lt_rms_L_SM; /* Left channel long term rms in SM mode*/ + float tdm_lt_rms_R_SM; /* Right channel long term rms in SM mode*/ + float tdm_last_ener_lt_R_SM; /* Right channel long term energy in SM mode*/ + float tdm_last_ener_lt_L_SM; /* Left channel long term energy in SM mode*/ +#endif Word32 tdm_lt_corr_RM_SM_fx; /* Long term right-mono correlation in SM mode*/ Word32 tdm_lt_corr_LM_SM_fx; /* Long term left-mono correlation in SM mode*/ @@ -513,14 +539,16 @@ typedef struct stereo_td_enc_data_structure Word16 tdm_hyst_cnt_SM; /* Counter in SM mode*/ Word16 tdm_prev_stable_idx_SM; /* Previous Transmitted ratio index in SM mode*/ Word16 tdm_prev_desired_idx_SM; /* Previous Transmitted ratio index in SM mode*/ - float tdm_LT_es_em_SM; /* Long term evoluation of the side to mono energy ratio in SM mode*/ - Word32 tdm_LT_es_em_SM_fx; /* Long term evoluation of the side to mono energy ratio in SM mode*/ - Word16 tdm_NOOP_cnt; /* Counter for channel combination scheme */ - Word16 tdm_SM_flag; /* Flag for channel combination scheme */ - Word16 tdm_SM_last2_clas[2]; /* Class of the frame immediately prior to the previous frame */ - Word16 tdm_SM_last_clas[2]; /* Class of the previous frame */ - Word16 tdm_SM_modi_flag; /* Flag that indicates to modify ratio */ - Word16 tdm_SM_reset_flag; /* Flag that indicates to reset the parameters for SM mode */ +#ifndef IVAS_FLOAT_FIXED + float tdm_LT_es_em_SM; /* Long term evoluation of the side to mono energy ratio in SM mode*/ +#endif + Word32 tdm_LT_es_em_SM_fx; /* Long term evoluation of the side to mono energy ratio in SM mode*/ + Word16 tdm_NOOP_cnt; /* Counter for channel combination scheme */ + Word16 tdm_SM_flag; /* Flag for channel combination scheme */ + Word16 tdm_SM_last2_clas[2]; /* Class of the frame immediately prior to the previous frame */ + Word16 tdm_SM_last_clas[2]; /* Class of the previous frame */ + Word16 tdm_SM_modi_flag; /* Flag that indicates to modify ratio */ + Word16 tdm_SM_reset_flag; /* Flag that indicates to reset the parameters for SM mode */ Word16 tdm_FD2LRTD_SW_cnt; /* Count the number of frames following a FD to LRTD switching */ Word16 tdm_LRTD_flag; /* LRTD stereo mode flag */ @@ -532,7 +560,8 @@ typedef struct stereo_td_enc_data_structure Word16 tdm_last_LRTD_frame_cnt; /* Count the number of frame since the last LRTD frame */ Word16 tdm_last_LRTD_PriCh_cnt; /* Count the number of frame since the primary channel changed */ Word16 flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */ - Word32 tdm_Pri_pitch_buf_fx[NB_SUBFR]; + // Word32 tdm_Pri_pitch_buf_fx[NB_SUBFR]; + Word16 tdm_Pri_pitch_buf_fx[NB_SUBFR]; // Q6 } STEREO_TD_ENC_DATA, *STEREO_TD_ENC_DATA_HANDLE; @@ -555,6 +584,9 @@ typedef struct stereo_tca_enc_data_structure Word32 instTargetGain_fx; /* instantaneous gain norm applied on target (or right) channel in current frame //Q29*/ Word32 prevTargetGain_fx; /* gain norm applied on target (or right) channel in previous frame //Q29 taken from decoder*/ Word16 corrStatsSmoothFac_fx; /* gD/corrStats smoothing based on corrStats //Q15*/ + Word16 targetGain_fx_e; + Word16 instTargetGain_fx_e; + Word16 prevTargetGain_fx_e; Word16 lMemRecalc; Word16 lMemRecalc_12k8; @@ -568,16 +600,22 @@ typedef struct stereo_tca_enc_data_structure float memChanL_DS[ADDED_MEM_DS]; /* left channel input speech memory for downmix */ float memChanR_DS[ADDED_MEM_DS]; /* right channel input speech memory for downmix */ +#ifndef IVAS_FLOAT_FIXED float mem_tempF; - float memdecim[12]; /* memory for pre-rmphasis filter for resampling */ +#endif + float memdecim[12]; /* memory for pre-rmphasis filter for resampling */ +#ifndef IVAS_FLOAT_FIXED float corrEstPrev[3][2 * L_NCSHIFT_DS + 1]; /* Prev correlation vector */ float corrEstLT[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ - float ica_envVarLT; +#endif + +#ifndef IVAS_FLOAT_FIXED float C_mem[2 * L_NCSHIFT_DS + 1]; float E1_mem, E2_mem; float delay_0_mem[MAX_DELAYREGLEN]; float smooth_dist_reg_prv_corr; +#endif Word32 memChanL_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH]; /* left channel input to correct at the cross-over */ Word32 memChanR_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH]; /* right channel input to correct at the cross-over */ @@ -585,15 +623,23 @@ typedef struct stereo_tca_enc_data_structure Word32 memChanL_DS_fx[ADDED_MEM_DS]; /* left channel input speech memory for downmix */ Word32 memChanR_DS_fx[ADDED_MEM_DS]; /* right channel input speech memory for downmix */ Word32 mem_tempF_fx; + Word16 mem_tempF_exp; Word32 memdecim_fx[12]; /* memory for pre-rmphasis filter for resampling */ Word32 corrEstPrev_fx[3][2 * L_NCSHIFT_DS + 1]; /* Prev correlation vector */ - Word32 corrEstLT_fx[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ + Word16 corrEstPrev_exp; + Word32 corrEstLT_fx[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ + Word16 corrEstLT_exp; - Word32 ica_envVarLT_fx; // Q20 + Word32 ica_envVarLT_fx; + Word16 ica_envVarLT_exp; Word32 C_mem_fx[2 * L_NCSHIFT_DS + 1]; + Word16 C_mem_exp[2 * L_NCSHIFT_DS + 1]; Word32 E1_mem_fx, E2_mem_fx; + Word16 E1_E2_mem_exp; Word32 delay_0_mem_fx[MAX_DELAYREGLEN]; - Word16 smooth_dist_reg_prv_corr_fx; + Word16 delay_0_mem_exp; + Word32 smooth_dist_reg_prv_corr_fx; + Word16 smooth_dist_reg_prv_corr_exp; Word16 LRTD_G_ATT_cnt; @@ -635,10 +681,11 @@ typedef struct stereo_icbwe_enc_data_structure float icbwe_inp_mem[CPE_CHANNELS][NS2SA( 48000, L_MEM_RECALC_TBE_NS )]; float *dataChan[CPE_CHANNELS]; float memModifyFs_icbwe[CPE_CHANNELS][2 * L_FILT32k]; - +#ifndef IVAS_FLOAT_FIXED float mem_nrg_L[CPE_CHANNELS]; float mem_nrg_R[CPE_CHANNELS]; float mem_nrg_DMX[CPE_CHANNELS]; +#endif float gDes_pastFrame; float icbweRefEner; @@ -649,8 +696,8 @@ typedef struct stereo_icbwe_enc_data_structure Word16 memHPF_fx[8]; // Q -> q_dataChan_fx Word16 mem_decim_shb_ch0_fx[2 * L_FILT_MAX]; // Q0 - Word32 mem_shb_speech_ref_fx[L_LOOK_16k]; - Word32 mem_shb_speech_nonref_fx[L_LOOK_16k]; + Word16 mem_shb_speech_ref_fx[L_LOOK_16k]; + Word16 mem_shb_speech_nonref_fx[L_LOOK_16k]; Word32 mem_lpc_shbsynth_nonref_fx[LPC_SHB_ORDER]; Word32 prevSpecMapping_fx; Word32 memShbSpecMapping_fx; @@ -670,12 +717,32 @@ typedef struct stereo_icbwe_enc_data_structure Word32 mem_nrg_DMX_fx[CPE_CHANNELS]; Word32 gDes_pastFrame_fx; // Q31 Word32 icbweRefEner_fx; - Word32 shbSynthRef_fx[L_FRAME16k]; - Word32 nlExc16k_fx[L_FRAME16k]; - Word32 mixExc16k_fx[L_FRAME16k]; + Word16 shbSynthRef_fx[L_FRAME16k]; + Word16 nlExc16k_fx[L_FRAME16k]; + Word16 mixExc16k_fx[L_FRAME16k]; Word32 lpSHBRef_fx[LPC_SHB_ORDER + 1]; Word16 MSFlag; + Word16 icbweRefEner_fx_e; + + Word16 mem_shb_speech_ref_e; + Word16 mem_shb_speech_nonref_e; + Word16 mem_lpc_shbsynth_nonref_e; + Word16 memShbSpecMapping_e; + Word16 memShbSpecXcorr_e; + Word16 prevgsMapping_e; + Word16 prevRefEner_e; // Q31 + Word16 prevNonRefEner_e; // Q31 + Word16 memGsEnerMap_e; + Word16 mem_nrg_L_fx_e; + Word16 mem_nrg_R_fx_e; + Word16 mem_nrg_DMX_fx_e; + Word16 gDes_pastFrame_e; // Q31 + Word16 icbweRefEner_e; + Word16 shbSynthRef_e; + Word16 lpSHBRef_e; + Word16 nlExc16k_e; + Word16 mixExc16k_e; } STEREO_ICBWE_ENC_DATA, *STEREO_ICBWE_ENC_HANDLE; @@ -689,6 +756,7 @@ typedef struct ivas_stereo_classifier_data_structure /* features for xtalk classifier and UNCLR classifier */ Word16 clas_ch1; Word16 pitch_ch1[3]; +#ifndef IVAS_FLOAT_FIXED float voicing_ch1[3]; float cor_map_sum_ch1; float lsf_ch1[M]; @@ -698,16 +766,19 @@ typedef struct ivas_stereo_classifier_data_structure float non_sta_ch1; float sp_div_ch1; float ps_diff_ch1, ps_diff_ch2; - 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_ratio_m1_m2; float ratio_L; +#endif + Word32 ps_diff_ch1_fx, ps_diff_ch2_fx; + Word16 ps_diff_ch1_e, ps_diff_ch2_e; Word16 vad_flag_glob; Word16 vad_relE; Word16 aEn_raw[CPE_CHANNELS]; /* raw aEn for local relative energy estimation */ +#ifndef IVAS_FLOAT_FIXED float ave_ener_L; /* average energy of the L channel */ float ave_ener_R; /* average energy of the R channel */ float Etot_dn; /* average energy in dB - lower bound */ @@ -716,51 +787,69 @@ typedef struct ivas_stereo_classifier_data_structure float Etot_buf[UNCLR_L_ETOT]; /* running buffer for average energy in dB */ float relE_0_1; /* relative energy in the current frame normalized to (0,1) */ float relE_0_1_LT; +#endif Word16 unclr_sw_enable_cnt[CPE_CHANNELS]; /* UNCLR classifier - counter of frames suitable for UNCLR switching */ - +#ifndef IVAS_FLOAT_FIXED float unclr_relE_0_1_LT[UNCLR_RC_ORDER]; float unclr_wscore; - Word16 unclr_decision; /* UNCLR stereo classifier decision (0/1) */ float unclr_fv[SSC_MAX_NFEA]; /* UNCLR - feature vector */ +#endif + Word16 unclr_decision; /* UNCLR stereo classifier decision (0/1) */ Word16 unclr_corrLagMax_prev; - +#ifndef IVAS_FLOAT_FIXED float xtalk_score_buf[XTALK_SCORE_BUF_LEN]; - Word16 xtalk_decision; /* xtalk stereo classifier decision (0/1) */ +#endif + Word16 xtalk_decision; /* xtalk stereo classifier decision (0/1) */ +#ifndef IVAS_FLOAT_FIXED float xtalk_fv[SSC_MAX_NFEA]; /* xtalk - feature vector */ float xtalk_wscore; float xtalk_score; float xtalk_score_wrelE; + float is_speech; +#endif Word16 lrtd_mode; Word16 prev_lrtd_mode; - float is_speech; Word16 silence_flag; // Above needs to remove once everything done Word32 voicing_ch1_fx[3]; + Word16 voicing_ch1_e; Word32 cor_map_sum_ch1_fx; + Word16 cor_map_sum_ch1_e; Word32 lsf_ch1_fx[M]; Word32 lepsP_ch1_fx; + Word16 lepsP_ch1_e; Word32 dE1_ch1_fx, dE1_ch2_fx; + Word16 dE1_ch1_e, dE1_ch2_e; Word32 nchar_ch1_fx, nchar_ch2_fx; + Word16 nchar_ch1_e, nchar_ch2_e; Word32 non_sta_ch1_fx; + Word16 non_sta_ch1_e; Word32 sp_div_ch1_fx; + Word16 sp_div_ch1_e; Word32 ps_sta_ch1_fx, ps_sta_ch2_fx; + Word16 ps_sta_ch1_e, ps_sta_ch2_e; Word32 prev_g_IPD_fx; // Q29 Word32 prev_IPD_fx; // Q29 Word32 prev_ratio_m1_m2_fx; // Q31 Word32 ratio_L_fx; + Word16 ratio_L_e; Word32 ave_ener_L_fx; /* average energy of the L channel Q(31-ave_ener_L_fx_e) */ Word16 ave_ener_L_fx_e; /* average energy of the L channel */ Word32 ave_ener_R_fx; /* average energy of the R channel Q(31-ave_ener_R_fx_e) */ Word16 ave_ener_R_fx_e; /* average energy of the R channel */ Word32 Etot_dn_fx; /* average energy in dB - lower bound */ + Word16 Etot_dn_e; /* average energy in dB - lower bound */ Word32 Etot_up_fx; /* average energy in dB - upper bound */ + Word16 Etot_up_e; /* average energy in dB - upper bound */ Word32 relE_buf_fx[UNCLR_L_RELE]; /* running buffer for relative energy Q31 */ + Word16 relE_buf_e; /* running buffer for relative energy Q31 */ Word32 Etot_buf_fx[UNCLR_L_ETOT]; /* running buffer for average energy in dB */ + Word16 e_Etot_buf_fx; /* exponent for Etot_buf_fx*/ Word32 relE_0_1_fx; /* relative energy in the current frame normalized to (0,1) Q31 */ Word32 relE_0_1_LT_fx; // Q31 Word32 unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER]; // Q31 @@ -768,10 +857,10 @@ typedef struct ivas_stereo_classifier_data_structure Word32 unclr_fv_fx[SSC_MAX_NFEA]; /* UNCLR - feature vector */ // Q15 Word32 xtalk_score_buf_fx[XTALK_SCORE_BUF_LEN]; // Q31 Word32 xtalk_fv_fx[SSC_MAX_NFEA]; /* xtalk - feature vector */ // Q15 - Word32 xtalk_wscore_fx; - Word32 xtalk_score_fx; // Q31 - Word32 xtalk_score_wrelE_fx; - Word32 is_speech_fx; + Word32 xtalk_wscore_fx; // Q31 + Word32 xtalk_score_fx; // Q31 + Word32 xtalk_score_wrelE_fx; // Q31 + Word32 is_speech_fx; // Q9 } STEREO_CLASSIF_DATA, *STEREO_CLASSIF_HANDLE; @@ -802,11 +891,12 @@ typedef struct typedef struct front_vad_enc { - int16_t ini_frame; /* initialization frames counter */ - float lp_speech; /* long term speech average */ - /* Q9 long term speech average */ - float lp_noise; /* long term noise average */ - /* long term noise average */ + int16_t ini_frame; /* initialization frames counter */ +#ifndef IVAS_FLOAT_FIXED + float lp_speech; /* long term speech average */ + /* Q9 long term speech average */ + float lp_noise; /* long term noise average */ +#endif float mem_decim[2 * L_FILT_MAX]; /* decimation filter memory */ float buffer_12k8[3 * L_FRAME / 2]; /* 12k8 signal buffer */ @@ -996,6 +1086,8 @@ typedef struct ivas_param_mc_enc_data_structure int16_t transient_detector_delay; const float *dmx_factors; + const Word32 *dmx_factors_fx; + /* Multichannel Specific Parameters */ IVAS_PARAM_MC_METADATA hMetadataPMC; int16_t band_grouping[PARAM_MC_MAX_PARAMETER_BANDS + 1]; @@ -1019,7 +1111,14 @@ typedef struct ivas_mc_paramupmix_enc_data_structure ivas_enc_cov_handler_state_t *hCovEnc[MC_PARAMUPMIX_COMBINATIONS]; float ***cov_real[MC_PARAMUPMIX_COMBINATIONS]; float ***cov_dtx_real[MC_PARAMUPMIX_COMBINATIONS]; +#ifdef IVAS_FLOAT_FIXED + Word32 ***cov_real_fx[MC_PARAMUPMIX_COMBINATIONS]; + Word32 ***cov_dtx_real_fx[MC_PARAMUPMIX_COMBINATIONS]; +#endif float *midside[MC_PARAMUPMIX_COMBINATIONS][MC_PARAMUPMIX_NCH]; /* hold PCM of mid-side data */ +#ifdef IVAS_FLOAT_FIXED + Word32 *midside_fx[MC_PARAMUPMIX_COMBINATIONS][MC_PARAMUPMIX_NCH]; /* hold PCM of mid-side data */ //(st_ivas->q_data_fx) +#endif int32_t alpha_quant_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; int32_t beta_quant_prev[MC_PARAMUPMIX_COMBINATIONS][IVAS_MAX_NUM_BANDS]; int16_t first_frame; @@ -1033,6 +1132,10 @@ typedef struct ivas_mc_paramupmix_enc_data_structure typedef struct ivas_omasa_enc_state_structure { +#ifdef IVAS_FLOAT_FIXED + Word16 interpolator_fx[L_FRAME48k]; /*q15*/ + Word16 prev_object_dm_gains_fx[MAX_NUM_OBJECTS][MASA_MAX_TRANSPORT_CHANNELS]; /*q15*/ +#endif // IVAS_FLOAT_FIXED uint8_t nbands; uint8_t nCodingBands; uint8_t nSubframes; @@ -1111,7 +1214,10 @@ typedef struct ivas_masa_sync_struct typedef struct ivas_masa_encoder_data_struct { float energy[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - +#ifdef IVAS_FLOAT_FIXED + Word32 energy_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; +#endif int16_t num_Cldfb_instances; HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc[MAX_NUM_ENC_CLDFB_INSTANCES]; int16_t band_mapping[MASA_FREQUENCY_BANDS + 1]; @@ -1119,6 +1225,10 @@ typedef struct ivas_masa_encoder_data_struct float importanceWeight[MASA_FREQUENCY_BANDS]; SPHERICAL_GRID_DATA Sph_Grid16; float lfeToTotalEnergyRatio[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef IVAS_FLOAT_FIXED + Word32 lfeToTotalEnergyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 lfeToTotalEnergyRatio_e[MAX_PARAM_SPATIAL_SUBFRAMES]; +#endif float prevq_lfeToTotalEnergyRatio; int16_t prevq_lfeIndex; @@ -1152,7 +1262,11 @@ typedef struct ivas_mcmasa_enc_data_structure int16_t nCodingBands; /* delay compensation */ +#ifndef IVAS_FLOAT_FIXED float *delay_buffer_lfe[2]; /* Delay buffer for LFE estimation */ +#else + Word32 *delay_buffer_lfe[2]; /* Delay buffer for LFE estimation */ +#endif int16_t num_samples_delay_comp; int16_t num_slots_delay_comp; @@ -1162,13 +1276,19 @@ typedef struct ivas_mcmasa_enc_data_structure IVAS_FB_MIXER_HANDLE hFbMixerLfe; /* DirAC parameter estimation */ +#ifndef IVAS_FLOAT_FIXED float **direction_vector_m[DIRAC_NUM_DIMS]; /* Average direction vector */ +#else + Word32 **direction_vector_m_fx[DIRAC_NUM_DIMS]; /* Average direction vector */ +#endif + Word16 **direction_vector_e[DIRAC_NUM_DIMS]; /* Average direction vector */ int16_t band_grouping[MASA_FREQUENCY_BANDS + 1]; int16_t block_grouping[5]; /* diffuseness */ int16_t index_buffer_intensity; int8_t no_col_avg_diff; +#ifndef IVAS_FLOAT_FIXED float **buffer_intensity_real[DIRAC_NUM_DIMS]; float **buffer_intensity_real_vert; float *buffer_energy; @@ -1176,26 +1296,60 @@ typedef struct ivas_mcmasa_enc_data_structure float chnlToFoaMtx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; float chnlToFoaEvenMtx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; float ls_azimuth[MCMASA_MAX_ANA_CHANS]; +#else + Word32 **buffer_intensity_real_fx[DIRAC_NUM_DIMS]; + Word16 buffer_intensity_real_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 **buffer_intensity_real_vert_fx; + Word16 buffer_intensity_real_vert_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 *buffer_energy_fx; + Word16 buffer_energy_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 chnlToFoaMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; + Word32 chnlToFoaEvenMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS]; +#endif + int16_t leftNearest[MCMASA_MAX_ANA_CHANS]; int16_t rightNearest[MCMASA_MAX_ANA_CHANS]; int16_t numHorizontalChannels; uint8_t isHorizontalSetup; uint8_t combineRatios; +#ifndef IVAS_FLOAT_FIXED float prevMultiChEne; float prevDownmixEne; float prevEQ; float interpolator[L_FRAME48k]; +#else + Word32 prevMultiChEne_fx; + Word16 prevMultiChEne_e; + Word32 prevDownmixEne_fx; + Word16 prevDownmixEne_e; + Word32 prevEQ_fx; + Word16 prevEQ_e; + Word16 interpolator_fx[L_FRAME48k]; +#endif uint8_t separateChannelEnabled; int16_t separateChannelIndex; /* LFE coding */ +#ifndef IVAS_FLOAT_FIXED float lfeLfEne[MAX_PARAM_SPATIAL_SUBFRAMES]; float totalLfEne[MAX_PARAM_SPATIAL_SUBFRAMES]; float *lfeAnaRingBuffer[2]; +#else + Word32 lfeLfEne[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 lfeLfEne_e[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 totalLfEne[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 totalLfEne_e[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 *lfeAnaRingBuffer[2]; +#endif int16_t ringBufferPointer; +#ifndef IVAS_FLOAT_FIXED float lowpassSum[2]; +#else + Word32 lowpassSum[2]; +#endif int16_t ringBufferSize; } MCMASA_ENC_DATA, *MCMASA_ENC_HANDLE; @@ -1207,12 +1361,25 @@ typedef struct ivas_mcmasa_enc_data_structure typedef struct ivas_osba_enc_data_structure { + +#ifdef IVAS_FLOAT_FIXED + Word32 interpolator_fx[L_FRAME48k]; +#else float interpolator[L_FRAME48k]; - float prev_object_dm_gains[MAX_NUM_OBJECTS][MAX_INPUT_CHANNELS]; +#endif +#ifdef IVAS_FLOAT_FIXED + Word32 prev_object_dm_gains_fx[MAX_NUM_OBJECTS][MAX_INPUT_CHANNELS]; +#else + float prev_object_dm_gains[MAX_NUM_OBJECTS][MAX_INPUT_CHANNELS]; +#endif int16_t nchan_ism; - float *input_data_mem[MAX_NUM_OBJECTS]; +#ifdef IVAS_FLOAT_FIXED + Word32 *input_data_mem_fx[MAX_NUM_OBJECTS]; +#else + float *input_data_mem[MAX_NUM_OBJECTS]; +#endif } OSBA_ENC_DATA, *OSBA_ENC_HANDLE; /*----------------------------------------------------------------------------------* @@ -1221,19 +1388,21 @@ typedef struct ivas_osba_enc_data_structure typedef struct stereo_cng_enc { - Word16 prev_sg_average_counter; /* Counter for sidegain averaging */ - Word16 sg_active_cnt; /* Counter for sidegain averaging */ - Word16 sg_average_counter; /* Counter for sidegain averaging */ - float sg_average[STEREO_DFT_ERB4_BANDS]; /* Sidegain average */ - float prev_sg_average[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average */ + Word16 prev_sg_average_counter; /* Counter for sidegain averaging */ + Word16 sg_active_cnt; /* Counter for sidegain averaging */ + Word16 sg_average_counter; /* Counter for sidegain averaging */ + float sg_average[STEREO_DFT_ERB4_BANDS]; /* Sidegain average */ +#ifndef IVAS_FLOAT_FIXED + float prev_sg_average[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average */ +#endif float mem_cohBand[STEREO_DFT_BAND_MAX / 2]; /* Coherence memory */ float prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )]; /* Previous coherence */ Word16 cng_counter; /* Counter for cng period length */ Word16 td_active; /* TD-stereo indication */ Word16 first_SID_after_TD; /* Set if first SID frame after TD stereo */ Word16 first_SID; /* Set if first SID frame since codec start */ - Word32 sg_average_fx[STEREO_DFT_ERB4_BANDS]; /* Sidegain average */ - Word32 prev_sg_average_fx[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average */ + Word32 sg_average_fx[STEREO_DFT_ERB4_BANDS]; /* Sidegain average Q26 */ + Word32 prev_sg_average_fx[STEREO_DFT_ERB4_BANDS]; /* Previous sidegain average Q26 */ Word32 mem_cohBand_fx[STEREO_DFT_BAND_MAX / 2]; /* Coherence memory */ Word32 prev_cohBand_fx[2 * ( STEREO_DFT_BAND_MAX / 2 )]; /* Previous coherence */ } STEREO_CNG_ENC, *STEREO_CNG_ENC_HANDLE; @@ -1326,6 +1495,7 @@ typedef struct mct_enc_data_structure #ifdef IVAS_FLOAT_FIXED Word32 *p_mdst_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS]; Word32 *p_orig_spectrum_long_fx[MCT_MAX_BLOCKS][CPE_CHANNELS]; + Word16 q_orig_spectrum_long_fx; #endif int16_t tnsBits[MCT_MAX_BLOCKS][CPE_CHANNELS][NB_DIV]; /* number of tns bits in the frame */ int16_t tnsSize[MCT_MAX_BLOCKS][CPE_CHANNELS][NB_DIV]; /* number of tns parameters put into prm */ diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 1d562403749314016c37fa4e8cdc3e2a202abc12..1b1d27c34f638a067902e63be97058e4e3c96786 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -42,26 +42,33 @@ #include "ivas_cnst.h" #include "wmc_auto.h" #include "prot_fx.h" - +#include "ivas_prot_fx.h" /*-------------------------------------------------------------------* * Local constants *-------------------------------------------------------------------*/ -#define RC_FACT_UP 0.3f -#define RC_FACT_UP_Q31 644245094 -#define RC_FACT_DOWN 0.7f -#define RC_FACT_DOWN_Q31 1503238554 -#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 RC_FACT_UP 0.3f +#define RC_FACT_UP_Q31 644245094 +#define RC_FACT_DOWN 0.7f +#define RC_FACT_DOWN_Q31 1503238554 +#define UNCLR_SCORE_THR 4.0f +#define UNCLR_SCORE_THR_Q28 ( 1073741824 ) +#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_UP_Q28 ( 805306368 ) +#define ONE_BY_XTALK_SCORE_THR_TD_UP_Q31 ( 715827882 ) +#define XTALK_SCORE_THR_TD_DN 4.0f +#define XTALK_SCORE_THR_TD_DN_Q28 ( 1073741824 ) +#define ONE_BY_XTALK_SCORE_THR_TD_DN_Q31 ( 536870912 ) #define UNCLR_INTERCEPT_TD 0.780313f +#define UNCLR_INTERCEPT_TD_Q28 ( 209463676 ) #define UNCLR_INTERCEPT_DFT 1.226513f #define UNCLR_INTERCEPT_DFT_Q30 1316958306 #define XTALK_INTERCEPT_TD -1.770983f +#define XTALK_INTERCEPT_TD_Q28 ( -475394629 ) #define XTALK_INTERCEPT_DFT -0.758556f #define XTALK_INTERCEPT_DFT_Q31 -1628986606 #define XTALK_INTERCEPT_DFT_Q27 -101811663 @@ -75,17 +82,22 @@ /*-------------------------------------------------------------------* * Local function prototypes *-------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED static void rc_filter_fx( const Word32 x, Word32 *y, const Word16 order, const Word32 tau ); +#else static void rc_filter( const float x, float *y, const int16_t order, const float tau ); - +#endif +#ifdef IVAS_FLOAT_FIXED +static void edge_detect( const Word32 *inp, const Word16 len, const Word32 inp_min, const Word32 inp_max, Word16 *edge_str, Word16 *edge_type ); +#else 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 ); +#endif #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 +#else static float redge_detect( const float *inp, const int16_t len, const float inp_min, const float inp_max ); - +#endif /*-------------------------------------------------------------------* * Function select_stereo_mode() @@ -94,6 +106,179 @@ static float redge_detect( const float *inp, const int16_t len, const float inp_ *-------------------------------------------------------------------*/ /*! r: element mode */ +#ifdef IVAS_FLOAT_FIXED +Word16 select_stereo_mode( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const IVAS_FORMAT ivas_format /* i : IVAS format */ +) +{ + Word16 element_mode; + STEREO_CLASSIF_HANDLE hStereoClassif; + Word16 is_speech; + Word16 stereo_switching_flag; + + /* initialization */ + element_mode = hCPE->element_mode; + hStereoClassif = hCPE->hStereoClassif; + + /* set binary flag to prevent LRTD mode on music */ + hStereoClassif->is_speech_fx = L_add( Mpy_32_32( hStereoClassif->is_speech_fx, 2083059139 ), Mpy_32_16_1( 64424509, hCPE->hCoreCoder[0]->hSpMusClas->past_dlp_fx[0] ) ); /* (((Q25*Q31) << 1) >> 32) -> Q25 + (((Q31*Q9) << 1) >> 16) -> Q25*/ + move32(); + is_speech = ( LT_32( hStereoClassif->is_speech_fx, ONE_IN_Q25 ) && hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk_fx < 0 ); + move16(); + + /* set binary flag indicating LRTD mode based on unclr/xtalk classifiers' decisions */ + hStereoClassif->prev_lrtd_mode = hStereoClassif->lrtd_mode; + move16(); + hStereoClassif->unclr_decision = ( hStereoClassif->unclr_decision && hCPE->hCoreCoder[0]->flag_noisy_speech_snr == 0 && GT_32( hCPE->element_brate, IVAS_16k4 ) ); + move16(); + hStereoClassif->lrtd_mode = ( ( hStereoClassif->unclr_decision | hStereoClassif->xtalk_decision ) && is_speech ); + move16(); + + stereo_switching_flag = 1; + move16(); + + test(); + test(); + IF( GE_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) || ( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( hCPE->element_brate, MASA_STEREO_MIN_BITRATE ) ) ) + { + stereo_switching_flag = 0; + move16(); + } + test(); + IF( GE_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) ) + { + hStereoClassif->prev_lrtd_mode = 0; + move16(); + hStereoClassif->lrtd_mode = 0; + move16(); + element_mode = IVAS_CPE_MDCT; + move16(); + } + ELSE IF( LT_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) ) + { + hStereoClassif->lrtd_mode = 0; + move16(); + element_mode = IVAS_CPE_DFT; + move16(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16( stereo_switching_flag, 1 ) && GT_32( hCPE->element_brate, IVAS_13k2 ) && LT_16( hCPE->hCoreCoder[0]->hSpMusClas->past_dlp_fx[0], ONE_IN_Q9 ) && LT_32( hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk_fx, -5243 /* -0.01 in Q19*/ ) && EQ_16( hCPE->hCoreCoder[0]->vad_flag, 1 ) && ( hCPE->hStereoMdct->sw_uncorr || hStereoClassif->xtalk_decision ) ) + { + hStereoClassif->lrtd_mode = 1; + move16(); + element_mode = IVAS_CPE_TD; + move16(); + } + } + + /* set the element mode */ + test(); + IF( EQ_16( hStereoClassif->lrtd_mode, 1 ) && EQ_16( stereo_switching_flag, 1 ) ) + { + element_mode = IVAS_CPE_TD; + move16(); + } + ELSE IF( LT_16( element_mode, IVAS_CPE_MDCT ) ) + { + IF( EQ_16( stereo_switching_flag, 0 ) ) + { + test(); + test(); + IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( hCPE->element_brate, MASA_STEREO_MIN_BITRATE ) ) + { + element_mode = IVAS_CPE_DFT; + move16(); + } + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + test(); + IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec > 0 && is_speech ) + { + /* if unclr_decision goes from 1->0 on active content, continue in LRTD mode */ + hStereoClassif->lrtd_mode = 1; + move16(); + } + ELSE IF( EQ_16( stereo_switching_flag, 1 ) ) + { + element_mode = IVAS_CPE_DFT; + move16(); + } + } + ELSE IF( EQ_16( stereo_switching_flag, 1 ) ) + { + element_mode = IVAS_CPE_DFT; + move16(); + } + } + + /* switch from LRTD to DFT when xtalk_decision goes from 0->1 (note: this special case is not handled in the xtalk classifier) */ + test(); + test(); + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( hStereoClassif->xtalk_decision, 1 ) ) + { + test(); + test(); + test(); + test(); + test(); + IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 && GT_16( hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt, 15 ) && GT_16( hCPE->hStereoTD->tdm_last_LRTD_frame_cnt, 3 ) && LT_16( hCPE->hCoreCoder[0]->clas, VOICED_CLAS ) && ( GE_32( hCPE->element_brate, IVAS_16k4 ) || LT_32( hStereoClassif->xtalk_wscore_fx, 21474836 /*0.01f in Q31*/ ) ) ) + { + IF( EQ_16( stereo_switching_flag, 1 ) ) + { + element_mode = IVAS_CPE_DFT; + move16(); + } + hStereoClassif->xtalk_decision = 0; + move16(); + hStereoClassif->lrtd_mode = 0; + move16(); + } + } + + IF( NE_16( hCPE->last_element_mode, element_mode ) ) + { + test(); + IF( NE_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) + { + Word16 lrtd_mode = hStereoClassif->lrtd_mode; + move16(); + + /* reset stereo classifier when switching from MDCT stereo to Unified stereo */ + stereo_classifier_init( hCPE->hStereoClassif ); +#ifdef IVAS_FLOAT_FIXED + stereo_classifier_init_fx( hCPE->hStereoClassif ); +#endif + hStereoClassif->lrtd_mode = lrtd_mode; + move16(); + } + ELSE + { + /* reset UNCLR classifier parameters */ + set32_fx( hStereoClassif->unclr_fv_fx, -MAX_16, SSC_MAX_NFEA ); + hStereoClassif->unclr_corrLagMax_prev = 0; + move16(); + + /* reset xtalk classifier parameters */ + set32_fx( hStereoClassif->xtalk_fv_fx, -MAX_16, SSC_MAX_NFEA ); + } + } + test(); + IF( EQ_16( element_mode, IVAS_CPE_TD ) && hCPE->hCoreCoder[0]->Opt_DTX_ON ) + { + hCPE->hStereoCng->td_active = 1; + move16(); + hCPE->hStereoCng->first_SID_after_TD = 1; + move16(); + } + + return ( element_mode ); +} +#else int16_t select_stereo_mode( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const IVAS_FORMAT ivas_format /* i : IVAS format */ @@ -221,7 +406,7 @@ int16_t select_stereo_mode( return ( element_mode ); } - +#endif /*-------------------------------------------------------------------* * Function stereo_classifier_init() @@ -236,6 +421,7 @@ void stereo_classifier_init( /* initialization of features for xtalk classifier and UNCLR classifier */ hStereoClassif->clas_ch1 = 0; set_s( hStereoClassif->pitch_ch1, 0, 3 ); +#ifndef IVAS_FLOAT_FIXED set_f( hStereoClassif->voicing_ch1, 0.0f, 3 ); hStereoClassif->cor_map_sum_ch1 = 0.0f; set_f( hStereoClassif->lsf_ch1, 0.0f, M ); @@ -246,52 +432,53 @@ void stereo_classifier_init( hStereoClassif->nchar_ch2 = 0.0f; hStereoClassif->non_sta_ch1 = 0.0f; hStereoClassif->sp_div_ch1 = 0.0f; - -#ifdef IVAS_FLOAT_FIXED - hStereoClassif->ps_diff_ch1_fx = 0; - hStereoClassif->ps_diff_ch2_fx = 0; - hStereoClassif->ps_sta_ch1_fx = 0; - hStereoClassif->ps_sta_ch2_fx = 0; -#endif hStereoClassif->ps_diff_ch1 = 0.0f; - + hStereoClassif->ps_diff_ch2 = 0.0f; hStereoClassif->ps_sta_ch1 = 0.0f; hStereoClassif->ps_sta_ch2 = 0.0f; hStereoClassif->prev_g_IPD = 0.5f; hStereoClassif->prev_IPD = 0.0f; hStereoClassif->prev_ratio_m1_m2 = 0.0f; +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hStereoClassif->xtalk_score_buf, 0.0f, XTALK_SCORE_BUF_LEN ); hStereoClassif->ratio_L = 0.5f; +#endif hStereoClassif->vad_flag_glob = 0; hStereoClassif->vad_relE = 0; - hStereoClassif->is_speech = 0.0f; set_s( hStereoClassif->aEn_raw, 0, CPE_CHANNELS ); - +#ifndef IVAS_FLOAT_FIXED + hStereoClassif->is_speech = 0.0f; hStereoClassif->Etot_dn = 0.0f; hStereoClassif->Etot_up = 0.0f; - set_f( hStereoClassif->relE_buf, 0.0f, UNCLR_L_RELE ); set_f( hStereoClassif->Etot_buf, 0.0f, UNCLR_L_ETOT ); +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hStereoClassif->unclr_relE_0_1_LT, 0.0f, UNCLR_RC_ORDER ); - +#endif hStereoClassif->unclr_sw_enable_cnt[0] = 0; hStereoClassif->unclr_sw_enable_cnt[1] = 0; hStereoClassif->unclr_decision = 0; +#ifndef IVAS_FLOAT_FIXED hStereoClassif->unclr_wscore = 0.0f; - set_f( hStereoClassif->unclr_fv, -1.0f, SSC_MAX_NFEA ); +#endif hStereoClassif->unclr_corrLagMax_prev = 0; +#ifndef IVAS_FLOAT_FIXED hStereoClassif->ave_ener_L = 0; hStereoClassif->ave_ener_R = 0; hStereoClassif->relE_0_1 = 0.01f; hStereoClassif->relE_0_1_LT = 0.01f; - +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hStereoClassif->xtalk_fv, -1.0f, SSC_MAX_NFEA ); hStereoClassif->xtalk_wscore = 0.0f; - hStereoClassif->xtalk_decision = 0; hStereoClassif->xtalk_score_wrelE = 0.0f; +#endif + hStereoClassif->xtalk_decision = 0; hStereoClassif->lrtd_mode = 0; hStereoClassif->prev_lrtd_mode = 0; @@ -310,6 +497,8 @@ void stereo_classifier_init_fx( move16(); set16_fx( hStereoClassif->pitch_ch1, 0, 3 ); set_zero_fx( hStereoClassif->voicing_ch1_fx, 3 ); + hStereoClassif->voicing_ch1_e = 0; + move16(); hStereoClassif->cor_map_sum_ch1_fx = 0; move32(); set_zero_fx( hStereoClassif->lsf_ch1_fx, M ); @@ -317,24 +506,44 @@ void stereo_classifier_init_fx( move32(); hStereoClassif->dE1_ch1_fx = 0; move32(); + hStereoClassif->dE1_ch1_e = 0; + move16(); hStereoClassif->dE1_ch2_fx = 0; move32(); + hStereoClassif->dE1_ch2_e = 0; + move16(); hStereoClassif->nchar_ch1_fx = 0; move32(); + hStereoClassif->nchar_ch1_e = 0; + move16(); hStereoClassif->nchar_ch2_fx = 0; move32(); + hStereoClassif->nchar_ch2_e = 0; + move16(); hStereoClassif->non_sta_ch1_fx = 0; move32(); + hStereoClassif->non_sta_ch1_e = 0; + move16(); hStereoClassif->sp_div_ch1_fx = 0; move32(); + hStereoClassif->sp_div_ch1_e = 0; + move16(); hStereoClassif->ps_diff_ch1_fx = 0; move32(); + hStereoClassif->ps_diff_ch1_e = 0; + move16(); hStereoClassif->ps_diff_ch2_fx = 0; move32(); + hStereoClassif->ps_diff_ch2_e = 0; + move16(); hStereoClassif->ps_sta_ch1_fx = 0; move32(); + hStereoClassif->ps_sta_ch1_e = 0; + move16(); hStereoClassif->ps_sta_ch2_fx = 0; move32(); + hStereoClassif->ps_sta_ch2_e = 0; + move16(); hStereoClassif->prev_g_IPD_fx = ONE_IN_Q28; // 0.5f in Q29 move32(); hStereoClassif->prev_IPD_fx = 0; @@ -344,6 +553,8 @@ void stereo_classifier_init_fx( set_zero_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN ); hStereoClassif->ratio_L_fx = 1073741824; // Q31 move32(); + hStereoClassif->ratio_L_e = 0; // Q31 + move16(); hStereoClassif->vad_flag_glob = 0; move16(); hStereoClassif->vad_relE = 0; @@ -355,11 +566,19 @@ void stereo_classifier_init_fx( hStereoClassif->Etot_dn_fx = 0; move32(); + hStereoClassif->Etot_dn_e = 0; + move16(); hStereoClassif->Etot_up_fx = 0; move32(); + hStereoClassif->Etot_up_e = 0; + move16(); set_zero_fx( hStereoClassif->relE_buf_fx, UNCLR_L_RELE ); + hStereoClassif->relE_buf_e = 0; + move16(); set_zero_fx( hStereoClassif->Etot_buf_fx, UNCLR_L_ETOT ); + hStereoClassif->e_Etot_buf_fx = 0; + move16(); set_zero_fx( hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER ); hStereoClassif->unclr_sw_enable_cnt[0] = 0; @@ -412,7 +631,415 @@ void stereo_classifier_init_fx( * * Collect features for stereo classifiers *-----------------------------------------------------------------*/ +/* Information on ouputs: +hStereoClassif->Etot_buf_fx has expoenent hStereoClassif->e_Etot_buf_fx +hStereoClassif->relE_buf_fx has expoenent hStereoClassif->relE_buf_e +hStereoClassif->lsf_ch1_fx has exponent 16 +hStereoClassif->xtalk_fv_fx has exponent 16 +hStereoClassif->voicing_ch1_fx has exponent hStereoClassif->voicing_ch1_e +hStereoClassif->lepsP_ch1_fx has exponent 16 +hStereoClassif->Etot_up_fx has exponent hStereoClassif->Etot_up_e +hStereoClassif->Etot_dn_fx has exponent hStereoClassif->Etot_dn_e +hStereoClassif->relE_0_1_fx has exponent hStereoClassif->relE_buf_e +hStereoClassif->relE_0_1_LT_fx has exponent hStereoClassif->relE_buf_e +hStereoClassif->cor_map_sum_ch1_fx has exponent hStereoClassif->cor_map_sum_ch1_e +hStereoClassif->non_sta_ch1_fx has exponent hStereoClassif->non_sta_ch1_e +hStereoClassif->sp_div_ch1_fx has exponent hStereoClassif->sp_div_ch1_e +hStereoClassif->nchar_ch1_fx has exponent hStereoClassif->nchar_ch1_e +hStereoClassif->nchar_ch2_fx has exponent hStereoClassif->nchar_ch2_e +hStereoClassif->dE1_ch1_fx has exponent hStereoClassif->dE1_ch1_e +hStereoClassif->dE1_ch2_fx has exponent hStereoClassif->dE1_ch2_e +hStereoClassif->ps_diff_ch1_fx has exponent hStereoClassif->ps_diff_ch1_e +hStereoClassif->ps_sta_ch1_fx has exponent hStereoClassif->ps_sta_ch1_e +hStereoClassif->ps_diff_ch2_fx has exponent hStereoClassif->ps_diff_ch2_e +hStereoClassif->ps_sta_ch2_fx has exponent hStereoClassif->ps_sta_ch2_e +*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_classifier_features_ivas_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 idchan, /* i : channel ID */ + const Word16 element_mode, /* i : element mode */ + const Word16 vad_flag, /* i : VAD flag */ + Word32 lsf_new_fx[], /* i : LSFs at the end of the frame */ + Word32 epsP_fx[], /* i : LP analysis residual energies for each iteration*/ + Word16 pitch[], /*q0 i : open-loop pitch values for quantiz. */ + Word16 voicing_fx[], /* i : OL maximum normalized correlation */ + Word32 cor_map_sum_fx, /* i : speech/music clasif. parameter */ + Word32 non_staX_fx, /* i : unbound non-stationarity for sp/mu clas. */ + Word32 sp_div_fx, /* i : spectral diversity feature */ + const Word16 clas, /* i : signal class */ + Word16 epsP_e, /*exponent for epsP_fx */ + Word16 voicing_e, /*exponent for voicing_fx */ + Word16 cor_map_sum_e, /*exponent for cor_map_sum_fx */ + Word16 non_staX_e, /*exponent for non_staX_fx */ + Word16 sp_div_e /*exponent for sp_div_fx */ +) +{ + Word16 i, clas_ch2; + Word16 e_relE_0_1_fx; + Word16 ener_e; + + Word32 lepsP_ch2_fx, ener_l_fx, ener_r_fx; + /* combine VAD flags from both channels */ + IF( idchan == 0 ) + { + hStereoClassif->vad_flag_glob = vad_flag; + } + ELSE + { + hStereoClassif->vad_flag_glob = s_or( hStereoClassif->vad_flag_glob, vad_flag ); + } + move16(); + + test(); + test(); + test(); + IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && idchan == 0 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( idchan, 1 ) ) ) + { + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->ave_ener_L_fx_e < 0 ) + { + hStereoClassif->ave_ener_L_fx = L_shl( hStereoClassif->ave_ener_L_fx, hStereoClassif->ave_ener_L_fx_e ); + hStereoClassif->ave_ener_L_fx_e = 0; + } + IF( hStereoClassif->ave_ener_R_fx_e < 0 ) + { + hStereoClassif->ave_ener_R_fx = L_shl( hStereoClassif->ave_ener_R_fx, hStereoClassif->ave_ener_R_fx_e ); + hStereoClassif->ave_ener_R_fx_e = 0; + } + move32(); + move16(); + /* update Etot_up and Etot_dn based on aEn */ + ener_l_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_L_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_L_fx_e ) ), hStereoClassif->ave_ener_L_fx_e + 1 ), 10 << 11 ); /*q21*/ + ener_r_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_R_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_R_fx_e ) ), hStereoClassif->ave_ener_R_fx_e + 1 ), 10 << 11 ); /*q21*/ + ener_e = 10; + move16(); + Copy32( &hStereoClassif->Etot_buf_fx[0], &hStereoClassif->Etot_buf_fx[1], UNCLR_L_ETOT - 1 ); + IF( GE_16( hStereoClassif->e_Etot_buf_fx, ener_e ) ) + { + hStereoClassif->Etot_buf_fx[0] = L_shl( L_max( 0, L_max( ener_l_fx, ener_r_fx ) ), sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); /*scaling from q25 to 31-e_Etot_buf_fx*/ + move32(); + } + ELSE + { + /*scaling Etot_buf_fx,Etot_up_fx and Etot_dn_fx to exponent ener_e*/ + hStereoClassif->Etot_buf_fx[0] = L_max( 0, L_max( ener_l_fx, ener_r_fx ) ); + hStereoClassif->Etot_buf_fx[1] = L_shr( hStereoClassif->Etot_buf_fx[1], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_buf_fx[2] = L_shr( hStereoClassif->Etot_buf_fx[2], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_up_fx = L_shr( hStereoClassif->Etot_up_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->e_Etot_buf_fx = ener_e; + move32(); + move32(); + move32(); + move32(); + move32(); + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16( hStereoClassif->aEn_raw[0], 6 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( hStereoClassif->aEn_raw[1], 6 ) ) ) + { + /* active signal, update upper bound */ + IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_up_fx ) ) + { + /* energy decreases -> slower update */ + hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, /*0.99f Q15*/ 32440 ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 328 /*0.01f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + ELSE + { + /* energy increases -> faster update */ + hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + move32(); + } + ELSE IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && hStereoClassif->aEn_raw[0] == 0 ) || + ( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif->aEn_raw[0] == 0 && hStereoClassif->aEn_raw[1] == 0 ) ) + { + /* inactive signal, update lower bound */ + IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx ) ) + { + /* energy decreases -> faster update */ + hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 29491 /*0.9f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 3277 /*0.1f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + ELSE + { + /* energy increases -> slower update */ + hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + move32(); + + IF( LT_32( hStereoClassif->Etot_dn_fx, L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) ) ) + { + /* do not decrease below lower bound threshold */ + hStereoClassif->Etot_dn_fx = L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) ); + move32(); + } + } + + /* upper bound is too low and close to lower bound -> update it */ + IF( LT_32( L_shr( hStereoClassif->Etot_up_fx, 1 ), L_add( L_shr( hStereoClassif->Etot_dn_fx, 1 ), L_shl( 20, sub( 30, hStereoClassif->e_Etot_buf_fx ) ) ) ) ) /*right shifted by 1 to avoid avoid overflow in addition*/ + { + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, 1 ); + scale_sig32( hStereoClassif->Etot_buf_fx, 3, -1 ); + hStereoClassif->e_Etot_buf_fx = add( hStereoClassif->e_Etot_buf_fx, 1 ); + hStereoClassif->Etot_up_fx = L_add( hStereoClassif->Etot_dn_fx, L_shl( 20, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) ); + move32(); + move32(); + move16(); + } + + /* normalize Etot to (0,1) */ + e_relE_0_1_fx = sub( 31, hStereoClassif->e_Etot_buf_fx ); + hStereoClassif->relE_0_1_fx = lin_interp32_fx( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx, 0, hStereoClassif->Etot_up_fx, L_shr( 1932735283, hStereoClassif->e_Etot_buf_fx /*0.9f exp:Etot_buf_fx*/ ), 1, &e_relE_0_1_fx ); /*e_relE_0_1_fx is ouput exp*/ + e_relE_0_1_fx = sub( 31, e_relE_0_1_fx ); + move32(); + + /* update relE_buf */ + Copy32( &hStereoClassif->relE_buf_fx[0], &hStereoClassif->relE_buf_fx[1], UNCLR_L_RELE - 1 ); + hStereoClassif->relE_0_1_fx = L_shr( hStereoClassif->relE_0_1_fx, sub( hStereoClassif->relE_buf_e, e_relE_0_1_fx ) ); /*scaling down to exponent of e_relE_buf_fx*/ + hStereoClassif->relE_buf_fx[0] = hStereoClassif->relE_0_1_fx; /*scaling down to exponent of e_relE_buf_fx*/ + move32(); + move32(); + + IF( GE_32( hStereoClassif->relE_0_1_fx, hStereoClassif->relE_buf_fx[1] ) ) + { + hStereoClassif->relE_0_1_LT_fx = Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 29491 /*0.9f q15*/ ) + Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 3277 /*0.1f q15*/ ); + } + ELSE + { + hStereoClassif->relE_0_1_LT_fx = Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 31129 /*0.95f q15*/ ) + Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 1638 /*0.05f0 q15*/ ); + } + move32(); + + /* estimate VAD flag based on relative energy */ + IF( LT_32( hStereoClassif->relE_0_1_LT_fx, L_shr( 214748365, hStereoClassif->relE_buf_e ) ) ) + { + hStereoClassif->vad_relE = 0; + } + ELSE + { + hStereoClassif->vad_relE = 1; + } + move16(); + /* combine classical VAD flag with VAD flag based on relative energy */ + hStereoClassif->vad_flag_glob = s_and( hStereoClassif->vad_flag_glob, hStereoClassif->vad_relE ); + move16(); + } + + IF( idchan == 0 ) + { + Copy32( lsf_new_fx, hStereoClassif->lsf_ch1_fx, M ); + hStereoClassif->lepsP_ch1_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/ + move32(); + move16(); + + hStereoClassif->xtalk_fv_fx[E_lsf_1] = lsf_new_fx[0]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_4] = lsf_new_fx[3]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_9] = lsf_new_fx[8]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_14] = lsf_new_fx[13]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lepsP_13] = hStereoClassif->lepsP_ch1_fx; /*q15*/ + move32(); + move32(); + move32(); + move32(); + move32(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0; + move32(); + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->ratio_L_e < 0 ) + { + hStereoClassif->ratio_L_fx = L_shl( hStereoClassif->ratio_L_fx, hStereoClassif->ratio_L_e ); + hStereoClassif->ratio_L_e = 0; + move32(); + move16(); + } + FOR( i = 0; i < M; i++ ) + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = L_add( hStereoClassif->xtalk_fv_fx[E_sum_d_LSF], L_abs( L_sub( lsf_new_fx[i], hStereoClassif->lsf_ch1_fx[i] ) ) ); /*q15*/ + move32(); + } + + test(); + test(); + IF( hStereoClassif->vad_flag_glob && ( hStereoClassif->ratio_L_fx > 0 && LT_32( L_shr( hStereoClassif->ratio_L_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->ratio_L_e ) ) ) ) ) + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0; + move32(); + } + lepsP_ch2_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_lepsP_13] = L_abs( L_sub( hStereoClassif->lepsP_ch1_fx, lepsP_ch2_fx ) ); /*q15*/ + move32(); + } + + IF( idchan == 0 ) + { + Copy( pitch, hStereoClassif->pitch_ch1, 3 ); + Copy_Scale_sig_16_32_no_sat( voicing_fx, hStereoClassif->voicing_ch1_fx, 3, 16 ); + hStereoClassif->voicing_ch1_e = voicing_e; + move16(); + + hStereoClassif->xtalk_fv_fx[E_pitch] = Mult_32_16( L_shl( add( pitch[0], add( pitch[1], pitch[2] ) ), 15 ), 10923 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_voicing] = Mult_32_16( L_add( voicing_fx[0], L_add( voicing_fx[1], voicing_fx[2] ) ), 10923 ); /*q15*/ + move32(); + move32(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_pitch] = 0; + hStereoClassif->xtalk_fv_fx[E_d_voicing] = 0; + FOR( i = 0; i < 3; i++ ) + { + hStereoClassif->xtalk_fv_fx[E_d_pitch] = L_add( hStereoClassif->xtalk_fv_fx[E_d_pitch], L_shl( abs_s( sub( pitch[i], hStereoClassif->pitch_ch1[i] ) ), Q15 ) ); + hStereoClassif->xtalk_fv_fx[E_d_voicing] = L_add( hStereoClassif->xtalk_fv_fx[E_d_voicing], L_abs( L_sub( L_shl( voicing_fx[i], voicing_e ), L_shr( hStereoClassif->voicing_ch1_fx[i], sub( 16, hStereoClassif->voicing_ch1_e ) ) ) ) ); + move32(); + move32(); + } + hStereoClassif->xtalk_fv_fx[E_d_pitch] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_pitch], 10923 /*1/3 q15*/ ); + hStereoClassif->xtalk_fv_fx[E_d_voicing] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_voicing], 10923 /*1/3 q15*/ ); + move32(); + move32(); + move32(); + move32(); + } + + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->nchar_ch1_e < 0 ) + { + hStereoClassif->nchar_ch1_fx = L_shl( hStereoClassif->nchar_ch1_fx, hStereoClassif->nchar_ch1_e ); + hStereoClassif->nchar_ch1_e = 0; + } + IF( hStereoClassif->nchar_ch2_e < 0 ) + { + hStereoClassif->nchar_ch2_fx = L_shl( hStereoClassif->nchar_ch2_fx, hStereoClassif->nchar_ch2_e ); + hStereoClassif->nchar_ch2_e = 0; + } + move32(); + move16(); + IF( idchan == 0 ) + { + hStereoClassif->cor_map_sum_ch1_fx = cor_map_sum_fx; + hStereoClassif->cor_map_sum_ch1_e = cor_map_sum_e; + hStereoClassif->non_sta_ch1_fx = non_staX_fx; + hStereoClassif->non_sta_ch1_e = non_staX_e; + hStereoClassif->sp_div_ch1_fx = sp_div_fx; + hStereoClassif->sp_div_ch1_e = sp_div_e; + hStereoClassif->xtalk_fv_fx[E_cor_map_sum] = L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_nchar] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ) /*q25*/, 10 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_non_sta] = L_shr( non_staX_fx, sub( 16, non_staX_e ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_sp_div] = L_shr( BASOP_Util_Loge( L_add( L_shr( sp_div_fx, 1 ), L_shl( 1, sub( 31, add( sp_div_e, 1 ) ) ) ), add( sp_div_e, 1 ) ), 10 ); /*q15*/ + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move16(); + move16(); + move16(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_cor_map_sum] = L_abs( L_sub( L_shr( hStereoClassif->cor_map_sum_ch1_fx, sub( 16, hStereoClassif->cor_map_sum_ch1_e ) ) /*q15*/, L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_nchar] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ), BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch2_e ) ) ), add( hStereoClassif->nchar_ch2_e, 1 ) ) ) /*q25*/, 10 ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_non_sta] = L_abs( L_sub( L_shr( hStereoClassif->non_sta_ch1_fx, sub( 16, hStereoClassif->non_sta_ch1_e ) ) /*q15*/, L_shr( non_staX_fx, sub( 16, non_staX_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_sp_div] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->sp_div_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->sp_div_ch1_e ) ) ), add( hStereoClassif->sp_div_ch1_e, 1 ) ), BASOP_Util_Loge( L_add( L_shr( sp_div_fx, 1 ), L_shl( 1, sub( 30, sp_div_e ) ) ), add( sp_div_e, 1 ) ) ) /*q25*/, 10 ) ); /*q15*/ + move32(); + move32(); + move32(); + move32(); + } + + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->dE1_ch1_e < 0 ) + { + hStereoClassif->dE1_ch1_fx = L_shl( hStereoClassif->dE1_ch1_fx, hStereoClassif->dE1_ch1_e ); + hStereoClassif->dE1_ch1_e = 0; + } + IF( hStereoClassif->dE1_ch2_e < 0 ) + { + hStereoClassif->dE1_ch2_fx = L_shl( hStereoClassif->dE1_ch2_fx, hStereoClassif->dE1_ch2_e ); + hStereoClassif->dE1_ch2_e = 0; + } + move32(); + move16(); + + IF( idchan == 0 ) + { + hStereoClassif->xtalk_fv_fx[E_dE1] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), hStereoClassif->dE1_ch1_e + 1 ) /*q25*/, 10 ); /*q15*/ + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_dE1] = L_shr( L_abs( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ) /*right shifting to avoid overflow*/, L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), add( hStereoClassif->dE1_ch1_e, 1 ) ) /*q25*/, BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch2_e ) ) ), add( hStereoClassif->dE1_ch2_e, 1 ) ) /*q25*/ ) ), 10 ); /*right shifting the ouput of log by 10 to bring value to q15*/ + } + move32(); + + IF( idchan == 0 ) + { + IF( GT_16( clas, VOICED_CLAS ) ) + { + hStereoClassif->clas_ch1 = VOICED_CLAS; /*q0*/ + } + ELSE IF( LT_16( clas, VOICED_CLAS ) ) + { + hStereoClassif->clas_ch1 = UNVOICED_CLAS; + } + ELSE + { + hStereoClassif->clas_ch1 = clas; + } + move16(); + + hStereoClassif->xtalk_fv_fx[E_clas] = L_shl( hStereoClassif->clas_ch1, 15 ); /*q15*/ + } + ELSE + { + IF( GT_16( clas, VOICED_CLAS ) ) + { + clas_ch2 = VOICED_CLAS; + } + ELSE IF( LT_16( clas, VOICED_CLAS ) ) + { + clas_ch2 = UNVOICED_CLAS; + } + ELSE + { + clas_ch2 = clas; + } + move16(); + + hStereoClassif->xtalk_fv_fx[E_d_clas] = L_shl( L_abs( sub( hStereoClassif->clas_ch1 /*q0*/, clas_ch2 /*q0*/ ) ), 15 ); /*q15*/ + } + move32(); + + IF( idchan == 0 ) + { + hStereoClassif->xtalk_fv_fx[E_ps_diff] = L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ); /*scaling to q15*/ + hStereoClassif->xtalk_fv_fx[E_ps_sta] = L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ); /*q15*/ + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_ps_diff] = L_abs( L_sub( L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_diff_ch2_fx, sub( 16, hStereoClassif->ps_diff_ch2_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_ps_sta] = L_abs( L_sub( L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_sta_ch2_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/ ) ); /*q15*/ + } + move32(); + move32(); + hStereoClassif->Etot_dn_e = hStereoClassif->Etot_up_e = hStereoClassif->e_Etot_buf_fx; /*updating the exponents*/ + move16(); + move16(); + return; +} +#else void stereo_classifier_features( STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ const int16_t idchan, /* i : channel ID */ @@ -629,30 +1256,115 @@ void stereo_classifier_features( clas_ch2 = clas; } - hStereoClassif->xtalk_fv[E_d_clas] = (float) abs( hStereoClassif->clas_ch1 - clas_ch2 ); + hStereoClassif->xtalk_fv[E_d_clas] = (float) abs( hStereoClassif->clas_ch1 - clas_ch2 ); + } + + if ( idchan == 0 ) + { + hStereoClassif->xtalk_fv[E_ps_diff] = hStereoClassif->ps_diff_ch1; + hStereoClassif->xtalk_fv[E_ps_sta] = hStereoClassif->ps_sta_ch1; + } + else + { + hStereoClassif->xtalk_fv[E_d_ps_diff] = fabsf( hStereoClassif->ps_diff_ch1 - hStereoClassif->ps_diff_ch2 ); + hStereoClassif->xtalk_fv[E_d_ps_sta] = fabsf( hStereoClassif->ps_sta_ch1 - hStereoClassif->ps_sta_ch2 ); + } + + return; +} +#endif + +/*-------------------------------------------------------------------* + * Function unclr_classifier_td() + * + * Classify current TD frame as uncorrelated L/R (1) or normal (0) + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void unclr_classifier_td_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +) +{ + Word16 i, ind, exp; + Word32 relE_ST, score, fvn; + Word16 edge, edge_0_1, score_exp; + STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif; + + /* calcualte raw score based on LR */ + exp = 0; + move16(); + score = UNCLR_INTERCEPT_TD_Q28; + move32(); + score_exp = 3; + move16(); + FOR( i = 0; i < SIZE_UNCLR_ISEL_TD; i++ ) + { + ind = unclr_isel_td[i]; + move16(); + + /* mean & std removal */ + fvn = BASOP_Util_Divide3232_Scale_cadence( L_sub( hStereoClassif->unclr_fv_fx[ind], unclr_mean_td[i] ), unclr_scale_td[i], &exp ); + fvn = Mpy_32_32( fvn, unclr_coef_td[i] ); // Q = 31-exp+15-31 = 15-exp + exp = add( exp, 16 ); // exp = 31-(15-exp) = 16+exp + + /* LR */ + score = BASOP_Util_Add_Mant32Exp( score, score_exp, fvn, exp, &score_exp ); } - if ( idchan == 0 ) + score = L_shl_sat( score, sub( score_exp, 3 ) ); // Q28 + + + /* normalize score to -1:+1 */ + IF( GT_32( score, UNCLR_SCORE_THR_Q28 ) ) { - hStereoClassif->xtalk_fv[E_ps_diff] = hStereoClassif->ps_diff_ch1; - hStereoClassif->xtalk_fv[E_ps_sta] = hStereoClassif->ps_sta_ch1; + score = UNCLR_SCORE_THR_Q28; + move32(); } - else + ELSE IF( LT_32( score, -UNCLR_SCORE_THR_Q28 ) ) { - hStereoClassif->xtalk_fv[E_d_ps_diff] = fabsf( hStereoClassif->ps_diff_ch1 - hStereoClassif->ps_diff_ch2 ); - hStereoClassif->xtalk_fv[E_d_ps_sta] = fabsf( hStereoClassif->ps_sta_ch1 - hStereoClassif->ps_sta_ch2 ); + score = -UNCLR_SCORE_THR_Q28; + move32(); } + /*score /= 2 * UNCLR_SCORE_THR; = score = score / 8 + score Q will be 31 to account the above operation*/ - return; -} + /* weight raw score with relative energy */ + score = Mpy_32_32( score, hStereoClassif->relE_0_1_fx ); // Q31 + /* rising edge detection on relE */ + relE_ST = Mean32( hStereoClassif->relE_buf_fx, UNCLR_L_RELE ); // Q31 + IF( hStereoClassif->relE_0_1_fx > relE_ST ) + { + rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_UP_Q31 ); + } + ELSE + { + rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_DOWN_Q31 ); + } -/*-------------------------------------------------------------------* - * Function unclr_classifier_td() - * - * Classify current TD frame as uncorrelated L/R (1) or normal (0) - *-------------------------------------------------------------------*/ + edge = extract_h( L_sub( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER - 1] ) ); // Q15 + edge_0_1 = lin_interp_ivas_fx( edge, 0, 31129 /*0.95 in Q15*/, MAX_16, 29491 /*0.9 in Q15f*/, 1 ); // Q15 + + /* LT average */ + hStereoClassif->unclr_wscore_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->unclr_wscore_fx, edge_0_1 ), score, sub( MAX_16, edge_0_1 ) ); // Q31 + move32(); + + /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */ + test(); + test(); + test(); + test(); + test(); + if ( ( ( hStereoClassif->unclr_decision == 0 && GT_32( hStereoClassif->unclr_wscore_fx, 214748365 /*0.1f in Q31*/ ) ) || ( EQ_16( hStereoClassif->unclr_decision, 1 ) && LT_32( hStereoClassif->unclr_wscore_fx, 150323855 /*-0.07f in Q31*/ ) ) ) && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 || hStereoClassif->unclr_sw_enable_cnt[1] > 0 ) ) + { + /* let's switch the binary decision */ + hStereoClassif->unclr_decision = !hStereoClassif->unclr_decision; + move16(); + } + + return; +} +#else void unclr_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ) @@ -719,7 +1431,7 @@ void unclr_classifier_td( return; } - +#endif /*-------------------------------------------------------------------* * Function unclr_classifier_dft() @@ -900,7 +1612,149 @@ void unclr_classifier_dft( * * Classify current TD frame as cross-talk frame (1) or normal stereo frame (0) *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void xtalk_classifier_td_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +) +{ + Word16 i, ind, edge_type, exp, score_exp; + Word32 score, fvn, scr_min, scr_max; + Word16 edge, edge_0_1, wedge, wrelE; + + STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif; + + /* calcualte raw score based on LR */ + exp = 0; + move16(); + score = XTALK_INTERCEPT_TD_Q28; + move32(); + score_exp = 3; + move16(); + FOR( i = 0; i < SIZE_XTALK_ISEL_TD; i++ ) + { + ind = xtalk_isel_td[i]; + move16(); + + /* mean & std removal */ + fvn = BASOP_Util_Divide3232_Scale_cadence( L_sub( hStereoClassif->xtalk_fv_fx[ind], xtalk_mean_td[i] ), xtalk_scale_td[i], &exp ); + fvn = Mpy_32_32( fvn, xtalk_coef_td[i] ); // Q = 31-exp+15-31 = 15-exp + exp = add( exp, 16 ); // exp = 31-(15-exp) = 16+exp + + /* LR */ + score = BASOP_Util_Add_Mant32Exp( score, score_exp, fvn, exp, &score_exp ); + } + + score = L_shl_sat( score, sub( score_exp, 3 ) ); // Q28 + + /* normalize raw score to -1:+1 */ + IF( GT_32( score, XTALK_SCORE_THR_TD_UP_Q28 ) ) + { + score = MAX_32; // Q31 + move32(); + } + ELSE IF( LT_32( score, -XTALK_SCORE_THR_TD_DN_Q28 ) ) + { + score = MIN_32; // Q31 + move32(); + } + ELSE IF( score > 0 ) + { + score = Mpy_32_32( score, ONE_BY_XTALK_SCORE_THR_TD_UP_Q31 ); // Q = 31-score_exp + score = L_shl( score, 3 ); // Q31 + } + ELSE + { + score = Mpy_32_32( score, ONE_BY_XTALK_SCORE_THR_TD_DN_Q31 ); // Q = 31-score_exp + score = L_shl( score, 3 ); // Q31 + } + + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + /* overwrite score if we have just switched from DFT stereo */ + score = hStereoClassif->xtalk_score_fx; // Q31 + move32(); + } + ELSE + { + hStereoClassif->xtalk_score_fx = score; // Q31 + move32(); + } + + if ( !hStereoClassif->vad_flag_glob ) + { + /* reset score to 0 in inactive segments */ + score = 0; + move32(); + } + + + /* weight raw score with relative energy */ + wrelE = lin_interp_ivas_fx( extract_h( hStereoClassif->relE_0_1_fx ), 16384 /*0.5f Q15*/, 31129 /*0.95f Q15*/, 29491 /*0.9f Q15*/, 0, 1 ); + hStereoClassif->xtalk_score_wrelE_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->xtalk_score_wrelE_fx, wrelE ), score, sub( MAX_16, wrelE ) ); // Q31 + move32(); + score = hStereoClassif->xtalk_score_wrelE_fx; // Q31 + move32(); + + /* rising edge detector on raw score -> yields 1 if strong rising edge is detected in the raw score 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; // Q31 + move32(); + + 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(); + test(); + IF( ( scr_min < 0 && GT_32( scr_max, 429496730 /*0.2f in Q31*/ ) ) || GT_32( L_sub_sat( scr_max, scr_min ), 1073741824 /*0.5f Q31*/ ) ) + { + /* test rising edge (use 0 as edge_type because of newer->older buffer samples ordering) */ + edge_type = 0; + move16(); + edge_detect( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, -53687091 /*-0.2f Q28*/, ONE_IN_Q28, &edge, &edge_type ); + + test(); + IF( edge_type == 0 && LT_16( edge, 9830 /*0.3f Q15*/ ) ) + { + /* normalize edge to 0-1 interval */ + edge_0_1 = lin_interp_ivas_fx( sub( MAX_16, edge ), MAX_16, MAX_16, 19661 /*0.6f Q15*/, 0, 1 ); + } + ELSE + { + edge_0_1 = 0; + move16(); + } + } + ELSE + { + edge_0_1 = 0; + move16(); + } + + /* weight raw score based on rising edge detector */ + wedge = lin_interp_ivas_fx( edge_0_1, 0, 29491 /*0.9f Q15*/, MAX_16, 16384 /*0.5f Q15 */, 1 ); + + hStereoClassif->xtalk_wscore_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->xtalk_wscore_fx, wedge ), score, sub( MAX_16, wedge ) ); // Q31 + move32(); + if ( !hStereoClassif->vad_flag_glob ) + { + hStereoClassif->xtalk_wscore_fx = 0; + move16(); + } + + /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */ + test(); + test(); + if ( ( hStereoClassif->unclr_decision == 0 && hStereoClassif->xtalk_decision == 0 && GT_32( hStereoClassif->xtalk_wscore_fx, 64424509 /*0.03f Q31*/ ) ) /*|| (hStereoClassif->xtalk_decision == 1 && hStereoClassif->xtalk_wscore < 0.00f)*/ && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 || hStereoClassif->unclr_sw_enable_cnt[1] > 0 ) ) + { + /* let's switch the binary decision */ + hStereoClassif->xtalk_decision = !hStereoClassif->xtalk_decision; + move16(); + } + + return; +} +#else void xtalk_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ) @@ -1015,7 +1869,7 @@ void xtalk_classifier_td( return; } - +#endif /*-------------------------------------------------------------------* * Function xtalk_classifier_dft() @@ -1248,6 +2102,7 @@ void xtalk_classifier_dft_fx( return; } #endif +#ifndef IVAS_FLOAT_FIXED 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 */ @@ -1396,7 +2251,7 @@ void xtalk_classifier_dft( return; } - +#endif /*-------------------------------------------------------------------* * Function rc_filter() @@ -1422,7 +2277,7 @@ static void rc_filter_fx( return; } -#endif +#else static void rc_filter( const float x, float *y, @@ -1439,7 +2294,7 @@ static void rc_filter( return; } - +#endif /*-------------------------------------------------------------------* * Function edge_detect() @@ -1449,7 +2304,143 @@ static void rc_filter( * Set edge_type to 0/1/2 when calling this function to specify the edge type you want to detect. The returned value will be modified * according to the edge type detected (-1 indicates that no edge has been detected) *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void edge_detect( + const Word32 *inp, /* i : input buffer Q31*/ + const Word16 len, /* i : length of the input buffer Q0*/ + const Word32 inp_min, /* i : minimum value for edge detection Q28*/ + const Word32 inp_max, /* i : maximum value for edge detection Q28*/ + Word16 *edge_str, /* o : edge strength (from 0 to Inf) Q15*/ + Word16 *edge_type /* i/o: edge type (to be) detected: 0 = falling, 1 = rising, 2 = both */ +) +{ + Word16 i, j, et; + Word32 y, err, edge_slope, edge[EDGE_MAX_LEN]; + Word32 edge_min, err0, L_tmp; + + et = -1; + move16(); + edge_min = ONE_IN_Q25; + move32(); + + test(); + IF( *edge_type == 0 || EQ_16( *edge_type, 2 ) ) + { + /* falling edge detection */ + set_zero_fx( edge, EDGE_MAX_LEN ); + + /* set error at 0th index */ + IF( GT_32( L_shr( inp[0], 6 ), inp_max ) ) + { + err0 = 0; + move32(); + } + ELSE + { + /* inhibits edge smearing effect */ + /* err0 = powf( inp[0] - inp_max, 2 ); */ + L_tmp = L_sub( L_shr( inp[0], 3 ), inp_max ); // Q28 + err0 = Mpy_32_32( L_tmp, L_tmp ); // Q25 + } + + /* test edges on intervals from 2 to len */ + FOR( i = 1; i < len; i++ ) + { + IF( EQ_16( i, 1 ) ) + { + edge_slope = L_sub( inp_max, inp_min ); // Q28 + } + ELSE + { + edge_slope = Mpy_32_16_1( L_sub( inp_max, inp_min ), divide1616( 1, i ) ); // Q28 + } + edge[i] = err0; // Q25 + move32(); + FOR( j = 1; j <= i; j++ ) + { + y = L_sub( inp_max, imult3216( edge_slope, j ) ); // Q28 + err = L_sub( y, check_bounds_l( L_shr( inp[j], 3 ), inp_min, inp_max ) ); // Q28 + edge[i] = Madd_32_32( edge[i], err, err ); // Q25 + move32(); + } + + edge[i] = Mpy_32_16_1( edge[i], divide1616( 1, add( i, 1 ) ) ); // Q25 + move32(); + + IF( LT_32( edge[i], edge_min ) ) + { + edge_min = edge[i]; // Q25 + move32(); + et = 0; + move16(); + } + } + } + + test(); + IF( EQ_16( *edge_type, 1 ) || EQ_16( *edge_type, 2 ) ) + { + /* rising edge detection */ + set_zero_fx( edge, EDGE_MAX_LEN ); + + /* set error at 0th index */ + IF( LT_32( L_shr( inp[0], 3 ), inp_min ) ) + { + err0 = 0; + move32(); + } + ELSE + { + /* inhibits edge smearing effect */ + /*err0 = powf( inp[0] - inp_min, 2 );*/ + L_tmp = L_sub( L_shr( inp[0], 3 ), inp_min ); // Q28 + err0 = Mpy_32_32( L_tmp, L_tmp ); // Q25 + } + + /* test edges on intervals from 2 to len */ + FOR( i = 1; i <= len; i++ ) + { + IF( EQ_16( i, 1 ) ) + { + edge_slope = L_sub( inp_max, inp_min ); // Q28 + } + ELSE + { + edge_slope = Mpy_32_16_1( L_sub( inp_max, inp_min ), divide1616( 1, i ) ); // Q28 + } + + edge[i] = err0; // Q25 + move32(); + + FOR( j = 1; j < i; j++ ) + { + y = L_add( inp_min, imult3216( edge_slope, j ) ); // Q28 + err = L_sub( y, check_bounds_l( L_shr( inp[j], 1 ), inp_min, inp_max ) ); // Q28 + edge[i] = Madd_32_32( edge[i], err, err ); // Q25 + move32(); + } + + edge[i] = Mpy_32_16_1( edge[i], divide1616( 1, add( i, 1 ) ) ); // Q25 + move32(); + + IF( LT_32( edge[i], edge_min ) ) + { + edge_min = edge[i]; // Q25 + move32(); + et = 1; + move16(); + } + } + } + + *edge_str = extract_l( L_shr( edge_min, 10 ) ); // Q15 + move16(); + *edge_type = et; // Q0 + move16(); + return; +} +#else static void edge_detect( const float *inp, /* i : input buffer */ const int16_t len, /* i : length of the input buffer */ @@ -1547,7 +2538,7 @@ static void edge_detect( return; } - +#endif /*-------------------------------------------------------------------* * Function redge_detect() @@ -1650,7 +2641,7 @@ static Word32 redge_detect_fx( return edge_min; // Q31 } -#endif +#else /*! r: rising edge strength normalized to 0-1 */ static float redge_detect( const float *inp, /* i : input buffer (ordered from newest to oldest values)*/ @@ -1710,3 +2701,4 @@ static float redge_detect( return edge_min; } +#endif diff --git a/lib_enc/ivas_stereo_cng_enc.c b/lib_enc/ivas_stereo_cng_enc.c index 55247933e347cf31aa3362ec7eb1c0744d7868e6..91799b60aca99cae00dbfa099f9593cd768314ec 100644 --- a/lib_enc/ivas_stereo_cng_enc.c +++ b/lib_enc/ivas_stereo_cng_enc.c @@ -60,7 +60,172 @@ * * Encodes the coherence in SID frames * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_sid_calc_coh_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + Word32 prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence Q31 */ + Word16 *td_active, /* i/o: TD stereo mode indicator */ + Word16 *first_SID, /* i/o: First SID indicator */ + Word32 *cohBand /* i/o: Coherence per band Q31 */ +) +{ + Word16 b, k; + Word32 coh_weight; + Word16 coh_weight_e; + Word32 coh_weight_sum; + Word16 coh_weight_sum_e; + Word32 xspec_scale; + Word32 L_tmp1, L_tmp2, L_tmp3; + Word16 L_tmp1_e, L_tmp2_e, L_tmp3_e; + Word64 W_tmp; + Word16 W_tmp_q; + // Word16 prev_cohBand_e[2 * (STEREO_DFT_BAND_MAX / 2)]; + Word16 cohBand_e[STEREO_DFT_BAND_MAX / 2]; + /* Cluster the coherence into bands using a weighted average. The coherence is weighted with the energy spectrum of the + mixdown signal. */ + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + cohBand[b] = 0; + move32(); + cohBand_e[b] = 0; + move16(); + coh_weight_sum = 0; + move32(); + coh_weight_sum_e = 0; + move16(); + + test(); + IF( hStereoDft->coh_fade_counter == 0 && !*first_SID ) + { + FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + // xspec_scale = sqrtf( ( prev_cohBand[b] * ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] ) ) / ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] + EPSILON ) ); + W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] ); + W_tmp_q = W_norm( W_tmp ); + L_tmp1 = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + L_tmp1_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp2_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e ); + L_tmp3 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &L_tmp3_e ); + L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) ); + L_tmp3 = Mpy_32_32( prev_cohBand[b], L_tmp3 ); + xspec_scale = Sqrt32( L_tmp3, &L_tmp3_e ); + // xspec_scale = L_shl(xspec_scale, L_tmp3_e);//Q31 + + hStereoDft->xspec_smooth_fx[2 * k] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], xspec_scale ); + move32(); + hStereoDft->xspec_smooth_fx_e[2 * k] = add( hStereoDft->xspec_smooth_fx_e[2 * k], L_tmp3_e ); + move16(); + hStereoDft->xspec_smooth_fx[2 * k + 1] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], xspec_scale ); + move32(); + hStereoDft->xspec_smooth_fx_e[2 * k + 1] = add( hStereoDft->xspec_smooth_fx_e[2 * k + 1], L_tmp3_e ); + move16(); + } + + cohBand[b] = prev_cohBand[b]; + move32(); + } + ELSE + { + FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + // coh_weight = hStereoDft->DFT[0][2 * k] * hStereoDft->DFT[0][2 * k] + hStereoDft->DFT[0][2 * k + 1] * hStereoDft->DFT[0][2 * k + 1]; + W_tmp = W_add( W_mult_32_32( hStereoDft->DFT_fx[0][2 * k], hStereoDft->DFT_fx[0][2 * k] ), W_mult_32_32( hStereoDft->DFT_fx[0][2 * k + 1], hStereoDft->DFT_fx[0][2 * k + 1] ) ); + W_tmp_q = W_norm( W_tmp ); + coh_weight = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + coh_weight_e = sub( shl( hStereoDft->DFT_fx_e[0], 1 ), W_tmp_q ); // 31 - dft_e*2 + W_tmp_q + + // cohBand[b] += coh_weight * ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] ) / ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] + EPSILON ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp1_e ); + W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] ); + W_tmp_q = W_norm( W_tmp ); + L_tmp2 = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + L_tmp2_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e ); + L_tmp3 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &L_tmp3_e ); + L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) ); + L_tmp3 = Mpy_32_32( coh_weight, L_tmp3 ); + L_tmp3_e = add( coh_weight_e, L_tmp3_e ); + cohBand[b] = BASOP_Util_Add_Mant32Exp( cohBand[b], cohBand_e[b], L_tmp3, L_tmp3_e, &cohBand_e[b] ); + move32(); + + // coh_weight_sum += coh_weight; + coh_weight_sum = BASOP_Util_Add_Mant32Exp( coh_weight_sum, coh_weight_sum_e, coh_weight, coh_weight_e, &coh_weight_sum_e ); + } + IF( coh_weight_sum > 0 ) + { + // cohBand[b] = cohBand[b] / coh_weight_sum; + cohBand[b] = BASOP_Util_Divide3232_Scale_cadence( cohBand[b], coh_weight_sum, &L_tmp1_e ); + move32(); + cohBand_e[b] = add( L_tmp1_e, sub( cohBand_e[b], coh_weight_sum_e ) ); + move16(); + cohBand[b] = L_shl_sat( cohBand[b], cohBand_e[b] ); // Q31: value does not exceed 1.0 + move32(); + } + } + } + + IF( *first_SID ) + { + Copy32( cohBand, prev_cohBand, hStereoDft->nbands ); + Copy32( prev_cohBand, &( prev_cohBand[STEREO_DFT_BAND_MAX / 2] ), hStereoDft->nbands ); + *first_SID = 0; + move32(); + } + + test(); + test(); + IF( LT_16( hStereoDft->coh_fade_counter, COH_FADE_MAX ) && ( *td_active || LT_16( hStereoDft->currentNumUpdates, COH_FADE_UPDATES ) ) ) + { + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + // cohBand[b] = ( cohBand[b] * hStereoDft->coh_fade_counter + prev_cohBand[b] * ( COH_FADE_MAX - hStereoDft->coh_fade_counter ) ) / COH_FADE_MAX; + SWITCH( hStereoDft->coh_fade_counter ) + { + case 0: + cohBand[b] = prev_cohBand[b]; + move32(); + BREAK; + case 1: + cohBand[b] = L_add( L_shr( cohBand[b], 2 ), Mpy_32_32( prev_cohBand[b], 1610612736 /*3/4*/ ) ); + move32(); + BREAK; + case 2: + cohBand[b] = L_add( L_shr( cohBand[b], 1 ), L_shr( prev_cohBand[b], 1 ) ); + move32(); + BREAK; + case 3: + cohBand[b] = L_add( Mpy_32_32( cohBand[b], 1610612736 /*3/4*/ ), L_shr( prev_cohBand[b], 2 ) ); + move32(); + BREAK; + default: + assert( "unexpected hStereoDft->coh_fade_counter value" ); + BREAK; + } + } + hStereoDft->coh_fade_counter = add( hStereoDft->coh_fade_counter, 1 ); + IF( hStereoDft->coh_fade_counter > 0 ) + { + Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); + } + ELSE + { + IF( hStereoDft->coh_fade_counter > 0 ) + { + Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); + hStereoDft->coh_fade_counter = COH_FADE_MAX; + move16(); + *td_active = 0; + move16(); + } + return; +} +#else void stereo_dft_enc_sid_calc_coh( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ float prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence */ @@ -139,7 +304,7 @@ void stereo_dft_enc_sid_calc_coh( return; } - +#endif /*--------------------------------------------------------------- * stereo_dft_enc_sid_coh() @@ -147,6 +312,231 @@ void stereo_dft_enc_sid_calc_coh( * Encodes the coherence in SID frames * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_sid_coh_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word32 *mem_cohBand, /* i/o: Coherence memory */ + const Word16 nbands, /* i : number of DFT stereo bands */ + Word16 *nb_bits, /* i/o: number of bits written */ + Word32 *cohBand /* i/o: Coherence per band */ +) +{ + Word16 b, k; + Word16 zeropad; + Word16 nr_of_sid_stereo_bits; + Word16 coh_pred_index; + Word16 min_pred_err; + Word16 min_pred_err_e; + Word16 pred_err; // Q13 + Word16 res_index; + Word16 i; + Word16 tmp; + const Word16 *pptr; + Word16 pred; // Q13 + Word16 cohBandq[STEREO_DFT_BAND_MAX / 2]; /* Reconstructed coherence values for intra-frame prediction Q15 */ + const Word16 *alphaptr; + Word16 nbbits_test; + Word16 prev_nbbits_test; + Word16 alpha_step; + Word16 alpha_level; + Word16 n; + + nr_of_sid_stereo_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + move16(); + zeropad = 0; + move16(); + + /* Encode coherence vector. Find best fixed predictor by minimizing prediction error on input vector. + The prediction is formed by a linear combination of the previous values + in the vector. Hence, prediction is only done for coefficient 1 and up. + If not enough bits for at least one bit for encoding prediction + residual then skip the coding and write zeroes to the bitstream if needed. + In this case the decoder will set alpha to 0, i.e. reuse previous coherence */ + + IF( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS + STEREO_DFT_PRED_NBITS ) > 0 ) + { + min_pred_err = 31250; + move32(); + min_pred_err_e = 20; + move16(); + coh_pred_index = -1; + move16(); + pptr = dft_cng_coh_pred_fx[0]; // Q13 + FOR( k = 0; k < STEREO_DFT_N_COH_PRED; k++ ) + { + pred_err = 0; + move16(); + FOR( b = 1; b < nbands; b++ ) /* Set b=1 to skip first coefficient (same error would otherwise be added for all predictors: (cohBand[0] - 0).^2) */ + { + pred = 0; + move16(); + FOR( i = 0; i < b; i++ ) + { + // pred += ( *pptr++ ) * cohBand[i]; + pred = add( pred, mult_r( extract_h( cohBand[i] ), ( *pptr++ ) ) ); // Q13 + } + tmp = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + // pred_err += tmp * tmp; + pred_err = add( pred_err, shl( mult_r( tmp, tmp ), 2 ) ); // Q13 + } + // if ( pred_err < min_pred_err ) /* Store best candidate */ + IF( BASOP_Util_Cmp_Mant32Exp( pred_err, 16, min_pred_err, add( min_pred_err_e, 16 ) ) < 0 ) /* Store best candidate */ + { + min_pred_err = pred_err; + move32(); + min_pred_err_e = 0; + move16(); + coh_pred_index = k; + move16(); + } + } + + push_next_indice( hBstr, coh_pred_index, STEREO_DFT_PRED_NBITS ); /* Write selected predictor to bitstream */ + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_PRED_NBITS ); + move16(); + + /* Pick two different alphas (one low and one high) as a function + of the number of available bits. */ + alpha_step = 0; + move16(); + FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_STEPS - 1; i++ ) + { + IF( GT_16( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ), dft_cng_coh_alpha_start[i] ) ) + { + alpha_step = add( i, 1 ); + } + } + + /* Calculate the number of encoded bits. */ + alphaptr = dft_cng_alpha_bits_fx[alpha_step]; + alpha_level = 0; + move16(); + prev_nbbits_test = 100; + move16(); + FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_LEVELS; i++ ) + { + nbbits_test = 0; + move16(); + pptr = dft_cng_coh_pred_fx[coh_pred_index]; // Q13 + pred = 3277 /*0.4f*/; + move16(); + FOR( b = 0; b < nbands; b++ ) + { + FOR( n = 0; n < b; n++ ) + { + // pred += ( *pptr++ ) * cohBandq[n]; + pred = add( pred, mult_r( cohBandq[n], *pptr++ ) ); // Q13 + } + + // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b]; + pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13 + pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 ); + res_index = dft_cng_coh_i2u[res_index]; + nbbits_test = add( nbbits_test, add( res_index, 1 ) ); + res_index = dft_cng_coh_u2i[res_index]; + pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ ); // Q13 + cohBandq[b] = add( pred, pred_err ); + move16(); + cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15 + move16(); + if ( cohBandq[b] < 0 ) + { + cohBandq[b] = 0; + move16(); + } + pred = 0; + move16(); + } + + if ( LT_16( nbbits_test, sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ) ) ) + { + alpha_level = i; + move16(); + } + + if ( LT_16( nbbits_test, prev_nbbits_test ) ) + { + alpha_level = i; + move16(); + } + + prev_nbbits_test = nbbits_test; + move16(); + alphaptr++; + } + + /* Do the actual encoding using the selected predictor and alpha */ + push_next_indice( hBstr, alpha_level, STEREO_DFT_N_COH_ALPHA_BITS ); /* Write selected alpha index to bitstream */ + ( *nb_bits ) += STEREO_DFT_N_COH_ALPHA_BITS; + move16(); + alphaptr = &dft_cng_alpha_bits_fx[alpha_step][alpha_level]; + pptr = dft_cng_coh_pred_fx[coh_pred_index]; /* Set pointer to selected predictor */ + pred = 3277 /*0.4f in Q13*/; + + FOR( b = 0; b < nbands; b++ ) + { + /* Intra-frame prediction using quantized values */ + FOR( i = 0; i < b; i++ ) + { + // pred += ( *pptr++ ) * cohBandq[i]; + pred = add( pred, mult_r( cohBandq[i], *pptr++ ) ); // Q13 + } + /* Weighted intra/inter-frame prediction */ + // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b]; + pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13 + pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + + res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 ); /* Quantize prediction residual */ + res_index = dft_cng_coh_i2u[res_index]; /* Convert to unary codeword - res_index+1 now equal to codeword + length in bits with the following order: + [0.0, 0.1, -0.1, 0.2, -0.2, 0.3, -0.3, 0.4, -0.4] */ + /* Bit rate truncation */ + WHILE( res_index + 1 + *nb_bits > nr_of_sid_stereo_bits && res_index > 0 ) + { + test(); + res_index = s_max( 0, sub( res_index, 2 ) ); /* Reduce step by one, keeping sign. */ + } + /* Write residual index to bitstream */ + IF( LE_16( add( add( res_index, 1 ), *nb_bits ), nr_of_sid_stereo_bits ) ) /* If the bit limit is reached, res_index = 0 is assumed for remaining indices */ + { + *nb_bits = add( *nb_bits, write_GR0( hBstr, IND_STEREO_DFT_SID_COH, &res_index, 1 ) ); + move16(); + } + + /* Reconstruct */ + res_index = dft_cng_coh_u2i[res_index]; + move16(); + pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ ); + cohBandq[b] = add( pred, pred_err ); /* Store for intra-frame prediction */ + move16(); + cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15 + move16(); + if ( cohBandq[b] < 0 ) + { + cohBandq[b] = 0; + move16(); + } + + mem_cohBand[b] = L_deposit_h( cohBandq[b] ); /* Update memory for next frame */ + move32(); + pred = 0; + move16(); + } + } + + /* Zero pad up to max number of bits to get constant bitrate */ + FOR( k = *nb_bits; k < nr_of_sid_stereo_bits; k++ ) + { + push_next_indice( hBstr, zeropad, 1 ); + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); + } + + + return; +} +#else void stereo_dft_enc_sid_coh( BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ float *mem_cohBand, /* i/o: Coherence memory */ @@ -332,7 +722,7 @@ void stereo_dft_enc_sid_coh( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_cng_side_gain() @@ -340,6 +730,169 @@ void stereo_dft_enc_sid_coh( * Calculate CNG side gain *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_cng_side_gain_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word32 last_core_brate, /* i : last core bitrate */ + const Word16 bwidth /* i : audio band-width */ +) +{ + Word16 b; + Word16 sgSum; + Word16 band_limits_full[STEREO_DFT_BAND_MAX + 1]; + Word16 prev_weight; // Q15 + Word16 NFFT_inner; + Word16 nbands_full; + Word32 tmp; + Word16 tmp_16; + Word16 tmp_e; + Word64 W_tmp; + Word16 W_tmp_q; + + // NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[bwidth] / L_FRAME48k; + NFFT_inner = shl( inner_frame_tbl[bwidth], 1 ); + nbands_full = hStereoDft->nbands; + move16(); + + /* Calculate side gain average. First average in an inactive period */ + /* uses a weighted sum of the current average and the one from the */ + /* previous inactive segment */ + + /* Inactive frame => Update both sets of averages */ + FOR( b = 0; b < nbands_full; b++ ) + { + // hStereoCng->sg_average[b] += hStereoDft->sidSideGain[b]; + hStereoCng->sg_average_fx[b] = L_add( hStereoCng->sg_average_fx[b], L_shr_r( hStereoDft->sidSideGain_fx[b], 5 ) ); + move32(); + } + hStereoCng->sg_average_counter = add( hStereoCng->sg_average_counter, 1 ); + move32(); + + hStereoCng->cng_counter = add( hStereoCng->cng_counter, 1 ); + move16(); + hStereoCng->cng_counter = s_min( hStereoCng->cng_counter, STEREO_DFT_SG_ACT_CNT_MAX ); + move16(); + + IF( EQ_32( core_brate, SID_2k40 ) ) + { + /* SID frame */ + test(); + IF( EQ_32( last_core_brate, FRAME_NO_DATA ) || hStereoCng->first_SID ) + { + /* If first ever SID frame or not the first SID in an inactive segment */ + /* Calculate average only based on current sg_average */ + /* Copy current sum to previous */ + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + hStereoCng->prev_sg_average_fx[b] = hStereoCng->sg_average_fx[b]; + move32(); + // hStereoCng->sg_average[b] = hStereoCng->sg_average[b] / (float) hStereoCng->sg_average_counter; + hStereoCng->sg_average_fx[b] = BASOP_Util_Divide3232_Scale_cadence( hStereoCng->sg_average_fx[b], hStereoCng->sg_average_counter, &tmp_e ); + move32(); + tmp_e = sub( tmp_e, 31 - 5 ); + hStereoCng->sg_average_fx[b] = L_shl_r( hStereoCng->sg_average_fx[b], sub( tmp_e, 5 ) ); // Q31 + move32(); + } + + hStereoCng->prev_sg_average_counter = hStereoCng->sg_average_counter; + move16(); + } + ELSE + { + /* If first SID in a new inactive segment */ + /* Calculate weighting factor based on the time since the last inactive segment */ + // prev_weight = 0.8f * (float) ( STEREO_DFT_SG_ACT_CNT_MAX - hStereoCng->sg_active_cnt ) / (float) STEREO_DFT_SG_ACT_CNT_MAX + 0.2f; + tmp_16 = BASOP_Util_Divide1616_Scale( sub( STEREO_DFT_SG_ACT_CNT_MAX, hStereoCng->sg_active_cnt ), STEREO_DFT_SG_ACT_CNT_MAX, &tmp_e ); + prev_weight = add( shl( mult_r( 26214 /*0.8f*/, tmp_16 ), tmp_e ), 6554 /*0.2f*/ ); + + /* Calculate weighted average between prev and current sg */ + /* Set prev_sg sum to current. */ + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + tmp = hStereoCng->sg_average_fx[b]; + move32(); + // hStereoCng->sg_average[b] = ( hStereoCng->sg_average[b] + prev_weight * hStereoCng->prev_sg_average[b] ) / ( (float) hStereoCng->sg_average_counter + prev_weight * (float) hStereoCng->prev_sg_average_counter ); + hStereoCng->sg_average_fx[b] = BASOP_Util_Divide3232_Scale_cadence( L_add( hStereoCng->sg_average_fx[b], Mpy_32_16_1( hStereoCng->prev_sg_average_fx[b], prev_weight ) ), L_add( L_shl( hStereoCng->sg_average_counter, Q15 ), L_mult0( prev_weight, hStereoCng->prev_sg_average_counter ) ), &tmp_e ); + move32(); + tmp_e = sub( tmp_e, 16 - 5 ); + hStereoCng->sg_average_fx[b] = L_shl_r( hStereoCng->sg_average_fx[b], sub( tmp_e, 5 ) ); // Q26 + move32(); + + hStereoCng->prev_sg_average_fx[b] = tmp; + move32(); + } + hStereoCng->prev_sg_average_counter = hStereoCng->sg_average_counter; + move16(); + } + + /* Use coarse band partitioning in inactive frames */ + /* Rescale bands to the coarser partitioning taking the band size into account */ + Copy( hStereoDft->band_limits, band_limits_full, STEREO_DFT_BAND_MAX + 1 ); + hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->hConfig->band_res, s_min( STEREO_DFT_N_32k_ENC, NFFT_inner ), ENC ); + move16(); + IF( GT_16( nbands_full, add( hStereoDft->nbands, 1 ) ) ) + { + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + // hStereoDft->sidSideGain[b] = hStereoCng->sg_average[2 * b] * ( band_limits_full[2 * b + 1] - band_limits_full[2 * b] ); + W_tmp = W_shl( W_mult_32_32( hStereoCng->sg_average_fx[2 * b], sub( band_limits_full[2 * b + 1], band_limits_full[2 * b] ) ), 5 ); // Q31 + sgSum = sub( band_limits_full[2 * b + 1], band_limits_full[2 * b] ); + // if ( ( 2 * b + 1 ) < nbands_full ) + IF( LT_16( add( shl( b, 1 ), 1 ), nbands_full ) ) + { + // hStereoDft->sidSideGain[b] += hStereoCng->sg_average[2 * b + 1] * ( band_limits_full[2 * b + 2] - band_limits_full[2 * b + 1] ); + W_tmp = W_add( W_tmp, W_shl( W_mult_32_32( hStereoCng->sg_average_fx[2 * b + 1], sub( band_limits_full[2 * b + 2], band_limits_full[2 * b + 1] ) ), 5 ) ); // Q31 + sgSum = add( sgSum, sub( band_limits_full[2 * b + 2], band_limits_full[2 * b + 1] ) ); + } + // hStereoDft->sidSideGain[b] = hStereoDft->sidSideGain[b] / sgSum; + W_tmp_q = W_norm( W_tmp ); + hStereoDft->sidSideGain_fx[b] = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + move32(); + hStereoDft->sidSideGain_fx[b] = BASOP_Util_Divide3232_Scale_cadence( hStereoDft->sidSideGain_fx[b], sgSum, &tmp_e ); + move32(); + tmp_e = sub( tmp_e, W_tmp_q ); + hStereoDft->sidSideGain_fx[b] = L_shl_sat( hStereoDft->sidSideGain_fx[b], tmp_e ); // Q31: saturation is fine since stereo_dft_quantize_res_gains_fx limits value to 1.0 + move32(); + stereo_dft_quantize_res_gains_fx( &hStereoDft->sidSideGain_fx[b], NULL, NULL, NULL, hStereoDft->side_gain_index_EC + b, NULL ); + } + } + ELSE + { + Word32 sg_average_fx_q31; + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + sg_average_fx_q31 = L_shl_sat( hStereoCng->sg_average_fx[b], 5 ); // Q31 + stereo_dft_quantize_res_gains_fx( &sg_average_fx_q31, NULL, NULL, NULL, hStereoDft->side_gain_index_EC + b, NULL ); + } + } + /* Restart SID avg after sending SID */ + hStereoCng->sg_average_counter = 0; + move16(); + set_zero_fx( hStereoCng->sg_average_fx, STEREO_DFT_BAND_MAX ); + } + ELSE + { + FOR( b = 0; b < nbands_full; b++ ) + { + // hStereoCng->prev_sg_average[b] += hStereoDft->sidSideGain[b]; + hStereoCng->prev_sg_average_fx[b] = L_add( hStereoCng->prev_sg_average_fx[b], L_shr_r( hStereoDft->sidSideGain_fx[b], 5 ) ); // Q26 + move32(); + } + + hStereoCng->prev_sg_average_counter = add( hStereoCng->prev_sg_average_counter, 1 ); + move16(); + } + + hStereoCng->sg_active_cnt = 0; + move16(); + hStereoCng->first_SID_after_TD = 0; + move16(); + + return; +} +#else void stereo_dft_cng_side_gain( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ @@ -455,7 +1008,7 @@ void stereo_dft_cng_side_gain( return; } - +#endif /*--------------------------------------------------------------- * stereo_enc_cng_init() @@ -473,8 +1026,9 @@ void stereo_enc_cng_init( set32_fx( hStereoCng->sg_average_fx, 0, STEREO_DFT_BAND_MAX ); #endif hStereoCng->prev_sg_average_counter = 0; +#ifndef IVAS_FLOAT_FIXED set_zero( hStereoCng->prev_sg_average, STEREO_DFT_BAND_MAX ); -#ifdef IVAS_FLOAT_FIXED +#else set32_fx( hStereoCng->prev_sg_average_fx, 0, STEREO_DFT_BAND_MAX ); #endif hStereoCng->sg_active_cnt = 0; @@ -498,7 +1052,58 @@ void stereo_enc_cng_init( * * Update Stereo CNG counters *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_cng_upd_counters_fx( + STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ + const Word32 element_mode, /* i : element mode */ + const Word16 nbands, /* i : Number of bands in active */ + const Word32 sidSideGain[], /* i : SID side gains */ + const Word16 burst_ho_count, /* i : Hang-over count */ + Word16 *coh_fade_counter /* i : Coherence fade counter */ +) +{ + Word16 b; + /* Update sg avg in hangover frames, reset in active frames */ + test(); + IF( burst_ho_count > 0 && EQ_32( element_mode, IVAS_CPE_DFT ) ) + { + FOR( b = 0; b < nbands; b++ ) + { + // hStereoCng->sg_average[b] += sidSideGain[b]; + hStereoCng->sg_average_fx[b] = L_add( hStereoCng->sg_average_fx[b], L_shr_r( sidSideGain[b], 5 ) ); // Q26 + move32(); + } + hStereoCng->sg_average_counter = add( hStereoCng->sg_average_counter, 1 ); + move16(); + } + else + { + hStereoCng->sg_average_counter = 0; + move16(); + set_zero_fx( hStereoCng->sg_average_fx, STEREO_DFT_BAND_MAX ); + } + + /* Increment active counter, stop at max value */ + hStereoCng->sg_active_cnt = add( hStereoCng->sg_active_cnt, 1 ); + move16(); + hStereoCng->sg_active_cnt = s_min( hStereoCng->sg_active_cnt, STEREO_DFT_SG_ACT_CNT_MAX ); + move16(); + + IF( GT_16( hStereoCng->sg_active_cnt, STEREO_DFT_CNG_ITD_CNT ) ) + { + hStereoCng->cng_counter = 0; + move16(); + } + + IF( EQ_32( element_mode, IVAS_CPE_DFT ) ) + { + *coh_fade_counter = 0; + move16(); + } + return; +} +#endif void stereo_cng_upd_counters( STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */ const int32_t element_mode, /* i : element mode */ diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index 7da597f49db19f5ad5417f0796555307466949f2..95be17fb57f2f1d791eb78937f6ab7824a6b0064 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -133,9 +133,27 @@ static Word32 stereo_dft_gain_offset_fx( const Word32 c, const Word16 c_e, const static float stereo_dft_gain_offset( const float c, const int16_t itd ); #endif +#ifdef IVAS_FLOAT_FIXED +static void side_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_GR[], + const Word16 sp_aud_decision0, /* i : Speech/audio decision 0 */ + const Word32 last_core_brate /* i : Last core bitrate */ +); +#else static void side_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int16_t encoded_ind_GR[], const int16_t sp_aud_decision0, const int32_t last_core_brate ); +#endif +#ifdef IVAS_FLOAT_FIXED +static void res_pred_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_pred_GR[], + const Word16 k_offset, /* i : Parameter offset */ + const Word32 last_core_brate /* i : Last core bitrate */ +); +#else static void res_pred_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int16_t encoded_ind_pred_GR[], const int16_t k_offset, const int32_t last_core_brate ); +#endif #ifdef IVAS_FLOAT_FIXED static void stereo_dft_enc_calculate_nrg_for_icbwe_fx( @@ -476,7 +494,7 @@ static void stereo_dft_quantize_ipd_fx( return; } -#endif +#else static void stereo_dft_quantize_ipd( const float *in, float *out, @@ -523,6 +541,7 @@ static void stereo_dft_quantize_ipd( return; } +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_create() @@ -650,10 +669,10 @@ static void stereo_dft_enc_open( #ifdef IVAS_FLOAT_FIXED hStereoDft->win_ana_energy_fx = (Word16) ( hStereoDft->win_ana_energy * ( 1 << 15 ) ); #endif - set_f( hStereoDft->output_mem_dmx_32k, 0, STEREO_DFT_OVL_32k ); hStereoDft->dft_zp = (int16_t) ( STEREO_DFT_ZP_MAX_ENC * input_Fs / 48000 ); - + set_f( hStereoDft->output_mem_dmx_32k, 0, STEREO_DFT_OVL_32k ); +#ifndef IVAS_FLOAT_FIXED hStereoDft->dft_trigo_8k = dft_trigo_32k; hStereoDft->dft_trigo_12k8 = dft_trigo_12k8; hStereoDft->dft_trigo_16k = dft_trigo_32k; @@ -668,7 +687,7 @@ static void stereo_dft_enc_open( hStereoDft->win_12k8 = win_syn_12k8; hStereoDft->win_16k = win_syn_16k; hStereoDft->win_32k = win_syn_32k; - +#endif // need to remove this once fixed function is called // #ifdef IVAS_FLOAT_FIXED hStereoDft->dft_trigo_8k_fx = dft_trigo_32k_fx; @@ -689,54 +708,60 @@ static void stereo_dft_enc_open( 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; +#else + hStereoDft->dft_trigo = dft_trigo_32k; + hStereoDft->win_ana = win_ana_16k; + hStereoDft->win = win_syn_16k; + #endif } else if ( input_Fs == 32000 ) { - hStereoDft->dft_trigo = dft_trigo_32k; 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; +#else + hStereoDft->dft_trigo = dft_trigo_32k; + hStereoDft->win_ana = win_ana_32k; + hStereoDft->win = win_syn_32k; #endif } else { assert( input_Fs == 48000 ); - hStereoDft->dft_trigo = dft_trigo_48k; 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; +#else + hStereoDft->dft_trigo = dft_trigo_48k; + hStereoDft->win_ana = win_ana_48k; + hStereoDft->win = win_syn_48k; + #endif } - hStereoDft->win_mdct_8k = win_mdct_8k; #ifdef IVAS_FLOAT_FIXED hStereoDft->win_mdct_8k_fx = win_mdct_8k_fx; +#else + hStereoDft->win_mdct_8k = win_mdct_8k; #endif - +#ifdef IVAS_FLOAT_FIXED /*I/O Buffers*/ set_zero( hStereoDft->output_mem_dmx, STEREO_DFT_OVL_MAX ); set_zero( hStereoDft->output_mem_dmx_12k8, STEREO_DFT_OVL_12k8 ); set_zero( hStereoDft->output_mem_dmx_16k, STEREO_DFT_OVL_16k ); set_zero( hStereoDft->output_mem_dmx_16k_shb, STEREO_DFT_OVL_16k ); set_zero( hStereoDft->output_mem_res_8k, STEREO_DFT_OVL_8k ); - +#endif #ifdef IVAS_FLOAT_FIXED hStereoDft->dft_trigo_8k_fx = dft_trigo_32k_fx; hStereoDft->dft_trigo_12k8_fx = dft_trigo_12k8_fx; @@ -939,7 +964,9 @@ void stereo_dft_enc_reset( { int16_t i; /*reset parameters*/ +#ifndef IVAS_FLOAT_FIXED set_zero( hStereoDft->side_gain, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); +#endif set_s( hStereoDft->side_gain_index_EC, 15, STEREO_DFT_BAND_MAX ); set_s( hStereoDft->side_gain_index_ECDiff, 0, STEREO_DFT_BAND_MAX ); set_s( hStereoDft->side_gain_index_ECprevious, 15, STEREO_DFT_BAND_MAX ); @@ -950,39 +977,50 @@ void stereo_dft_enc_reset( #else hStereoDft->side_gain_bitdiff_lp = STEREO_DFT_BITDIFF_INIT; #endif +#ifndef IVAS_FLOAT_FIXED set_zero( hStereoDft->gipd, STEREO_DFT_ENC_DFT_NB ); set_zero( hStereoDft->dot_prod_real_smooth, STEREO_DFT_BAND_MAX ); set_zero( hStereoDft->dot_prod_img_smooth, STEREO_DFT_BAND_MAX ); +#endif #ifdef IVAS_FLOAT_FIXED set_zero_fx( hStereoDft->dot_prod_real_smooth_fx, STEREO_DFT_BAND_MAX ); set16_zero_fx( hStereoDft->dot_prod_real_smooth_fx_e, STEREO_DFT_BAND_MAX ); set_zero_fx( hStereoDft->dot_prod_img_smooth_fx, STEREO_DFT_BAND_MAX ); set16_zero_fx( hStereoDft->dot_prod_img_smooth_fx_e, STEREO_DFT_BAND_MAX ); #endif +#ifndef IVAS_FLOAT_FIXED for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) { set_zero( hStereoDft->ipd_buf[i], STEREO_DFT_IPD_BUF_LEN ); } hStereoDft->prev_gipd = 0.f; - hStereoDft->gipd_index = 0; set_zero( hStereoDft->res_pred_gain, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); +#endif + hStereoDft->gipd_index = 0; set_s( hStereoDft->res_pred_index_EC, 0, STEREO_DFT_BAND_MAX ); set_s( hStereoDft->res_pred_index_ECDiff, 0, STEREO_DFT_BAND_MAX ); set_s( hStereoDft->res_pred_index_ECprevious, 0, STEREO_DFT_BAND_MAX ); hStereoDft->res_pred_counter = 0; +#ifndef IVAS_FLOAT_FIXED set_zero( hStereoDft->past_nrgL, STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX ); set_zero( hStereoDft->past_nrgR, STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX ); set_zero( hStereoDft->past_dot_prod_real, STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX ); set_zero( hStereoDft->past_dot_prod_imag, STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX ); +#endif hStereoDft->nrg_past_pos = 0; - +#ifndef IVAS_FLOAT_FIXED hStereoDft->res_dmx_ratio_lt = 1.0f; +#endif hStereoDft->hangover_cnt0 = 0; hStereoDft->hangover_cnt1 = 0; +#ifndef IVAS_FLOAT_FIXED hStereoDft->dmx_res_all_prev = EPSILON; +#endif hStereoDft->last_res_cod_mode_modify_flag = 0; hStereoDft->res_cod_sw_flag = 0; +#ifndef IVAS_FLOAT_FIXED hStereoDft->switch_fade_factor = 0.5f; +#endif hStereoDft->res_cod_mode[STEREO_DFT_OFFSET - 1] = STEREO_DFT_RES_COD_1kHz; for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) { @@ -993,11 +1031,12 @@ void stereo_dft_enc_reset( hStereoDft->reverb_flag = 0; +#ifndef IVAS_FLOAT_FIXED set_zero( hStereoDft->pre_sub_nrg_DMX, STEREO_DFT_BAND_MAX ); hStereoDft->diff_l_h_sm = 0.0f; hStereoDft->diff_r_h_sm = 0.0f; hStereoDft->prev_fac2 = 1.0f; - +#endif set_zero( hStereoDft->res_pred_gain_f, STEREO_DFT_BAND_MAX ); /*misc*/ @@ -1007,27 +1046,29 @@ void stereo_dft_enc_reset( hStereoDft->no_ipd_cnt1 = 0; hStereoDft->attackPresent = 0; hStereoDft->wasTransient = 0; +#ifndef IVAS_FLOAT_FIXED hStereoDft->gainIPD_sm = 1.f; - - hStereoDft->voicing_lt = 0; +#endif - hStereoDft->flip_sign = 1; + hStereoDft->flip_sign = 1; +#ifndef IVAS_FLOAT_FIXED hStereoDft->sfm = 0.f; hStereoDft->sum_dot_prod_real = 0.f; hStereoDft->sum_dot_prod_img = 0.f; - +#endif /*Coherence*/ +#ifndef IVAS_FLOAT_FIXED set_f( hStereoDft->xspec_smooth, 1.0f, STEREO_DFT_N_32k_ENC ); + hStereoDft->sid_gipd = 0; + hStereoDft->prev_sid_gipd = 0; set_f( hStereoDft->Spd_L_smooth, 1.0f, STEREO_DFT_N_32k_ENC / 2 ); set_f( hStereoDft->Spd_R_smooth, 1.0f, STEREO_DFT_N_32k_ENC / 2 ); - +#endif hStereoDft->currentNumUpdates = 0; hStereoDft->expectedNumUpdates = FIXED_SID_RATE; hStereoDft->resetFrames = 0; - hStereoDft->sid_gipd = 0; - hStereoDft->prev_sid_gipd = 0; hStereoDft->prev_sid_no_ipd_flag = 1; hStereoDft->coh_fade_counter = 0; @@ -1175,8 +1216,13 @@ void stereo_dft_enc_reset_fx( /*Coherence*/ set32_fx( hStereoDft->xspec_smooth_fx, MAX_32, STEREO_DFT_N_32k_ENC ); + set16_fx( hStereoDft->xspec_smooth_fx_e, 0, STEREO_DFT_N_32k_ENC ); set32_fx( hStereoDft->Spd_L_smooth_fx, MAX_32, shr( STEREO_DFT_N_32k_ENC, 1 ) ); + hStereoDft->Spd_L_smooth_fx_e = 0; + move16(); set32_fx( hStereoDft->Spd_R_smooth_fx, MAX_32, shr( STEREO_DFT_N_32k_ENC, 1 ) ); + hStereoDft->Spd_R_smooth_fx_e = 0; + move16(); hStereoDft->currentNumUpdates = 0; move16(); @@ -1250,8 +1296,9 @@ void stereo_enc_itd_init( hItd->prev_max = 0.f; hItd->prev_index = 0; hItd->prev_avg_max = 0.f; +#ifndef IVAS_FLOAT_FIXED hItd->currFlatness = 0.f; - +#endif /* Xtalk classifier */ hItd->prev_m1 = 0; hItd->prev_m2 = 0; @@ -1300,7 +1347,6 @@ void stereo_enc_itd_init_fx( 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; @@ -1515,7 +1561,7 @@ void stereo_dft_enc_destroy( * * DFT analysis on a 20ms frame *-------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_analyze( Encoder_State **sts, /* i/o: encoder state structure */ const int16_t n_channels, /* i : number of input channels */ @@ -1643,8 +1689,7 @@ void stereo_dft_enc_analyze( pop_wmops(); return; } - -#ifdef IVAS_FLOAT_FIXED +#else void stereo_dft_enc_analyze_fx( Encoder_State **sts, /* i/o: encoder state structure */ const Word16 n_channels, /* i : number of input channels */ @@ -1652,6 +1697,7 @@ void stereo_dft_enc_analyze_fx( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 DFT_e[CPE_CHANNELS], /* o : DFT buffers */ Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ Word16 *q_input_mem ) { @@ -1774,9 +1820,9 @@ void stereo_dft_enc_analyze_fx( pDFT_R[add( add( dft_zp, dft_ovl ), i )] = L_shr( L_deposit_h( input[1][add( add( offset, dft_ovl ), i )] ), 1 ); move32(); } - hStereoDft->DFT_fx_e[0] = sub( 31, add( 15, sts[0]->q_inp ) ); + DFT_e[0] = sub( 31, add( 15, sts[0]->q_inp ) ); move16(); - hStereoDft->DFT_fx_e[1] = sub( 31, add( 15, sts[1]->q_inp ) ); + DFT_e[1] = sub( 31, add( 15, sts[1]->q_inp ) ); move16(); Word16 q_shift, guarded_bits; @@ -1789,7 +1835,7 @@ void stereo_dft_enc_analyze_fx( move32(); } - hStereoDft->DFT_fx_e[0] = sub( hStereoDft->DFT_fx_e[0], q_shift ); + DFT_e[0] = sub( DFT_e[0], q_shift ); move16(); FOR( Word16 j = 0; j < NFFT; j++ ) @@ -1798,7 +1844,7 @@ void stereo_dft_enc_analyze_fx( move32(); } - hStereoDft->DFT_fx_e[1] = sub( hStereoDft->DFT_fx_e[1], q_shift ); + DFT_e[1] = sub( DFT_e[1], q_shift ); move16(); rfft_fx( pDFT_L, trigo_enc, NFFT, -1 ); @@ -2260,7 +2306,7 @@ Word32 stereo_dft_enc_synthesize_fx( pop_wmops(); return ( nrg_fx ); } -#endif +#else float stereo_dft_enc_synthesize( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ float *output, /* o : output synthesis */ @@ -2542,7 +2588,7 @@ float stereo_dft_enc_synthesize( pop_wmops(); return ( nrg ); } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_process() @@ -3403,17 +3449,6 @@ void stereo_dft_enc_process_fx( stereo_dft_enc_calculate_nrg_for_icbwe_fx( hStereoDft, DFT_L_e_tmp, DFT_R_e_tmp, DFT_DMX, DFT_DMX_e, input_Fs ); } -#if 0 // def IVAS_FLOAT_FIXED_CONVERSIONS - float DFT_DMX_flt[STEREO_DFT_N_MAX_ENC]; - float DFT_RES_flt[STEREO_DFT_N_8k_ENC]; - - for (i = 0; i < STEREO_DFT_N_MAX_ENC; i++) { - DFT_DMX_flt[i] = me2f(DFT_DMX[i], DFT_DMX_e[i]); - } - for (i = 0; i < STEREO_DFT_N_8k_ENC; i++) { - DFT_RES_flt[i] = me2f(DFT_RES[i], DFT_RES_e[i]); - } -#endif // making exp common Word16 max_exp = MIN_16; move16(); @@ -4260,6 +4295,168 @@ static void stereo_dft_enc_get_res_cod_mode_flag( * Code the residual signal *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_res_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word32 *input_8k, /* i : input buffer sampled at 8kHz Q16 */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word16 *nb_bits, /* o : number of bits written */ + const Word16 max_bits ) +{ + Word16 i, b; + RangeUniEncState range_uni_enc_state; + ECSQ_instance ecsq_inst; + Word32 MDCT_RES[L_FRAME8k]; + Word16 MDCT_RES_e; + Word16 win[L_FRAME8k + STEREO_DFT_OVL_8k]; // Q0 + Word16 global_gain_index; + Word16 total_bit_count; + Word32 max_snr; // Q25 + Word32 panning_gain, panning_gain_min; + Word32 res_cod_gain[10]; // Q25 + Word32 in_phase_ratio; + Word16 in_phase_ratio_e; + Word32 L_tmp1, L_tmp2; + Word16 /*L_tmp1_e,*/ L_tmp2_e; + assert( hStereoDft->res_cod_line_max <= L_FRAME8k ); + + IF( hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + /* Windowing */ + /* overlapping parts */ + /*input_8k-=STEREO_DFT_OVL_8k;*/ + FOR( i = 0; i < STEREO_DFT_OVL_8k; i++ ) + { + // win[i] = input_8k[i] * hStereoDft->win_mdct_8k[i]; + win[i] = extract_h( Mpy_32_32( input_8k[i], hStereoDft->win_mdct_8k_fx[i] /*Q31*/ ) ); + move32(); + // win[L_FRAME8k + i] = input_8k[L_FRAME8k + i] * hStereoDft->win_mdct_8k[STEREO_DFT_OVL_8k - 1 - i]; + win[L_FRAME8k + i] = extract_h( Mpy_32_32( input_8k[L_FRAME8k + i], hStereoDft->win_mdct_8k_fx[STEREO_DFT_OVL_8k - 1 - i] /*Q31*/ ) ); + move32(); + } + /* middle part */ + FOR( ; i < L_FRAME8k; i++ ) + { + win[i] = extract_h( input_8k[i] ); + move32(); + } + + /* MDCT analysis */ + // TCX_MDCT_flt( win, MDCT_RES, STEREO_DFT_OVL_8k, L_FRAME8k - STEREO_DFT_OVL_8k, STEREO_DFT_OVL_8k, IVAS_CPE_DFT ); + MDCT_RES_e = 16; + move16(); + TCX_MDCT( win, MDCT_RES, &MDCT_RES_e, STEREO_DFT_OVL_8k, L_FRAME8k - STEREO_DFT_OVL_8k, STEREO_DFT_OVL_8k, IVAS_CPE_DFT ); + + /*Compute the DMX to RES for each band*/ + max_snr = 0; /*minimum gain for residual coding -> no coding*/ + move32(); + FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ ) + { + /*Get side gain information and it is we*/ + panning_gain = hStereoDft->side_gain_fx[STEREO_DFT_OFFSET * STEREO_DFT_BAND_MAX + b]; + panning_gain_min = L_sub( MAX_32, L_abs( panning_gain ) ); + + // in_phase_ratio = ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] ) / ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] + hStereoDft->res_cod_NRG_S[b] + 1 ); + L_tmp1 = Mpy_32_32( Mpy_32_32( panning_gain_min, panning_gain_min ), hStereoDft->res_cod_NRG_M_fx[b] ); + L_tmp2 = L_tmp1; + L_tmp2_e = hStereoDft->res_cod_NRG_M_fx_e[b]; + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, hStereoDft->res_cod_NRG_S_fx[b], hStereoDft->res_cod_NRG_S_fx_e[b], &L_tmp2_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, MAX_32, 0, &L_tmp2_e ); + in_phase_ratio = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &in_phase_ratio_e ); + in_phase_ratio_e = add( in_phase_ratio_e, sub( hStereoDft->res_cod_NRG_M_fx_e[b], L_tmp2_e ) ); + in_phase_ratio = L_shl_sat( in_phase_ratio, in_phase_ratio_e ); // Q31 : bound from 0.0 to 1.0 + in_phase_ratio = L_max( 0, in_phase_ratio ); + // in_phase_ratio = check_bounds(in_phase_ratio, 0, 1); + + // res_cod_gain[b] = in_phase_ratio * STEREO_DFT_RES_COD_SNR_MIN + ( 1 - in_phase_ratio ) * STEREO_DFT_RES_COD_SNR_MAX; + res_cod_gain[b] = L_add( Mpy_32_32( in_phase_ratio, STEREO_DFT_RES_COD_SNR_MIN_Q25 ), Mpy_32_32( L_sub( MAX_32, in_phase_ratio ), STEREO_DFT_RES_COD_SNR_MAX ) ); // Q25 + move32(); + + /*get the maximum through bands*/ + if ( GT_32( res_cod_gain[b], max_snr ) ) + { + max_snr = res_cod_gain[b]; + move32(); + } + } + + /*Smooth max_snr because of several perturbations in computation*/ + hStereoDft->old_snr_fx = L_add( Mpy_32_32( 429496730 /*0.2f*/, max_snr ), Mpy_32_32( 1717986918 /*0.8f*/, hStereoDft->old_snr_fx ) ); + move32(); + max_snr = hStereoDft->old_snr_fx; + move32(); + + if ( LT_32( max_snr, STEREO_DFT_RES_COD_SNR_MIN_Q25 ) ) + { + max_snr = STEREO_DFT_RES_COD_SNR_MIN_Q25; + move32(); + } + + push_wmops( "residual_encode" ); + /* residual encoding */ + ECSQ_init_instance_fx( &ecsq_inst, 0 /*dummy index*/, &range_uni_enc_state ); + rc_uni_enc_init( &range_uni_enc_state ); + + ecsq_inst.bit_count_estimate = 0; + move32(); + ecsq_inst.config_index = sub( shl( hStereoDft->res_cod_mode[STEREO_DFT_OFFSET], 1 ), 1 ); + move16(); + + /* 7 bits (STEREO_DFT_RES_GLOBAL_GAIN_BITS) for global_gain_index, 2 bits for closing of the arithmetic coder, 8 safety bits to account for the size estimation accuracy */ + ECSQ_encode_target_SNR_fx( &ecsq_inst, MDCT_RES, MDCT_RES_e, hStereoDft->res_cod_line_max, max_snr, max_bits - ( *nb_bits ) - STEREO_DFT_RES_GLOBAL_GAIN_BITS - 2 - 8, NULL, &global_gain_index ); + IF( NE_16( global_gain_index, ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO ) ) + { + total_bit_count = rc_uni_enc_finish( &range_uni_enc_state ); + + IF( LE_16( total_bit_count, sub( sub( max_bits, *nb_bits ), STEREO_DFT_RES_GLOBAL_GAIN_BITS ) ) ) + { + Word16 idx; + UWord8 *byte_buffer; + + /* Global gain */ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + + /* Push arithmetic coded bits */ + byte_buffer = range_uni_enc_state.byte_buffer; + FOR( idx = 0; idx < shr( total_bit_count, 3 ); ++idx ) + { + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_COD, byte_buffer[idx], 8 ); + } + IF( s_and( total_bit_count, 7 ) != 0 ) + { + /* move the last 1 to 7 bits from the MSB position of the last byte to the LSB postion */ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_COD, shr( byte_buffer[idx], sub( 8, s_and( total_bit_count, 7 ) ) ), s_and( total_bit_count, 7 ) ); + } + ( *nb_bits ) = add( *nb_bits, total_bit_count ); + move16(); + } + ELSE + { + /* Global gain -> 127*/ + global_gain_index = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + } + } + ELSE + { + /* Global gain -> 127*/ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + } + + pop_wmops(); + } + + + return; +} +#else void stereo_dft_enc_res( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ const float *input_8k, /* i : input buffer sampled at 8kHz*/ @@ -4384,29 +4581,29 @@ void stereo_dft_enc_res( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_write_BS() * * Write DFT stereo bitstream *-------------------------------------------------------------------------*/ - -void stereo_dft_enc_write_BS( +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_write_BS_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - int16_t *nb_bits /* o : number of bits written */ + Word16 *nb_bits /* o : number of bits written */ ) { - int16_t b, k_offset, itd, nb, nbands, sp_aud_decision0; - int16_t NFFT_inner, nbands_full; - int16_t no_GR_ord; - int16_t encoded_ind_GR[STEREO_DFT_BAND_MAX]; - int16_t encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; - int16_t sid_gIpd_index, sid_itd; - float cohBand[STEREO_DFT_BAND_MAX / 2]; + Word16 b, k_offset, itd, nb, nbands, sp_aud_decision0; + Word16 NFFT_inner, nbands_full; + Word16 no_GR_ord; + Word16 encoded_ind_GR[STEREO_DFT_BAND_MAX]; + Word16 encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; + Word16 sid_gIpd_index, sid_itd; + Word32 cohBand[STEREO_DFT_BAND_MAX / 2]; BSTR_ENC_HANDLE hBstr; STEREO_DFT_ENC_DATA_HANDLE hStereoDft; - int32_t core_brate; + Word32 core_brate; /*------------------------------------------------------------------* * Initialization @@ -4415,84 +4612,497 @@ void stereo_dft_enc_write_BS( hStereoDft = hCPE->hStereoDft; hBstr = hCPE->hMetaData; core_brate = hCPE->hCoreCoder[0]->core_brate; + move32(); sp_aud_decision0 = 0; - if ( hCPE->last_element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) { sp_aud_decision0 = hCPE->hCoreCoder[0]->sp_aud_decision0; + move16(); } *nb_bits = 0; + move16(); k_offset = STEREO_DFT_OFFSET; + move16(); nbands_full = hStereoDft->nbands; + move16(); - if ( core_brate == FRAME_NO_DATA || core_brate == SID_2k40 ) + test(); + IF( EQ_32( core_brate, FRAME_NO_DATA ) || EQ_32( core_brate, SID_2k40 ) ) { - NFFT_inner = min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); + NFFT_inner = s_min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); hStereoDft->band_res[k_offset] = hStereoDft->hConfig->band_res; + move16(); hStereoDft->res_pred_mode[k_offset] = 0; + move16(); hStereoDft->res_cod_mode[k_offset] = 0; + move16(); } - else + ELSE { - NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + // NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + NFFT_inner = shl( inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth], 1 ); } /* set number of bands according to bandwidth after BWD */ -#ifndef IVAS_FLOAT_FIXED - hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); -#else hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); -#endif + move16(); - if ( core_brate == FRAME_NO_DATA ) + IF( EQ_32( core_brate, FRAME_NO_DATA ) ) { /* No data frame */ ( *nb_bits ) = 0; + move16(); return; } /* attack present */ /* attackPresent not sent in inactive frames, receiver assumes = 0 */ - if ( core_brate != SID_2k40 ) + IF( NE_32( core_brate, SID_2k40 ) ) { push_indice( hBstr, IND_STEREO_DFT_ATTACK_PRESENT, hStereoDft->attackPresent, 1 ); - ( *nb_bits )++; + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); } /* Writing coding residual coding mode into bitstream */ - if ( hStereoDft->hConfig->ada_wb_res_cod_mode && hCPE->hCoreCoder[0]->bwidth == WB ) + test(); + IF( hStereoDft->hConfig->ada_wb_res_cod_mode && EQ_16( hCPE->hCoreCoder[0]->bwidth, WB ) ) { push_indice( hBstr, IND_STEREO_DFT_RES_COD, hStereoDft->res_cod_mode[k_offset], 1 ); - ( *nb_bits )++; + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; - hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + move16(); + hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + move16(); } - if ( nbands_full < hStereoDft->nbands ) + if ( LT_16( nbands_full, hStereoDft->nbands ) ) { hStereoDft->reverb_flag = 0; + move16(); } /* Side gains */ hStereoDft->side_gain_flag_1 = 0; /* EC coding by default */ - side_gain_mode_decision( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); + move16(); + side_gain_mode_decision_fx( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); /* residual pred. gains */ hStereoDft->res_pred_flag_1 = 0; /* EC coding by default */ + move16(); - res_pred_gain_mode_decision( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); + res_pred_gain_mode_decision_fx( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); /*------------------------------------------------------------------* * write ITD indices *-----------------------------------------------------------------*/ - if ( core_brate != SID_2k40 ) + IF( NE_32( core_brate, SID_2k40 ) ) { - push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); - ( *nb_bits ) += STEREO_DFT_ITD_MODE_NBITS; /*ITD mode flag: 1bit*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd_fx[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_MODE_NBITS ); /*ITD mode flag: 1bit*/ + move16(); + } + + IF( NE_32( core_brate, SID_2k40 ) ) + { + IF( hStereoDft->hItd->itd_fx[k_offset] ) + { + itd = hStereoDft->hItd->itd_index[k_offset]; + move16(); + IF( GT_16( itd, 255 ) ) + { + itd = sub( itd, 256 ); + + IF( LT_16( itd, 20 ) ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); + ( *nb_bits ) = add( *nb_bits, add( dft_len_itd[itd], 2 ) ); + move16(); + } + ELSE + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 0, 1 ); /* don't use Huffman */ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS - 1 ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_NBITS + 1 ); + move16(); + } + } + ELSE + { + IF( LT_16( itd, 20 ) ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 0, 1 ); /* positive */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); + ( *nb_bits ) = add( *nb_bits, add( dft_len_itd[itd], 2 ) ); + move16(); + } + ELSE + { + /* don't use Huffman and positive*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS + 1 ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_NBITS + 1 ); + move16(); + } + } + } + } + +#ifdef DEBUG_MODE_DFT_BITS + fprintf( ITD_bits, "%d ", *nb_bits ); +#endif + + /*------------------------------------------------------------------* + * write Side gain indices + *-----------------------------------------------------------------*/ + + /* Side Gain flag 1 */ + nb = 0; + move16(); + IF( hStereoDft->side_gain_flag_1 > 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, 2 ); + nb = add( nb, 2 ); + } + ELSE + { + push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); + } + + no_GR_ord = 3; + move16(); + + IF( hStereoDft->side_gain_flag_1 == 0 ) + { + nb = add( nb, write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, encoded_ind_GR, hStereoDft->nbands, hStereoDft->side_gain_flag_2, no_GR_ord ) ); + } + ELSE{ + IF( EQ_16( hStereoDft->side_gain_flag_1, 2 ) ){ + nb = add( nb, write_bitstream_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_ECDiff, hStereoDft->nbands, hStereoDft->side_gain_flag_2 - no_GR_ord ) ); +} +ELSE +{ + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + /*ILD*/ + push_indice( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_EC[b], STEREO_DFT_SIDEGAIN_NBITS ); + nb = add( nb, STEREO_DFT_SIDEGAIN_NBITS ); + } +} +} + +/* nb bits are used for side gain*/ +( *nb_bits ) = add( *nb_bits, nb ); +move16(); +#ifdef DEBUG_MODE_DFT_BITS +fprintf( SG_bits, "%d ", nb ); +#endif +nb = 0; +move16(); + +IF( EQ_32( core_brate, SID_2k40 ) ) +{ + stereo_dft_enc_sid_calc_coh_fx( hStereoDft, hCPE->hStereoCng->prev_cohBand_fx, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); + + IF( LE_16( *nb_bits, ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) ) + { + IF( NE_32( hStereoDft->hItd->itd_fx[k_offset], 0 ) ) + { + /* Re-quantize ITD with lower resolution for Stereo CNG */ + itd = hStereoDft->hItd->itd_index[k_offset]; + move16(); + if ( GT_16( itd, 255 ) ) + { + itd = sub( itd, 256 ); + } + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); + + sid_itd = itd && 1; + move16(); + } + ELSE + { + sid_itd = 0; + move16(); + } + + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, sid_itd, STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_MODE_NBITS ); /*ITD mode flag: 1bit*/ + move16(); + + IF( sid_itd ) + { + itd = hStereoDft->hItd->itd_index[k_offset]; + move16(); + IF( GT_16( itd, 255 ) ) + { + itd = sub( itd, 256 ); + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); + + if ( GT_16( itd, ( ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1 ) ) ) + { + itd = ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1; + move16(); + } + + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_SID_ITD_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_SID_ITD_NBITS + 1 ); + move16(); + } + ELSE + { + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); + + if ( GT_16( itd, ( ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1 ) ) ) + { + itd = ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1; + move16(); + } + + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 0, 1 ); /* Positive */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_SID_ITD_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_SID_ITD_NBITS + 1 ); + move16(); + } + } + } +} + +/*------------------------------------------------------------------* + * write IPD indices + *-----------------------------------------------------------------*/ + +IF( NE_32( core_brate, SID_2k40 ) ) +{ + push_indice( hBstr, IND_STEREO_DFT_NO_IPD_FLAG, hStereoDft->no_ipd_flag, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*IPD mode flag: 1bit*/ + + IF( hStereoDft->no_ipd_flag == 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_GIPD, hStereoDft->gipd_index, STEREO_DFT_GIPD_NBITS ); + nb = add( nb, STEREO_DFT_GIPD_NBITS ); + } +} +ELSE IF( LE_16( *nb_bits, ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS ) ) ) +{ + push_indice( hBstr, IND_STEREO_DFT_NO_IPD_FLAG, hStereoDft->no_ipd_flag, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*IPD mode flag: 1bit*/ + + IF( hStereoDft->no_ipd_flag == 0 ) + { + stereo_dft_quantize_ipd_fx( &hStereoDft->sid_gipd_fx, &hStereoDft->sid_gipd_fx, &sid_gIpd_index, STEREO_DFT_SID_GIPD_NBITS ); + push_indice( hBstr, IND_STEREO_DFT_GIPD, sid_gIpd_index, STEREO_DFT_SID_GIPD_NBITS ); + nb = add( nb, STEREO_DFT_SID_GIPD_NBITS ); + } +} + + +#ifdef DEBUG_MODE_DFT_BITS +fprintf( IPD_bits, "%d ", nb ); +#endif +( *nb_bits ) = add( *nb_bits, nb ); + +/*----------------------------------------------------------------* + * Residual prediction + *----------------------------------------------------------------*/ + +nb = 0; /* bits for residual pred gains */ +move16(); +IF( hStereoDft->res_pred_mode[k_offset] ) +{ + IF( hStereoDft->attackPresent == 0 ) + { + nbands = s_min( hStereoDft->nbands, STEREO_DFT_RES_PRED_BAND_MAX ); + b = hStereoDft->res_pred_band_min; + move16(); + + /*Adaptive SF*/ + IF( hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) + { + /*read flag*/ + push_indice( hBstr, IND_STEREO_DFT_REVERB_MODE, hStereoDft->reverb_flag, STEREO_DFT_REVERB_MODE_NBITS ); + nb = add( nb, STEREO_DFT_REVERB_MODE_NBITS ); + IF( hStereoDft->reverb_flag ) + { + nbands = sub( nbands, STEREO_DFT_RES_PRED_BAND_MIN_CONST ); + } + } + + /* Res Pred Gain flag 0 */ + IF( hStereoDft->res_pred_flag_1 > 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_RES_PRED_FLAG, hStereoDft->res_pred_flag_1, 2 ); + nb = add( nb, 2 ); /*pred gain mode flag: 2 bits*/ + } + ELSE + { + push_indice( hBstr, IND_STEREO_DFT_RES_PRED_FLAG, hStereoDft->res_pred_flag_1, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*pred gain mode flag: 1bit*/ + } + + no_GR_ord = 2; + move16(); + IF( hStereoDft->res_pred_flag_1 == 0 ) + { + IF( EQ_16( encoded_ind_pred_GR[0], dft_maps_rpg[8 * NO_SYMB_GR_PRED_G] ) ) + { + nb = add( nb, write_GR1( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, encoded_ind_pred_GR, 1 ) ); + } + ELSE + { + nb = add( nb, write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, encoded_ind_pred_GR, nbands - hStereoDft->res_pred_band_min, hStereoDft->res_pred_flag_2, 2 ) ); + } + } + ELSE + { + IF( EQ_16( hStereoDft->res_pred_flag_1, 2 ) ) + { + nb = add( nb, write_bitstream_GR( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, &hStereoDft->res_pred_index_ECDiff[hStereoDft->res_pred_band_min], nbands - hStereoDft->res_pred_band_min, hStereoDft->res_pred_flag_2 - no_GR_ord ) ); + } + ELSE + { + FOR( b = hStereoDft->res_pred_band_min; b < nbands; b++ ) + { + push_indice( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, hStereoDft->res_pred_index_EC[b], STEREO_DFT_RES_GAINS_BITS ); + nb = add( nb, STEREO_DFT_RES_GAINS_BITS ); + } + } + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, sub( hStereoDft->nbands, hStereoDft->res_pred_band_min ) ); + } +} +ELSE +{ + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands - hStereoDft->res_pred_band_min ); +} + +( *nb_bits ) = add( *nb_bits, nb ); + +IF( EQ_32( core_brate, SID_2k40 ) ) +{ + stereo_dft_enc_sid_coh_fx( hBstr, hCPE->hStereoCng->mem_cohBand_fx, hStereoDft->nbands, nb_bits, cohBand ); +} + + +return; +} +#else +void stereo_dft_enc_write_BS( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + int16_t *nb_bits /* o : number of bits written */ +) +{ + int16_t b, k_offset, itd, nb, nbands, sp_aud_decision0; + int16_t NFFT_inner, nbands_full; + int16_t no_GR_ord; + int16_t encoded_ind_GR[STEREO_DFT_BAND_MAX]; + int16_t encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; + int16_t sid_gIpd_index, sid_itd; + float cohBand[STEREO_DFT_BAND_MAX / 2]; + BSTR_ENC_HANDLE hBstr; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + int32_t core_brate; + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + hStereoDft = hCPE->hStereoDft; + hBstr = hCPE->hMetaData; + core_brate = hCPE->hCoreCoder[0]->core_brate; + + sp_aud_decision0 = 0; + if ( hCPE->last_element_mode == IVAS_CPE_DFT ) + { + sp_aud_decision0 = hCPE->hCoreCoder[0]->sp_aud_decision0; + } + + *nb_bits = 0; + k_offset = STEREO_DFT_OFFSET; + + nbands_full = hStereoDft->nbands; + + if ( core_brate == FRAME_NO_DATA || core_brate == SID_2k40 ) + { + NFFT_inner = min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); + hStereoDft->band_res[k_offset] = hStereoDft->hConfig->band_res; + hStereoDft->res_pred_mode[k_offset] = 0; + hStereoDft->res_cod_mode[k_offset] = 0; + } + else + { + NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + } + + /* set number of bands according to bandwidth after BWD */ +#ifndef IVAS_FLOAT_FIXED + hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); +#else + hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); +#endif + + if ( core_brate == FRAME_NO_DATA ) + { + /* No data frame */ + ( *nb_bits ) = 0; + return; + } + + /* attack present */ + /* attackPresent not sent in inactive frames, receiver assumes = 0 */ + if ( core_brate != SID_2k40 ) + { + push_indice( hBstr, IND_STEREO_DFT_ATTACK_PRESENT, hStereoDft->attackPresent, 1 ); + ( *nb_bits )++; + } + + /* Writing coding residual coding mode into bitstream */ + if ( hStereoDft->hConfig->ada_wb_res_cod_mode && hCPE->hCoreCoder[0]->bwidth == WB ) + { + push_indice( hBstr, IND_STEREO_DFT_RES_COD, hStereoDft->res_cod_mode[k_offset], 1 ); + ( *nb_bits )++; + hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; + hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + } + + + if ( nbands_full < hStereoDft->nbands ) + { + hStereoDft->reverb_flag = 0; + } + + /* Side gains */ + hStereoDft->side_gain_flag_1 = 0; /* EC coding by default */ + side_gain_mode_decision( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); + + /* residual pred. gains */ + hStereoDft->res_pred_flag_1 = 0; /* EC coding by default */ + + res_pred_gain_mode_decision( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); + + /*------------------------------------------------------------------* + * write ITD indices + *-----------------------------------------------------------------*/ + + if ( core_brate != SID_2k40 ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) += STEREO_DFT_ITD_MODE_NBITS; /*ITD mode flag: 1bit*/ } if ( core_brate != SID_2k40 ) @@ -4767,7 +5377,7 @@ void stereo_dft_enc_write_BS( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_compute_prm() @@ -5994,7 +6604,82 @@ static void stereo_dft_enc_compute_prm( * * *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void side_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_GR[], + const Word16 sp_aud_decision0, /* i : Speech/audio decision 0 */ + const Word32 last_core_brate /* i : Last core bitrate */ +) +{ + Word16 try_diff, nb_diff, no_GR_ord, n_bits, i; + try_diff = sp_aud_decision0; + move16(); + IF( try_diff ) + { + IF( EQ_16( hStereoDft->side_gain_counter, STEREO_DFT_FEC_THRESHOLD ) ) + { + try_diff = 0; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + } + ELSE + { + hStereoDft->side_gain_counter = 0; + move16(); + } + + /* If last frame SID/NO_DATA do not use differential coding */ + if ( LE_32( last_core_brate, SID_2k40 ) ) + { + try_diff = 0; + move16(); + } + no_GR_ord = 3; + move16(); + hStereoDft->side_gain_flag_2 = adapt_GR_ief_fx( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, + hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, + hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp_fx, &hStereoDft->q_side_gain_bitdiff_lp, try_diff ); + move16(); + + FOR( i = 0; i < hStereoDft->nbands; i++ ) + { + hStereoDft->side_gain_index_ECprevious[i] = hStereoDft->side_gain_index_EC[i]; + move16(); + } + + IF( GT_16( n_bits, sub( imult1616( hStereoDft->nbands, STEREO_DFT_SIDE_GAIN_NBITS ), 1 ) ) ) + { + /* use fixed rate */ + hStereoDft->side_gain_flag_1 = 3; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + ELSE + { + IF( GE_32( hStereoDft->side_gain_flag_2, no_GR_ord ) ) + { + hStereoDft->side_gain_flag_1 = 2; + move16(); + hStereoDft->side_gain_counter = add( hStereoDft->side_gain_counter, 1 ); + move16(); + } + ELSE + { + hStereoDft->side_gain_flag_1 = 0; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + } + + return; +} +#else static void side_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ int16_t encoded_ind_GR[], @@ -6024,16 +6709,10 @@ static void side_gain_mode_decision( try_diff = 0; } no_GR_ord = 3; -#ifdef IVAS_FLOAT_FIXED - hStereoDft->side_gain_flag_2 = adapt_GR_ief_fx( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, - hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, - hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp_fx, &hStereoDft->q_side_gain_bitdiff_lp, try_diff ); -#else + hStereoDft->side_gain_flag_2 = adapt_GR_ief( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp, try_diff ); -#endif - for ( i = 0; i < hStereoDft->nbands; i++ ) { @@ -6062,7 +6741,7 @@ static void side_gain_mode_decision( return; } - +#endif /*---------------------------------------------------------------------* * res_pred_gain_mode_decision() @@ -6070,6 +6749,103 @@ static void side_gain_mode_decision( * *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void res_pred_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_pred_GR[], + const Word16 k_offset, /* i : Parameter offset */ + const Word32 last_core_brate /* i : Last core bitrate */ +) +{ + Word16 nb_diff, try_diff, no_GR_ord, i, n_bits; + Word16 nbands; + + /* Residual Prediction Gain */ + IF( hStereoDft->res_pred_mode[k_offset] ) + { + IF( hStereoDft->attackPresent == 0 ) + { + nbands = s_min( hStereoDft->nbands, STEREO_DFT_RES_PRED_BAND_MAX ); + + if ( hStereoDft->reverb_flag ) + { + nbands = sub( nbands, STEREO_DFT_RES_PRED_BAND_MIN_CONST ); + } + + try_diff = 1; + move16(); + IF( EQ_16( hStereoDft->res_pred_counter, STEREO_DFT_FEC_THRESHOLD ) ) + { + try_diff = 0; + move16(); + hStereoDft->res_pred_counter = 0; + move16(); + } + + /* If last frame SID/NO_DATA do not use differential coding */ + IF( LE_32( last_core_brate, SID_2k40 ) ) + { + try_diff = 0; + move16(); + } + + no_GR_ord = 2; + move16(); + + hStereoDft->res_pred_flag_2 = adapt_GR_rpg1_ief( &hStereoDft->res_pred_index_EC[hStereoDft->res_pred_band_min], &hStereoDft->res_pred_index_ECDiff[hStereoDft->res_pred_band_min], &hStereoDft->res_pred_index_ECprevious[hStereoDft->res_pred_band_min], nbands - hStereoDft->res_pred_band_min, NO_SYMB_GR_PRED_G, &n_bits, encoded_ind_pred_GR, dft_maps_rpg, &nb_diff, no_GR_ord, try_diff ); + move16(); + + FOR( i = 0; i < nbands; i++ ) + { + hStereoDft->res_pred_index_ECprevious[i] = hStereoDft->res_pred_index_EC[i]; + move16(); + } + + FOR( ; i < hStereoDft->nbands; i++ ) + { + hStereoDft->res_pred_index_ECprevious[i] = 0; + move16(); + } + + IF( GT_16( n_bits, sub( imult1616( sub( nbands, hStereoDft->res_pred_band_min ), STEREO_DFT_RES_GAINS_BITS ), 1 ) ) ) + { + hStereoDft->res_pred_flag_1 = 3; + move16(); + hStereoDft->res_pred_counter = 0; + move16(); + } + ELSE + { + IF( GT_16( hStereoDft->res_pred_flag_2, 1 ) ) + { + /* differential coding */ + hStereoDft->res_pred_flag_1 = 2; + move16(); + hStereoDft->res_pred_counter = add( hStereoDft->res_pred_counter, 1 ); + move16(); + } + ELSE + { + hStereoDft->res_pred_counter = 0; + move16(); + hStereoDft->res_pred_flag_1 = 0; + move16(); + } + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands ); + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands ); + } + + return; +} +#else static void res_pred_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ int16_t encoded_ind_pred_GR[], @@ -6151,7 +6927,7 @@ static void res_pred_gain_mode_decision( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_calc_mean_bipd() diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index 2115cc652765abe120221be784959e504b42670d..effd61ed8f0f58af6c8a86d8dd245cbd2a3d91a2 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -40,6 +40,7 @@ #include "prot.h" #include "prot_fx.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_enc.h" @@ -121,7 +122,7 @@ static void set_band_limits_fx( return; } -#endif +#else static void set_band_limits( int16_t *nbands, int16_t band_limits[STEREO_DFT_BAND_MAX + 1], @@ -138,7 +139,7 @@ static void set_band_limits( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_hybrid_ITD_flag() @@ -212,7 +213,7 @@ static void stereo_dft_quantize_itd_fx( return; } -#endif +#else static void stereo_dft_quantize_itd( const int16_t in, float *out, @@ -238,7 +239,7 @@ static void stereo_dft_quantize_itd( return; } - +#endif /*------------------------------------------------------------------------- * itd_vad_ms_snr_calc() @@ -320,7 +321,7 @@ static Word32 itd_vad_ms_snr_calc_fx( return ( ms_snr ); } -#endif +#else static float itd_vad_ms_snr_calc( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], float *Spd, @@ -359,7 +360,7 @@ static float itd_vad_ms_snr_calc( return ( ms_snr ); } - +#endif /*------------------------------------------------------------------------- * itd_vad_background_update() @@ -464,7 +465,7 @@ static void itd_vad_background_update_fx( return; } -#endif +#else static void itd_vad_background_update( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], int16_t *vad_frm_cnt, @@ -510,7 +511,7 @@ static void itd_vad_background_update( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_itd_vad() * @@ -570,7 +571,7 @@ static Word16 stereo_dft_enc_itd_vad_fx( return ( vad_flag_itd ); } -#endif +#else static int16_t stereo_dft_enc_itd_vad( float E_band_n[STEREO_DFT_ITD_VAD_BAND_NUM], int16_t *vad_frm_cnt, @@ -611,7 +612,7 @@ static int16_t stereo_dft_enc_itd_vad( return ( vad_flag_itd ); } - +#endif /*------------------------------------------------------------------------- * calc_mean_E_ratio() @@ -791,7 +792,7 @@ static Word32 calc_mean_E_ratio_fx( // return ( sum_Er * B_DENOM ); return Mpy_32_32( sum_Er, B_DENOM_Q31 ); } -#endif +#else static float calc_mean_E_ratio( ITD_DATA_HANDLE hItd, int16_t nbands, @@ -859,7 +860,7 @@ static float calc_mean_E_ratio( return ( sum_Er * B_DENOM ); } - +#endif /*------------------------------------------------------------------------- * resetEstimates() @@ -884,7 +885,7 @@ static void resetEstimates_fx( return; } -#endif +#else static void resetEstimates( ITD_DATA_HANDLE hItd ) { @@ -895,7 +896,7 @@ static void resetEstimates( return; } - +#endif /*------------------------------------------------------------------------- * td_sm_filter() * @@ -929,7 +930,7 @@ static void td_sm_filter_fx( return; } -#endif +#else static void td_sm_filter( float *x, float *y, @@ -953,7 +954,7 @@ static void td_sm_filter( return; } - +#endif /*------------------------------------------------------------------------- * peak_detect() * @@ -1151,7 +1152,7 @@ static Word32 peak_detect_fx( // 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 + wfac = 805306368; // 1.5f in Q29 move32(); } ELSE @@ -1175,7 +1176,7 @@ static Word32 peak_detect_fx( return Mpy_32_32( wfac, avg_max ); // 2+sum_max_e } } -#endif +#else static float peak_detect( float *xcorr_itd, float *max_max, @@ -1320,7 +1321,7 @@ static float peak_detect( return ( wfac * avg_max ); } } - +#endif /*------------------------------------------------------------------------- * Compute stereo parameter: ITD @@ -1329,17 +1330,17 @@ static float peak_detect( #ifdef IVAS_FLOAT_FIXED void stereo_dft_enc_compute_itd_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - Word32 *DFT_L, + Word32 *DFT_L, /* i : exp : DFT_L_e */ Word16 *DFT_L_e, - Word32 *DFT_R, + Word32 *DFT_R, /* i : exp : DFT_R_e */ Word16 *DFT_R_e, const Word16 k_offset, const Word16 input_frame, const Word16 vad_flag_dtx[], const Word16 vad_hover_flag[], - Word32 *bin_nrgL, + Word32 *bin_nrgL, /* i : exp : bin_nrgL_e */ Word16 *bin_nrgL_e, - Word32 *bin_nrgR, + Word32 *bin_nrgR, /* i : exp : bin_nrgR_e */ Word16 *bin_nrgR_e ) { Word16 i, j; @@ -1889,7 +1890,8 @@ void stereo_dft_enc_compute_itd_fx( 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 + // sfm_R = L_shl_r( sfm_R, sfm_R_e ); // Q31 + sfm_R = L_shl_sat( sfm_R, sfm_R_e ); // Q31 } if ( sfm_R > sfm_L ) @@ -2013,8 +2015,6 @@ void stereo_dft_enc_compute_itd_fx( 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 ); @@ -2029,6 +2029,7 @@ void stereo_dft_enc_compute_itd_fx( { /* Reset cross spectrum when there is hangover */ set32_fx( hStereoDft->xspec_smooth_fx, 0, STEREO_DFT_N_32k_ENC ); + set16_fx( hStereoDft->xspec_smooth_fx_e, 0, STEREO_DFT_N_32k_ENC ); hStereoDft->resetFrames = 0; move16(); hStereoDft->currentNumUpdates = 0; @@ -2053,12 +2054,12 @@ void stereo_dft_enc_compute_itd_fx( { /* 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] ); + 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] ), hStereoDft->xspec_smooth_fx_e[2 * i], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i] ), xcorr_e[2 * i], &hStereoDft->xspec_smooth_fx_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] ); + 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] ), hStereoDft->xspec_smooth_fx_e[2 * i + 1], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &hStereoDft->xspec_smooth_fx_e[2 * i + 1] ); move32(); /* Low pass filter L/R power spectrum */ @@ -2127,18 +2128,18 @@ void stereo_dft_enc_compute_itd_fx( { // 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 ); + Copy( hStereoDft->xspec_smooth_fx_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] ); + hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i] ), hStereoDft->xspec_smooth_fx_e[2 * i], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i] ), xcorr_e[2 * i], &hStereoDft->xspec_smooth_fx_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] ); + 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] ), hStereoDft->xspec_smooth_fx_e[2 * i + 1], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &hStereoDft->xspec_smooth_fx_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], @@ -2223,19 +2224,6 @@ void stereo_dft_enc_compute_itd_fx( /* 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] ); @@ -2578,7 +2566,7 @@ void stereo_dft_enc_compute_itd_fx( 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 ) ) + IF( flag_noisy_speech_snr == 0 && hCPE->hCoreCoder[0]->vad_flag == 1 && hItd->detected_itd_flag == 0 && ( LT_16( hItd->currFlatness_fx, 192 ) /* 1.5 in Q7*/ || 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) */ @@ -2964,6 +2952,7 @@ void stereo_dft_enc_compute_itd_fx( return; } #endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_compute_itd( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float *DFT_L, @@ -3728,3 +3717,4 @@ void stereo_dft_enc_compute_itd( return; } +#endif diff --git a/lib_enc/ivas_stereo_dft_td_itd.c b/lib_enc/ivas_stereo_dft_td_itd.c index c3673647fab720a8e2caa61bba5fb46f6a0249f3..5c7b73a015153d7b22a90266cf773e68a218eb04 100644 --- a/lib_enc/ivas_stereo_dft_td_itd.c +++ b/lib_enc/ivas_stereo_dft_td_itd.c @@ -441,22 +441,23 @@ static void stereo_td_channel_extrapolate_fx( 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] ) ); + shift_input[i] = extract_h( L_mac0( L_mult0( g_lpc, shift_input[i] ), g, sts[leading_channel]->input_fx[i] ) ); // Q = 14 + q_shift - 16 + move16(); } - Word16 q_temp = 14 + q_shift - 15; + Word16 q_temp = sub( q_shift, 2 ); /* 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; + Word16 e_shift = 0; 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 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] ) ) ); // q_shift-1(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 ); + temp1 = L_add( temp1, temp2 ); // q_shift-1 + shift_input[i] = BASOP_Util_Divide3232_Scale( temp1, pred_ovlp, &e_shift ); // Q=15-e_shift+q_shift-1 + move16(); + shift_input[i] = shr( shift_input[i], sub( add( sub( 15, e_shift ), sub( q_shift, 1 ) ), q_temp ) ); // q_temp + move16(); } // scaling whole buffer to q_temp// @@ -465,15 +466,6 @@ static void stereo_td_channel_extrapolate_fx( 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; } @@ -771,6 +763,7 @@ void stereo_td_itd_fx( ELSE { Copy( shift_mem, mdct_mem[ch], input_frame ); + Scale_sig( mdct_mem[ch], input_frame, sub( sts[ch]->q_inp, *q_input_mem ) ); } } } @@ -784,7 +777,7 @@ void stereo_td_itd_fx( * * Time-domain ITD in MDCT stereo * ---------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void stereo_td_itd_mdct_stereo( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ @@ -824,3 +817,62 @@ void stereo_td_itd_mdct_stereo( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +void stereo_td_itd_mdct_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : frame length */ +) +{ + Word16 i; + Word32 bin_nrgL_fx[STEREO_DFT_N_32k_ENC]; + Word16 bin_nrgL_e[STEREO_DFT_N_32k_ENC]; + Word32 bin_nrgR_fx[STEREO_DFT_N_32k_ENC]; + Word16 bin_nrgR_e[STEREO_DFT_N_32k_ENC]; + Word32 DFT_fx[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC]; + Word16 DFT_e[CPE_CHANNELS]; + Word16 DFT_tmp_e[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC]; + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct; + + IF( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + hStereoMdct = hCPE->hStereoMdct; + + hCPE->hStereoMdct->hItd->td_itd_32k[STEREO_DFT_OFFSET] = 0; + move16(); + hStereoMdct->hItd->td_itd[STEREO_DFT_OFFSET] = 0; + move16(); + + /* Update the parameters */ + FOR( i = 0; i < STEREO_DFT_OFFSET; i++ ) + { + hStereoMdct->hItd->deltaItd_fx[i] = hStereoMdct->hItd->deltaItd_fx[i + 1]; + move32(); + hStereoMdct->hItd->td_itd[i] = hStereoMdct->hItd->td_itd[i + 1]; + move16(); + hStereoMdct->hItd->td_itd_32k[i] = hStereoMdct->hItd->td_itd_32k[i + 1]; + move16(); + } + + stereo_dft_enc_analyze_fx( hCPE->hCoreCoder, CPE_CHANNELS, input_frame, NULL, hStereoMdct, DFT_fx, DFT_e, hCPE->input_mem_fx, hCPE->q_input_mem ); + + FOR( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + DFT_tmp_e[0][i] = DFT_e[0]; + move16(); + DFT_tmp_e[1][i] = DFT_e[1]; + move16(); + } + + /*call ITD function*/ + stereo_dft_enc_compute_itd_fx( hCPE, DFT_fx[0], DFT_tmp_e[0], DFT_fx[1], DFT_tmp_e[1], STEREO_DFT_OFFSET, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL_fx, bin_nrgL_e, bin_nrgR_fx, bin_nrgR_e ); + + /* Time Domain ITD compensation using extrapolation */ + stereo_td_itd_fx( hStereoMdct->hItd, NULL, NULL, 1, hStereoMdct->hDft_ana->dft_ovl, hCPE->hCoreCoder, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); + } + + return; +} +#endif diff --git a/lib_enc/ivas_stereo_eclvq_enc.c b/lib_enc/ivas_stereo_eclvq_enc.c index 8fecfc41497b0cebe94919f1b9d343d862360932..39ededb6471bd510cc880350fcb9dcc6aa356410 100644 --- a/lib_enc/ivas_stereo_eclvq_enc.c +++ b/lib_enc/ivas_stereo_eclvq_enc.c @@ -34,11 +34,13 @@ #include "options.h" #include #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_enc.h" #include #include "prot.h" +#include "prot_fx.h" #include "wmc_auto.h" /* used only for norm_s in the code_length_from_count function */ #include "stl.h" @@ -50,30 +52,61 @@ * * ---------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static double log_base2( double x ) { return log( x ) * INV_LOG_2; } +#endif /*--------------------------------------------------------------- * get_sign() * * * ---------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static Word16 get_sign_fx( Word16 n ) +{ + return extract_l( L_shr( (UWord16) n, 15 ) ); /* extract the sign bit */ +} +#else static int16_t get_sign( int16_t n ) { return (uint16_t) n >> 15; /* extract the sign bit */ } - +#endif /*--------------------------------------------------------------- * ECSQ_quantize_vector() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ECSQ_quantize_vector_fx( + const Word32 *input, + const Word16 input_e, + const Word32 global_gain, // Q15 + const Word16 N, + Word16 *output ) +{ + Word16 i; + Word32 inv_global_gain; + Word16 inv_global_gain_e; + + // inv_global_gain = 1.0f / global_gain; + inv_global_gain = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q15, global_gain, &inv_global_gain_e ); + inv_global_gain = L_shl( inv_global_gain, inv_global_gain_e ); // Q31 + FOR( i = 0; i < N; ++i ) + { + // output[i] = (int16_t) round_f( input[i] * inv_global_gain ); + output[i] = extract_l( L_shr_r( Mpy_32_32( input[i], inv_global_gain ), sub( 31, input_e ) ) ); + move16(); + } + return; +} +#else void ECSQ_quantize_vector( const float *input, const float global_gain, @@ -91,6 +124,7 @@ void ECSQ_quantize_vector( return; } +#endif /*--------------------------------------------------------------- * ECSQ_compute_optimal_gain() @@ -98,7 +132,43 @@ void ECSQ_quantize_vector( * compute the optimal global gain for dequantization of output * if all the values in output are zero, it returns 0 * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word32 ECSQ_compute_optimal_gain_fx( // Q15 + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word16 *output ) +{ + Word16 i; + Word32 sum_sq_output; + Word32 sum_input_output; + Word32 optimal_global_gain; + Word16 optimal_global_gain_e; + + sum_sq_output = 0; + move32(); + sum_input_output = 0; + move32(); + FOR( i = 0; i < N; ++i ) + { + // sum_sq_output += (float) output[i] * (float) output[i]; + sum_sq_output = L_add( sum_sq_output, L_shl( L_mult0( output[i], output[i] ), 15 ) ); // Q15 + // sum_input_output += input[i] * (float) output[i]; + sum_input_output = L_add( sum_input_output, L_shr( W_extract_l( W_mult0_32_32( input[i], output[i] ) ), sub( 16, input_e ) ) ); // Q15 + } + optimal_global_gain = 0; + move32(); + IF( sum_sq_output != 0 ) + { + // optimal_global_gain = sum_input_output / sum_sq_output; + optimal_global_gain = BASOP_Util_Divide3232_Scale_cadence( sum_input_output, sum_sq_output, &optimal_global_gain_e ); + optimal_global_gain = L_shr( optimal_global_gain, sub( 16, optimal_global_gain_e ) ); // Q15 + } + + return optimal_global_gain; +} +#else float ECSQ_compute_optimal_gain( const float *input, const int16_t N, @@ -125,6 +195,7 @@ float ECSQ_compute_optimal_gain( return optimal_global_gain; } +#endif /*--------------------------------------------------------------- * ECSQ_quantize_gain() @@ -132,6 +203,30 @@ float ECSQ_compute_optimal_gain( * quantize global gain * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ECSQ_quantize_gain_fx( + Word32 global_gain ) // Q15 +{ + Word16 index; + + // global_gain = max(global_gain, 1.0f); /* because always index >= 0 anyway */ + global_gain = L_max( global_gain, ONE_IN_Q15 ); + + /* min gain = 1 (index 0), max gain ~= 29145 (index 126), domain range ~= 90 dB, resolution 90 / 127 ~= 0.7 dB */ + /* value 127 (ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO) is reserved and indicates that all values in the vector are zero */ + + // index = (int16_t) ( ECLVQ_GLOBAL_GAIN_FACTOR * log10f( global_gain ) + 0.4898f ); + index = extract_l( L_shr( L_add( Mpy_32_32( ECLVQ_GLOBAL_GAIN_FACTOR_Q26, BASOP_Util_Log10( global_gain, 16 ) ), 513592 /*0.4898f in Q20*/ ), 20 ) ); + + /* for MSE quantization, the value f in (0, 1) is the middle between consecutive quantization points in the linear scale */ + /* 10 ^ (inv_global_gain_factor * f) - 1 = 10 ^ inv_global_gain_factor - 10 ^ (inv_global_gain_factor * f) */ + /* f = 0.5102, and when applying floor to convert to integer, 1 - f = 0.4898 must be used as the offset */ + + index = s_min( s_max( index, 0 ), 126 ); + + return index; +} +#else static int16_t ECSQ_quantize_gain( float global_gain ) { @@ -153,13 +248,34 @@ static int16_t ECSQ_quantize_gain( return index; } +#endif /*--------------------------------------------------------------- * arith_encode_bit() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bit_fx( + ECSQ_instance *ecsq_inst, + const Word16 bit ) +{ + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, 1024 ); /* 1024 eq 1 << 10, 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_bits( rc_st_enc, bit, 1 ); + } + + return; +} +#else static void arith_encode_bit( ECSQ_instance *ecsq_inst, const int16_t bit ) @@ -178,13 +294,33 @@ static void arith_encode_bit( return; } - +#endif /*--------------------------------------------------------------- * arith_encode_bits() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bits_fx( + ECSQ_instance *ecsq_inst, + const UWord16 n, + Word16 size ) +{ + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, L_shl( size, 10 ) ); /* 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + rc_uni_enc_encode_bits( rc_st_enc, n, size ); + } + return; +} +#else static void arith_encode_bits( ECSQ_instance *ecsq_inst, const uint16_t n, @@ -203,14 +339,36 @@ static void arith_encode_bits( return; } - +#endif /*--------------------------------------------------------------- * code_length_from_count() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 code_length_from_count_fx( // Q10 + const Word16 c ) +{ + /* compute the approximation of code length, 14 - log2(c), in 22Q10 fixed-point representation */ + /* with c in {1, ..., 2 ^ 14}, representing a probability count in 14-bit AC implementations */ + Word16 c_norm; + Word16 res; + +#define WMC_TOOL_SKIP + c_norm = norm_s( (Word16) c ); /* equivalent with 14 - floor(log_base2(c)) */ +#undef WMC_TOOL_SKIP + + /* compute linear approximation of log2(1 + x), for x in [0, 1], using a look-up table with 64 entries */ + /* normalize to {16384, ..., 32767}, subtract MSB bit, and convert to Q6 for indexing log2_1px_table */ + res = sub( shl( c_norm, 10 ), log2_1px_table[( ( c << c_norm ) - ( 1 << 14 ) + ( 1 << 7 ) ) >> 8] ); + + /* |(14 - log2(c)) - res / (1 << 10)| < 0.0113, for c in {1, ..., 2 ^ 14} */ + /* complexity: 1 norm_s, 2 adds, 3 shifts, 1 table lookup */ + return res; +} +#else static int16_t code_length_from_count( const int16_t c ) { @@ -232,13 +390,43 @@ static int16_t code_length_from_count( /* complexity: 1 norm_s, 2 adds, 3 shifts, 1 table lookup */ return res; } - +#endif /*--------------------------------------------------------------- * arith_encode_bit_prob() * * encoding for one bit with the probabilies prob_0 = count0 / 2 ^ ECSQ_PROB_BITS and prob_1 = 1 - prob_0 * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bit_prob_fx( + ECSQ_instance *ecsq_inst, + const Word16 count0, + const Word16 bit ) +{ + Word16 count; + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + + count = sub( ECSQ_PROB_TOTAL, count0 ); + + IF( bit == 0 ) + { + count = count0; + move16(); + } + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, code_length_from_count_fx( count ) ); /* 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_fast( rc_st_enc, bit * count0, count, 14 ); + } + + return; +} +#else static void arith_encode_bit_prob( ECSQ_instance *ecsq_inst, const int16_t count0, @@ -266,13 +454,41 @@ static void arith_encode_bit_prob( return; } - +#endif /*--------------------------------------------------------------- * arith_encode_prob() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_prob_fx( + ECSQ_instance *ecsq_inst, + const UWord16 table[], + const Word16 table_size, + const Word16 symbol ) +{ + Word16 count; + RangeUniEncState *rc_st_enc; + + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + count = table_size; /* just to avoid warning when DEBUGGING is deactivated */ + move16(); + + count = sub( table[symbol], table[symbol + 1] ); + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, code_length_from_count_fx( count ) ); /* 22Q10 fixed-point representation */ + move16(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_fast( rc_st_enc, ECSQ_PROB_TOTAL - table[symbol], count, 14 ); + } + return; +} +#else static void arith_encode_prob( ECSQ_instance *ecsq_inst, const uint16_t table[], @@ -298,13 +514,46 @@ static void arith_encode_prob( return; } +#endif /*--------------------------------------------------------------- * arith_encode_elias_mod() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_elias_mod_fx( + ECSQ_instance *ecsq_inst, + const Word16 n ) +{ + Word16 i; + + IF( LE_16( n, 1 ) ) + { + /* code for 0 is 10 and code for 1 is 11 */ + arith_encode_bit_fx( ecsq_inst, 1 ); + arith_encode_bit_fx( ecsq_inst, n ); + } + ELSE /* n >= 2 */ + { + /* code consists of n_bits zero bits, an one bit, and n_bits data bits */ + Word16 n_bits; + /* n_bits is floor(log_2(n)), the number of bits after the leading one bit */ + n_bits = sub( 30, norm_l( n ) ); + FOR( i = 0; i < n_bits; i++ ) + { + arith_encode_bit_fx( ecsq_inst, 0 ); + } + arith_encode_bit_fx( ecsq_inst, 1 ); + + /* encode the n_bits data bits at once */ + arith_encode_bits_fx( ecsq_inst, n - ( 1 << n_bits ), n_bits ); + } + + return; +} +#else static void arith_encode_elias_mod( ECSQ_instance *ecsq_inst, const int16_t n ) @@ -336,13 +585,34 @@ static void arith_encode_elias_mod( return; } +#endif /*--------------------------------------------------------------- * arith_encode_prob_escape() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_prob_escape_fx( + ECSQ_instance *ecsq_inst, + const UWord16 table[], + const Word16 table_size, + const Word16 symbol ) +{ + IF( LT_16( symbol, sub( table_size, 1 ) ) ) + { + arith_encode_prob_fx( ecsq_inst, table, table_size, symbol ); + } + ELSE + { + arith_encode_prob_fx( ecsq_inst, table, table_size, sub( table_size, 1 ) ); /* escape symbol */ + /* encode the additional value using a modified Elias integer code */ + arith_encode_elias_mod_fx( ecsq_inst, sub( symbol, sub( table_size, 1 ) ) ); + } + return; +} +#else static void arith_encode_prob_escape( ECSQ_instance *ecsq_inst, const uint16_t table[], @@ -362,14 +632,87 @@ static void arith_encode_prob_escape( return; } - +#endif /*--------------------------------------------------------------- * get_best_param() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 get_best_param_fx( + Word16 *x, + const Word16 start_offset, + const Word16 stop_offset, + Word32 *avg_abs_sum, // Q10 + Word16 *N0 ) +{ + Word16 v; + Word16 val; + Word32 sum_abs; // Q10 + Word16 count; + Word16 count0; + Word16 param; + Word16 L_tmp_e; + + const Word16 offset = INV_LOG_2_FX; /* offset = 1 / ln(2) and log2(offset) ~ 0.528766 */ + + sum_abs = 0; + move16(); + count = add( sub( stop_offset, start_offset ), 1 ); + count0 = 0; + move16(); + + /* compute sum(abs(x[v])) and sum(x[v] == 0) */ + FOR( v = start_offset; v <= stop_offset; ++v ) + { + + val = x[v]; + move16(); + sum_abs = L_add( sum_abs, L_shl( abs_s( val ), 10 ) ); // Q10 + IF( val == 0 ) + { + ++count0; + move16(); + } + } + + + /* the vector has at most ECSQ_NONZERO_MAX values of +-1 and the rest are zeros */ + test(); + IF( LE_16( sub( count, count0 ), ECSQ_NONZERO_MAX ) && EQ_32( sum_abs, L_shl( sub( count, count0 ), 10 ) ) ) + { + //*avg_abs_sum = ( sum_abs + 0.25f * count0 ) / count; + *avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( sum_abs, L_shl( count0, 8 ) ), L_shl( count, 10 ), &L_tmp_e ); + move32(); + *avg_abs_sum = L_shr_r( *avg_abs_sum, sub( 21, L_tmp_e ) ); // Q10 + move32(); + *N0 = count0; + move16(); + + return ECSQ_ALL_ZERO_PARAM; + } + + //*avg_abs_sum = ( sum_abs + 0.25f * count0 ) / count; + *avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( sum_abs, L_shl( count0, 8 ) ), L_shl( count, 10 ), &L_tmp_e ); + move32(); + *avg_abs_sum = L_shr_r( *avg_abs_sum, sub( 21, L_tmp_e ) ); // Q10 + move32(); + *N0 = count0; + move16(); + /* the best Laplace integer parameter is floor(log2(avg_abs_sum) + log2(offset)) */ + // param = (int16_t) floor( log_base2( *avg_abs_sum * offset ) ); + param = sub( 31, norm_l( L_sub( L_shr( Mpy_32_16_1( *avg_abs_sum, offset ), 10 - 1 ), 1 ) ) ); + // sub( 31, norm_l( L_sub( n, 1 ) ) ) + + /* limit param value to the available exponent range */ + param = s_max( ECSQ_ALL_ZERO_PARAM + 1, param ); + param = s_min( param, ECSQ_ALL_ZERO_PARAM + ECSQ_PARAM_COUNT - 1 ); + + return param; +} +#else static int16_t get_best_param( int16_t *x, const int16_t start_offset, @@ -424,7 +767,7 @@ static int16_t get_best_param( return param; } - +#endif /*--------------------------------------------------------------- * get_est_size() @@ -433,7 +776,81 @@ static int16_t get_best_param( * ---------------------------------------------------------------*/ #define ECSQ_log2TB_FIRST_PARAM -2 +#ifdef IVAS_FLOAT_FIXED +static Word32 get_est_size_fx( // Q10 + const Word16 N, + Word32 avg_abs_sum, // Q10 + const Word16 N0, + Word16 param ) +{ + Word32 size; // Q10 + // Word32 two_to_param; + // Word16 two_to_param_e; + + // two_to_param = (float) ( 1 << abs( param ) ); + // two_to_param = 1 << abs_s( param ) ; + // if ( param < 0 ) + //{ + // //two_to_param = 1.0f / two_to_param; + // two_to_param = BASOP_Util_Divide3232_Scale_cadence( 1, two_to_param,&two_to_param_e); + // } + + IF( NE_16( param, ECSQ_ALL_ZERO_PARAM ) ) /* not all values are zeros */ + { + Word16 index; + index = sub( param, ECSQ_log2TB_FIRST_PARAM ); + index = s_min( index, ECSQ_log2TB_SIZE - 2 ); + + + /* the estimated size in bits is N * log2(2 * 2 ^ param) + */ + /* + N * log2(e) * (avg_abs_sum / 2 ^ param) - (N - N0) * log2(T(2 ^ param)) - */ + /* - N0 * log2(T(2 * 2 ^ param)) */ + // size = N * ( 1 + param + INV_LOG_2 * ( avg_abs_sum / two_to_param ) ); + size = W_extract_l( W_mult0_32_32( N, L_add( L_shl( add( 1, param ), 10 ), Mpy_32_16_1( L_shr( avg_abs_sum, sub( param, 1 /*compesating for INV_LOG_2_FX*/ ) ), INV_LOG_2_FX ) ) ) ); // Q10 + // size -= ( N - N0 ) * log2TB[index]; + size = L_sub( size, Mpy_32_32( L_shl( sub( N, N0 ), 10 ), log2TB_Q31[index] ) ); // Q10 + // size -= N0 * log2TB[index + 1]; + size = L_sub( size, Mpy_32_32( L_shl( N0, 10 ), log2TB_Q31[index + 1] ) ); // Q10 + } + ELSE + { + /* used for all zero values or for very low entropy with number of nonzeros <= ECSQ_NONZERO_MAX */ + Word16 nonzero; + Word32 required_avg_abs_sum; // Q10 + Word16 required_avg_abs_sum_e; + + nonzero = sub( N, N0 ); + + // required_avg_abs_sum = ( nonzero + 0.25f * N0 ) / N; /* the vector must have nonzero +-1 and N0 zeros */ + required_avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( L_shl( nonzero, 10 ), L_shl( N0, 8 ) ), L_shl( N, 10 ), &required_avg_abs_sum_e ); /* the vector must have nonzero +-1 and N0 zeros */ + required_avg_abs_sum = L_shr_r( required_avg_abs_sum, sub( 21, required_avg_abs_sum_e ) ); // Q10 + + test(); + IF( EQ_32( avg_abs_sum, required_avg_abs_sum ) && LE_16( nonzero, ECSQ_NONZERO_MAX ) ) + { + // size = 2.0f; /* log_base2(1 + ECSQ_NONZERO_MAX), indicate the nonzero count */ + size = 2 << 10; /* log_base2(1 + ECSQ_NONZERO_MAX), indicate the nonzero count */ + move32(); + + /* the number of bits for the nonzero mask is log2(nchoosek(N, nonzero)) */ + // size += ECSQ_log2_fact[N] - ECSQ_log2_fact[N - nonzero] - ECSQ_log2_fact[nonzero]; + size = L_add( size, L_sub( L_sub( ECSQ_log2_fact_Q10[N], ECSQ_log2_fact_Q10[N - nonzero] ), ECSQ_log2_fact_Q10[nonzero] ) ); + + // size += (float) nonzero; /* indicate the signs for nonzero values */ + size = L_add( size, L_shl( nonzero, 10 ) ); /* indicate the signs for nonzero values */ + } + ELSE + { + /* the method cannot be used, return a huge value so that it will never be chosen */ + // size = 1.0e11f; + size = MAX_32; + move32(); + } + } + return size; +} +#else static float get_est_size( const int16_t N, float avg_abs_sum, @@ -491,14 +908,213 @@ static float get_est_size( return size; } - +#endif /*--------------------------------------------------------------- * ECSQ_encode_raw() * * encode input, which contains a concatenation of quantized RE8 integer-valued vectors; * the return value is the approximate number of bits written, expressed in 22Q10 fixed-point representation * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word32 ECSQ_encode_raw_fx( + ECSQ_instance *ecsq_inst, + Word16 *input, + const Word16 N ) +{ + int32_t bit_count_estimate_initial; + + Word32 total_size; // Q10 + Word16 segment_count; + + Word16 seg_length, seg_start, seg_stop, segment, seg_count0; + Word32 est_size; + + Word16 est_param, first_param, last_param, param; + Word32 best_size, test_size; // Q10 + Word16 best_param, best_params[ECSQ_VECTOR_SIZE_MAX / ECSQ_SEGMENT_SIZE]; + Word16 saved_seg_count0[ECSQ_VECTOR_SIZE_MAX / ECSQ_SEGMENT_SIZE]; + + Word32 avg_abs_sum; // Q10 + // const Word32 scale_Q10 = ONE_IN_Q21;// 1.0f / 1024.0f + Word16 i, idx, shift, val, sym, nonzero, left0, left1, count, count0, lsbs; + Word16 param_zb, best_param_zb; /* zero-based parameter index for coding */ + const UWord16 *tab_vals, *tab_abs_lsbs; + + bit_count_estimate_initial = ecsq_inst->bit_count_estimate; + + + total_size = 0; + move32(); + // segment_count = ( N + ECSQ_SEGMENT_SIZE - 1 ) / ECSQ_SEGMENT_SIZE; + segment_count = shr( add( N, ECSQ_SEGMENT_SIZE - 1 ), 3 ); + + FOR( segment = 0; segment < segment_count; ++segment ) + { + seg_start = imult1616( segment, ECSQ_SEGMENT_SIZE ); + seg_stop = sub( s_min( add( seg_start, ECSQ_SEGMENT_SIZE ), N ), 1 ); + seg_length = add( sub( seg_stop, seg_start ), 1 ); + + est_param = get_best_param_fx( input, seg_start, seg_stop, &avg_abs_sum, &seg_count0 ); + saved_seg_count0[segment] = seg_count0; + move16(); + + /* find the best param around est_param for the current segment count */ + best_size = MAX_32 - 1; // 1.0e10f ? + move32(); + best_param = -1000; + move16(); + + IF( EQ_16( est_param, ECSQ_ALL_ZERO_PARAM ) ) /* all values are zero */ + { + first_param = ECSQ_ALL_ZERO_PARAM; + move16(); + last_param = ECSQ_ALL_ZERO_PARAM + 2 * ECSQ_PARAM_SEARCH_RANGE; + move16(); + } + ELSE + { + first_param = s_max( ECSQ_ALL_ZERO_PARAM, sub( est_param, ECSQ_PARAM_SEARCH_RANGE ) ); + last_param = s_min( add( est_param, ECSQ_PARAM_SEARCH_RANGE ), ECSQ_ALL_ZERO_PARAM + ECSQ_PARAM_COUNT - 1 ); + } + + FOR( param = first_param; param <= last_param; ++param ) + { + param_zb = sub( param, ECSQ_ALL_ZERO_PARAM ); + count = ECSQ_tab_param[ecsq_inst->config_index][param_zb] - ECSQ_tab_param[ecsq_inst->config_index][param_zb + 1]; + // test_size = scale_Q10 * code_length_from_count( count ); + test_size = code_length_from_count_fx( count ); // Q10 + + test_size = L_add_sat( test_size, get_est_size_fx( seg_length, avg_abs_sum, seg_count0, param ) ); // if test_size > best_size we don't select + + IF( LT_32( test_size, best_size ) ) + { + best_param = param; + move16(); + best_size = test_size; + move32(); + } + } + + best_params[segment] = best_param; + total_size = L_add( total_size, best_size ); + } + + IF( !ecsq_inst->encoding_active ) /* only size estimation is needed */ + { + // est_size = (int32_t) ( total_size * 1024.0 + 0.5 ); /* 22Q10 fixed-point representation */ + est_size = total_size; /* 22Q10 fixed-point representation */ + move32(); + + return est_size; + } + + /* encode with the best parameters: best_params[] */ + FOR( segment = 0; segment < segment_count; ++segment ) + { + seg_start = imult1616( segment, ECSQ_SEGMENT_SIZE ); + seg_stop = add( seg_start, ECSQ_SEGMENT_SIZE - 1 ); + seg_length = ECSQ_SEGMENT_SIZE; + IF( EQ_16( segment, sub( segment_count, 1 ) ) ) + { + seg_stop = sub( N, 1 ); + seg_length = add( sub( seg_stop, seg_start ), 1 ); + } + + best_param_zb = sub( best_params[segment], ECSQ_ALL_ZERO_PARAM ); + shift = s_max( 0, sub( best_param_zb, 3 ) ); /* first nonzero shift of 1 is used for param 3 */ + + arith_encode_prob_fx( ecsq_inst, ECSQ_tab_param[ecsq_inst->config_index], ECSQ_PARAM_COUNT, best_param_zb ); + + /* encode the actual values if not using the ECSQ_ALL_ZERO_PARAM parameter */ + IF( best_param_zb != 0 ) + { + tab_vals = ECSQ_tab_vals[best_param_zb - 1]; + idx = s_min( shift, 4 ); + tab_abs_lsbs = ECSQ_tab_abs_lsbs[idx]; + + FOR( i = seg_start; i <= seg_stop; ++i ) + { + val = input[i]; + move16(); + sym = abs_s( val ); + + IF( shift != 0 ) + { + lsbs = s_and( sym, sub( shl( 1, shift ), 1 ) ); + sym = shr( sym, shift ); + + arith_encode_prob_escape_fx( ecsq_inst, tab_vals, ECSQ_TAB_VALS_SIZE, sym ); + + test(); + IF( ( sym > 0 ) || GT_16( shift, 4 ) ) + { + arith_encode_bits_fx( ecsq_inst, lsbs, shift ); + } + ELSE /* (sym == 0) && (shift <= 4) */ + { + arith_encode_prob_fx( ecsq_inst, tab_abs_lsbs, shl( 1, shift ), lsbs ); + } + } + ELSE /* shift == 0 */ + { + arith_encode_prob_escape_fx( ecsq_inst, tab_vals, ECSQ_TAB_VALS_SIZE, sym ); + } + + IF( val != 0 ) + { + arith_encode_bit_fx( ecsq_inst, get_sign_fx( val ) ); + } + } + } + ELSE + { + nonzero = sub( seg_length, saved_seg_count0[segment] ); + + + arith_encode_bits_fx( ecsq_inst, nonzero, 2 ); /* log_base2(ECSQ_NONZERO_MAX + 1) == 2 */ + + left1 = nonzero; + move16(); + left0 = sub( seg_length, nonzero ); + + FOR( i = seg_start; i <= seg_stop; ++i ) + { + val = input[i]; + move16(); + sym = abs_s( val ); + + + IF( left1 == 0 ) + { + } + ELSE IF( left0 == 0 ) + { + } + ELSE + { + count0 = imult1616( left0, ECSQ_tab_inverse[left0 + left1] ); /* left0 * round(ECSQ_PROB_TOTAL / (left0 + left1)) */ + arith_encode_bit_prob_fx( ecsq_inst, count0, sym ); + } + IF( sym != 0 ) + { + arith_encode_bit_fx( ecsq_inst, get_sign_fx( val ) ); + --left1; + move16(); + } + ELSE + { + --left0; + move16(); + } + } + } + } + + + return L_sub( ecsq_inst->bit_count_estimate, bit_count_estimate_initial ); +} +#else static int32_t ECSQ_encode_raw( ECSQ_instance *ecsq_inst, int16_t *input, @@ -679,7 +1295,7 @@ static int32_t ECSQ_encode_raw( return ecsq_inst->bit_count_estimate - bit_count_estimate_initial; } - +#endif /*--------------------------------------------------------------- * ECSQ_encode_target_SNR() @@ -693,6 +1309,185 @@ static int32_t ECSQ_encode_raw( #define ECSQ_MAX_BITS_ITERATIONS 2 +#ifdef IVAS_FLOAT_FIXED +Word32 ECSQ_encode_target_SNR_fx( + ECSQ_instance *ecsq_inst, + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word32 target_SNR, // Q25 + const Word16 max_bits, + Word32 *output, + Word16 *global_gain_index_output ) +{ + Word16 global_gain_index; + Word16 global_gain_index_last; /* used to potentially save one call to ECSQ_quantize_vector */ + Word16 quantized_input[ECSQ_VECTOR_SIZE_MAX]; + Word16 saved_encoding_active; + Word32 saved_bit_count_estimate; + Word32 test_size /*Q10*/, adjust_size; + Word16 i, iteration; + Word32 global_gain /*Q15*/, adjust_global_gain_index; + Word16 global_gain_e; + Word32 max_bits_fixpt; + Word32 sum_squared, target_ratio, target_sum_squared_error; + Word16 sum_squared_e, target_ratio_e, target_sum_squared_error_e; + // const Word32 global_gain_step = 1165018877; // powf( 10.0f, ECLVQ_INV_GLOBAL_GAIN_FACTOR ) in Q30 + Word32 L_tmp1; + Word16 L_tmp1_e; + + // max_bits_fixpt = max_bits * 1024; /* max_bits_fixpt is in 22Q10 fixed-point representation */ + max_bits_fixpt = L_shl( max_bits, 10 ); /* max_bits_fixpt is in 22Q10 fixed-point representation */ + + IF( LE_32( target_SNR, 0 ) ) + { + /* a target SNR of 0.0 dB is already achieved by quantizing all values in the vector to zero */ + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + sum_squared = 0; + move32(); + sum_squared_e = 0; + move16(); + FOR( i = 0; i < N; ++i ) + { + // sum_squared += input[i] * input[i]; + sum_squared = BASOP_Util_Add_Mant32Exp( sum_squared, sum_squared_e, Mpy_32_32( input[i], input[i] ), shl( input_e, 1 ), &sum_squared_e ); + } + + // if ( sum_squared < 0.25f ) /* all the values in the input vector will always be quantized to zero */ + IF( BASOP_Util_Cmp_Mant32Exp( sum_squared, sum_squared_e, ONE_IN_Q29, 0 ) < 0 ) /* all the values in the input vector will always be quantized to zero */ + { + /* the condition above holds because sum(input[i] ^ 2) < 0.25 => max(abs(input[i])) < 0.5 */ + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + /* save internal state and activate size evaluation only */ + saved_encoding_active = ecsq_inst->encoding_active; + move32(); + saved_bit_count_estimate = ecsq_inst->bit_count_estimate; + move32(); + ecsq_inst->encoding_active = 0; + move16(); + + /* target_ratio is the target ratio between the sum squared values of input and sum squared values of quantization error */ + // target_ratio = powf( 10.0f, target_SNR / 10.0f ); + L_tmp1 = BASOP_Util_Divide3232_Scale_cadence( target_SNR, 10, &L_tmp1_e ); + L_tmp1_e = add( L_tmp1_e, 6 - 31 ); + target_ratio = BASOP_Util_fPow( 10 << 27, 4, L_tmp1, L_tmp1_e, &target_ratio_e ); + // target_sum_squared_error = sum_squared / target_ratio; + target_sum_squared_error = BASOP_Util_Divide3232_Scale_cadence( sum_squared, target_ratio, &target_sum_squared_error_e ); + target_sum_squared_error_e = add( target_sum_squared_error_e, sub( sum_squared_e, target_ratio_e ) ); + + /* the mean of squared quantization error for uniform scalar quantization is 1 / 12, approximately 0.0833 */ + /* when including global_gain, the relationship is target_sum_squared_error ~ (0.0833 * N) * global_gain ^ 2 */ + /* the representable range for global_gain is from 1 (global_gain_index 0) to 29145 (global_gain_index 126) inclusive */ + // global_gain = sqrtf( target_sum_squared_error / ( 0.0833f * (float) N ) ); + global_gain = BASOP_Util_Divide3232_Scale_cadence( target_sum_squared_error, L_mult0( 5459 /*0.0833f in Q16*/, N ), &global_gain_e ); + global_gain_e = add( global_gain_e, sub( target_sum_squared_error_e, 15 ) ); + global_gain = L_shr( global_gain, sub( 16, global_gain_e ) ); // Q15 + /* quantize the estimated global_gain */ + global_gain_index = ECSQ_quantize_gain_fx( global_gain ); + + iteration = 0; + move16(); + + /* do the quantization with the dequantized estimated global_gain_index found */ + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + global_gain_index_last = global_gain_index; + move16(); + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + + test_size = ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + ++iteration; + move16(); + Word16 tmp_e; + WHILE( GT_32( test_size, max_bits_fixpt ) && LT_16( iteration, ECSQ_MAX_BITS_ITERATIONS ) ) + { + test(); + adjust_size = L_sub( test_size, max_bits_fixpt ); + /* assume doubling the quantization step size will reduce the entropy with (up to) one bit */ + // adjust_global_gain_index = (int16_t) ceil( adjust_size / ( 1024.0f * N * log_base2( global_gain_step ) ) ); + adjust_global_gain_index = BASOP_Util_Divide3232_Scale_cadence( adjust_size, N, &tmp_e ); + adjust_global_gain_index = Mpy_32_32( adjust_global_gain_index, 17816838 /*/ ( 1024.0f * log_base2( global_gain_step ) )*/ ); + adjust_global_gain_index = extract_l( L_shr( L_add( adjust_global_gain_index, L_shl( 1, sub( 31, tmp_e ) ) ), sub( 31, tmp_e ) ) ); + global_gain_index = s_min( add( global_gain_index, (Word16) adjust_global_gain_index ), 126 ); + + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + global_gain_index_last = global_gain_index; + move16(); + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + + test_size = ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + ++iteration; + move16(); + } + + IF( GT_32( test_size, max_bits_fixpt ) ) + { + /* further increase the quantization step with the smallest increment for global_gain_index */ + global_gain_index = s_min( global_gain_index + 1, 126 ); + } + + /* restore internal state */ + ecsq_inst->encoding_active = saved_encoding_active; + move16(); + ecsq_inst->bit_count_estimate = saved_bit_count_estimate; + move32(); + + /* do the quantization with the dequantized final global_gain_index found */ + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + + IF( global_gain_index != global_gain_index_last ) + { + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + } + + global_gain = ECSQ_compute_optimal_gain_fx( input, input_e, N, quantized_input ); + + IF( global_gain == 0 ) /* all values in quantized_input are zero */ + { + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + global_gain_index = ECSQ_quantize_gain_fx( global_gain ); + *global_gain_index_output = global_gain_index; + move16(); + + + IF( output != NULL ) + { + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); + ECSQ_dequantize_vector_fx( quantized_input, global_gain, N, output ); + } + + ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + return L_sub( ecsq_inst->bit_count_estimate, saved_bit_count_estimate ); +} +#else int32_t ECSQ_encode_target_SNR( ECSQ_instance *ecsq_inst, const float *input, @@ -832,3 +1627,4 @@ int32_t ECSQ_encode_target_SNR( return ecsq_inst->bit_count_estimate - saved_bit_count_estimate; } +#endif diff --git a/lib_enc/ivas_stereo_ica_enc.c b/lib_enc/ivas_stereo_ica_enc.c index 4ea6055b25e54c6325125228a4455d86e58610e6..1bbd497e5fe364ad8615346ff98f22799d481b99 100644 --- a/lib_enc/ivas_stereo_ica_enc.c +++ b/lib_enc/ivas_stereo_ica_enc.c @@ -45,14 +45,28 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "ivas_rom_com_fx.h" #endif /*--------------------------------------------------------------- * Local function prototypes * ---------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static void unclr_calc_corr_features_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + Word32 buf1[], /* i : left channel */ + Word32 buf2[], /* i : right channel */ + Word16 q_com, + const Word16 length, /* i : length of input signal buffers */ + Word32 corrEst[], /* i : buffer containing inter-channel correlation values */ + Word16 corrEst_exp, + const int16_t lagSearchRange[], /* i : minimum and maximum lags for corrEst[] */ + Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers */ + Word16 *corrEst_ncorr_exp ); +#else static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STEREO_TCA_ENC_HANDLE hStereoTCA, const float buf1[], const float buf2[], const int16_t length, const float corrEst[], const int16_t lagSearchRange[], float *corrEst_ncorr ); - +#endif /*-------------------------------------------------------------------* * Local constants @@ -67,6 +81,17 @@ static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STER #define SMOOTH_DIST_FACTOR 0.4f #define SMOOTH_ENV_FACTOR 0.6f +#define XL_BIAS_FX_Q15 6554 +#define XH_BIAS_FX_Q15 13107 +#define XL_WIDTH_FX_Q15 3932 +#define XH_WIDTH_FX_Q15 4915 +#define SMOOTH_DIST_FACTOR_FX_Q15 14418 +#define A_BIAS_FX_Q15 3277 +#define B_BIAS_FX_Q15 -16384 +#define A_WIDTH_FX_Q31 32212264 +#define B_WIDTH_FX_Q31 32212192 +#define SMOOTH_ENV_FACTOR_FX_Q15 19661 + #define A_BIAS ( ( XH_BIAS - XL_BIAS ) / ( YH_DIST - YL_DIST ) ) #define B_BIAS ( XH_BIAS - ( A_BIAS * YH_DIST ) ) #define A_WIDTH ( ( XH_WIDTH - XL_WIDTH ) / ( YH_DIST - YL_DIST ) ) @@ -78,7 +103,125 @@ static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STER * * Temporal channel adjustment of LA samples in target channel * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void tcaTargetCh_LA_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, + Word32 *ptrChanL, + Word32 *ptrChanR, + Word16 *q_com, + const Word16 currentNCShift, + const Word16 input_frame ) +{ + Word16 i, j; + Word16 tempS, temp, sine_inp; + Word32 tempF1, tempF2, gAdj; + Word16 tempF1_exp, tempF2_exp, gAdj_exp; + + Word32 *ref, *target; + Word16 ref_exp, target_exp, target_exp_temp[L_FRAME48k + L_FRAME48k]; + Word16 win[240]; /* 5 ms at 48 kHz */ + + ref_exp = sub( 31, *q_com ); + target_exp = sub( 31, *q_com ); + set16_fx( target_exp_temp, target_exp, L_FRAME48k + 30 ); + + IF( EQ_16( hStereoTCA->refChanIndx, L_CH_INDX ) ) + { + ref = ptrChanL; + target = ptrChanR; + } + ELSE + { + ref = ptrChanR; + target = ptrChanL; + } + + tempS = NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ); + tempF1 = 0; + move32(); + tempF1_exp = 0; + move32(); + tempF2 = 0; + move32(); + tempF2_exp = 0; + move16(); + FOR( i = 0; i < sub( input_frame, currentNCShift ); i++ ) + { + tempF1 = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, L_abs( ref[i] ), ref_exp, &tempF1_exp ); + tempF2 = BASOP_Util_Add_Mant32Exp( tempF2, tempF2_exp, L_abs( target[i + currentNCShift] ), target_exp, &tempF2_exp ); + } + + IF( tempF1 == 0 ) + { + gAdj = ONE_IN_Q31; + move32(); + gAdj_exp = 0; + move16(); + } + ELSE + { + Word32 deno = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, -21475 /*0.00001f in Q31*/, 0, &temp ); + Word16 deno_exp; + IF( deno > 0 ) + { + deno = tempF1; + deno_exp = tempF1_exp; + } + ELSE + { + deno = 21475; + deno_exp = 0; + } + move32(); + move32(); + gAdj = BASOP_Util_Divide3232_Scale_cadence( tempF2, deno, &gAdj_exp ); + gAdj_exp = add( gAdj_exp, sub( tempF2_exp, deno_exp ) ); + } + + FOR( i = 0; i < tempS; i++ ) + { + sine_inp = BASOP_Util_Divide1616_Scale( add( shl( i, 10 ), 512 ), shl( tempS, 1 ), &temp ); + sine_inp = shl_sat( sine_inp, add( temp, -10 ) ); + win[i] = getSineWord16R2( shr( sine_inp, 1 ) ); + move16(); + } + + j = 0; + move16(); + + Word16 exp_com = target_exp_temp[0]; + move16(); + FOR( i = sub( input_frame, add( currentNCShift, tempS ) ); i < sub( input_frame, currentNCShift ); ( i++, j++ ) ) + { + target[i + currentNCShift] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( Mpy_32_16_1( gAdj, win[j] ), ref[i] ), add( ref_exp, gAdj_exp ), Mpy_32_16_1( target[i + currentNCShift], sub( MAX_16, win[j] ) ), target_exp, &temp ); + move32(); + target_exp_temp[i + currentNCShift] = temp; + move16(); + exp_com = s_max( exp_com, temp ); + } + + FOR( ; i < input_frame; i++ ) + { + target[i + currentNCShift] = Mpy_32_32( gAdj, ref[i] ); + move32(); + target_exp_temp[i + currentNCShift] = add( gAdj_exp, ref_exp ); + move16(); + exp_com = s_max( exp_com, target_exp_temp[i + currentNCShift] ); + } + + FOR( i = 0; i < input_frame; i++ ) + { + target[i] = L_shl( target[i], sub( target_exp_temp[i], exp_com ) ); + move32(); + ref[i] = L_shl( ref[i], sub( ref_exp, exp_com ) ); + move32(); + } + *q_com = sub( 31, exp_com ); + move16(); + return; +} +#else static void tcaTargetCh_LA( STEREO_TCA_ENC_HANDLE hStereoTCA, float *ptrChanL, @@ -132,7 +275,7 @@ static void tcaTargetCh_LA( return; } - +#endif /*--------------------------------------------------------------- * spectral_balancer() * @@ -232,6 +375,88 @@ void spectral_balancer_fx16( return; } + +void spectral_balancer_fx( + Word32 *signal, /* i/o : signal Qx */ + Word32 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +) +{ + Word16 i; + Word32 x0, x1, x2, y0, y1, y2; + Word32 a1, a2, b0, b1, b2; + + y1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + move32(); + move32(); + move32(); + move32(); + + /* hp filter 60Hz at 3dB for 8000KHz sampling rate + 1. [b,a] = butter(1, 60.0/8000.0, 'high'); + 2. spectral_balancing_filter + < maybe not needed>> + b =[1, -1] [1, -0.6] + a =[1, -0.95395255590776329] [1, 0.5] */ + IF( coeff_set == 0 ) + { + a1 = 401466258; // Q29 + move32(); + a2 = -146144282; // Q29 + move32(); + b0 = 271120363; // Q29 + move32(); + b1 = -542240726; // Q29 + move32(); + b2 = 271120363; // Q29 + move32(); + } + ELSE + { + a1 = -72242031; // Q29 + move32(); + a2 = -208379437; // Q29 + move32(); + b0 = 536870912; // Q29 + move32(); + b1 = -1072703858; // Q29 + move32(); + b2 = 536870912; // Q29 + move32(); + } + + FOR( i = 0; i < lg; i++ ) + { + x2 = x1; + move16(); + x1 = x0; + move16(); + x0 = signal[i]; + move16(); + y0 = W_extract_l( W_shr( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mult_32_32( a1, y1 ), a2, y2 ), b0, x0 ), b1, x1 ), b2, x2 ), 30 ) ); // Qx + signal[i] = y0; + move16(); + y2 = y1; + move16(); + y1 = y0; + move16(); + } + + mem[0] = y1; + move32(); + mem[1] = y2; + move32(); + mem[2] = x0; + move32(); + mem[3] = x1; + move32(); + + return; +} #endif // IVAS_FLOAT_FIXED void spectral_balancer( @@ -297,7 +522,60 @@ void spectral_balancer( * * De-emphasize and resample the L and R channels. * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void deEmphResample( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA encoder handle */ + const Word32 *tempChan1_fx, /* i : Stereo data Qx*/ + const Word32 *tempChan2_fx, /* i : Stereo data Qx*/ + Word32 *chan1_fx, // Qx + Word32 *chan2_fx, // Qx + const Word16 input_frame, + const Word16 dsFactor ) +{ + Word32 buf1_fx[L_FRAME48k], buf2_fx[L_FRAME48k]; + Word32 tempBuf1_fx[2 * L_FRAME_DS], tempBuf2_fx[2 * L_FRAME_DS]; + Word16 i; + Word16 dsFac1, dsFac2; + + /* Estimate first and second stage downsample factors */ + dsFac1 = shr( dsFactor, 1 ); + dsFac2 = idiv1616( dsFactor, dsFac1 ); + + /* convert stereo data to two distinct channels, e.g., L, R */ + Copy32( tempChan1_fx, buf1_fx, input_frame ); + Copy32( tempChan2_fx, buf2_fx, input_frame ); + + /* De-emphasis, 1/(1-mu z^-1), and resample, stage 1 */ + + deemph_fx_32( 0, buf1_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[0] ); + deemph_fx_32( 0, buf2_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[1] ); + + FOR( i = 0; i < idiv1616( input_frame, dsFac1 ); i++ ) + { + tempBuf1_fx[i] = buf1_fx[i * dsFac1]; + move32(); + tempBuf2_fx[i] = buf2_fx[i * dsFac1]; + move32(); + } + + /* De-emphasis, 1/(1-mu z^-1), and resample, stage 2 */ + deemph_fx_32( 0, tempBuf1_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[2] ); + deemph_fx_32( 0, tempBuf2_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[3] ); + + FOR( i = 0; i < idiv1616( input_frame, dsFactor ); i++ ) + { + chan1_fx[i] = tempBuf1_fx[i * dsFac2]; + move32(); + chan2_fx[i] = tempBuf2_fx[i * dsFac2]; + move32(); + } + spectral_balancer_fx( chan1_fx, &hStereoTCA->memdecim_fx[4], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */ + spectral_balancer_fx( chan2_fx, &hStereoTCA->memdecim_fx[8], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */ + + return; +} +#else static void deEmphResample( STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA encoder handle */ const float *tempChan1, /* i : Stereo data */ @@ -345,14 +623,117 @@ static void deEmphResample( return; } - +#endif /*--------------------------------------------------------------- * utilCrossCorr_mod() * * Biased crossCorr estimation between buf1, buf2 over the * lag range of (lagSearchRange[0], lagSearchRange[1]). * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void utilCrossCorr_mod_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + const Word32 *buf1, + const Word32 *buf2, + const Word16 q_com, + Word32 *corrEst, /* o : correlation estimate */ + Word16 *corrEst_Exp, /* o : correlation estimate */ + const Word16 *lagSearchRange, + const Word16 len ) +{ + Word32 C, E1, E2, C_C_mem; + Word16 i, j, E1_exp, E2_exp, E1E2_exp, Inv_Tot_E_exp, k, C_exp, exp; + Word16 Inv_Tot_E, corrEst_exp[2 * L_NCSHIFT_DS + 1]; + Word64 L64_sum; + + set16_fx( corrEst_exp, -1000, 2 * L_NCSHIFT_DS + 1 ); + E1_exp = sub( 31, q_com ); + E2_exp = sub( 31, q_com ); + + E1 = sum2_32_exp_fx( buf1, len, &E1_exp, 2 ); + E2 = sum2_32_exp_fx( buf2, len, &E2_exp, 2 ); + + E1E2_exp = s_max( E1_exp, E2_exp ); + E1 = L_shl( E1, sub( E1_exp, E1E2_exp ) ); + E2 = L_shl( E2, sub( E2_exp, E1E2_exp ) ); + + Word32 E1_mul = BASOP_Util_Add_Mant32Exp( E1, E1E2_exp, hStereoTCA->E1_mem_fx, hStereoTCA->E1_E2_mem_exp, &E1_exp ); + Word32 E2_mul = BASOP_Util_Add_Mant32Exp( E2, E1E2_exp, hStereoTCA->E2_mem_fx, hStereoTCA->E1_E2_mem_exp, &E2_exp ); + Word32 sqr_inp = Mpy_32_32( E1_mul, E2_mul ); + Word16 sq_exp = add( E1_exp, E2_exp ); + + IF( sqr_inp ) + { + sqr_inp = Sqrt32( sqr_inp, &sq_exp ); + sqr_inp = Mpy_32_32( sqr_inp, 1342177280 /* 320 in Q22*/ ); + sq_exp = add( sq_exp, 9 ); + Inv_Tot_E = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, sqr_inp, &Inv_Tot_E_exp ); + Inv_Tot_E_exp = add( Inv_Tot_E_exp, sub( 0, sq_exp ) ); + } + ELSE + { + Inv_Tot_E = 25088; /* 98.82 in Q8 */ + Inv_Tot_E_exp = 7; + } + + hStereoTCA->E1_mem_fx = E1; + hStereoTCA->E2_mem_fx = E2; + hStereoTCA->E1_E2_mem_exp = E1E2_exp; + move16(); + + *corrEst_Exp = corrEst_exp[0]; + + for ( i = lagSearchRange[0], j = 0; i <= 0; i++, j++ ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < len; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + C = W_extract_h( L64_sum ); // ener_side_q + C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) ); + C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); + corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); + corrEst_exp[j] = add( Inv_Tot_E_exp, exp ); + *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] ); + hStereoTCA->C_mem_fx[j] = C; + hStereoTCA->C_mem_exp[j] = C_exp; + } + + for ( ; i <= lagSearchRange[1]; i++, j++ ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < len; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + C = W_extract_h( L64_sum ); // ener_side_q + C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) ); + C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); + corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); + corrEst_exp[j] = add( Inv_Tot_E_exp, exp ); + *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] ); + hStereoTCA->C_mem_fx[j] = C; + hStereoTCA->C_mem_exp[j] = C_exp; + } + /* Rescaling buffers */ + + FOR( i = 0; i < ( 2 * L_NCSHIFT_DS + 1 ); i++ ) + { + corrEst[i] = L_shl( corrEst[i], sub( corrEst_exp[i], *corrEst_Exp ) ); + move32(); + } + + return; +} +#else static void utilCrossCorr_mod( STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ const float *buf1, @@ -389,64 +770,195 @@ static void utilCrossCorr_mod( return; } - - +#endif /*--------------------------------------------------------------- * utilCrossCorr() * * crossCorr estimation between buf1, buf2 over the * lag range of (lagSearchRange[0], lagSearchRange[1]). * ---------------------------------------------------------------*/ - -static void utilCrossCorr( - const float *buf1, - const float *buf2, - const float *win, - float *corrEst, /* o : correlation estimate */ - const int16_t *lagSearchRange, - const int16_t len, - const int16_t winSymmFlag ) +#ifdef IVAS_FLOAT_FIXED +static void utilCrossCorr_fx( + const Word32 *buf1, // buf1_q + Word16 buf1_q, + const Word32 *buf2, // buf2_q + Word16 buf2_q, + const Word32 *win, + Word32 *corrEst, /* o : correlation estimate corrEst_e */ + Word16 *corrEst_e, + const Word16 *lagSearchRange, + const Word16 len, + const Word16 winSymmFlag ) { - float tempBuf1[L_FRAME48k]; - float tempBuf2[L_FRAME48k]; - float temp, scale; - int16_t i, j; + Word32 tempBuf1[L_FRAME48k]; + Word32 tempBuf2[L_FRAME48k]; + Word32 temp, scale; + Word16 res_e, tmp_e; + Word64 L64_sum; + Word16 i, j, k; + Word16 corrEstTemp_e[N_MAX_SHIFT_CHANGE + 1]; + Word16 max_e = MIN16B; + move16(); + + Word16 gb1 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf1, len ) ) ); + Word16 gb2 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf2, len ) ) ); /* Apply windowing */ - if ( win != NULL ) + IF( win != NULL ) { - if ( winSymmFlag == 0 ) + IF( EQ_16( winSymmFlag, 0 ) ) { - v_mult( buf1, win, tempBuf1, len ); - v_mult( buf2, win, tempBuf2, len ); + v_mult_fixed( buf1, win, tempBuf1, len ); + v_mult_fixed( buf2, win, tempBuf2, len ); } - else + ELSE { - v_mult( buf1, win, tempBuf1, ( len >> 1 ) ); - v_mult( buf2, win, tempBuf2, ( len >> 1 ) ); + v_mult_fixed( buf1, win, tempBuf1, ( len >> 1 ) ); + v_mult_fixed( buf2, win, tempBuf2, ( len >> 1 ) ); - for ( i = ( len >> 1 ); i < len; i++ ) + FOR( i = shr( len, 1 ); i < len; i++ ) { - tempBuf1[i] = win[len - 1 - i] * buf1[i]; - tempBuf2[i] = win[len - 1 - i] * buf2[i]; + tempBuf1[i] = Mpy_32_32( win[len - 1 - i], buf1[i] ); + move32(); + tempBuf2[i] = Mpy_32_32( win[len - 1 - i], buf2[i] ); + move32(); } } } - else + ELSE { - mvr2r( buf1, tempBuf1, len ); - mvr2r( buf2, tempBuf2, len ); + Copy32( buf1, tempBuf1, len ); + Copy32( buf2, tempBuf2, len ); } - temp = sum2_f( tempBuf1, len ); - temp *= sum2_f( tempBuf2, len ); - scale = ( temp == 0 ) ? 1.0f : inv_sqrt( temp ); + Word16 temp1_e = sub( Q31, buf1_q ); + Word16 temp2_e = sub( Q31, buf2_q ); - /* starting point of lag search range should be less than the ending point */ - assert( lagSearchRange[0] <= lagSearchRange[1] ); + temp = sum2_32_exp_fx( tempBuf1, len, &temp1_e, gb1 ); // temp1_e + temp = Mpy_32_32( temp, sum2_32_exp_fx( tempBuf2, len, &temp2_e, gb2 ) ); // temp2_e + temp2_e = add( temp1_e, temp2_e ); - /* first part of noncausal corr est. */ - for ( i = lagSearchRange[0], j = 0; i <= min( 0, lagSearchRange[1] ); i++, j++ ) + IF( temp == 0 ) + { + scale = MAXVAL_WORD32; + move32(); + } + ELSE + { + scale = Isqrt_lc( temp, &temp2_e ); // temp2_e + } + + /* starting point of lag search range should be less than the ending point */ + assert( lagSearchRange[0] <= lagSearchRange[1] ); + + /* first part of noncausal corr est. */ + for ( i = lagSearchRange[0], j = 0; i <= s_min( 0, lagSearchRange[1] ); ( i++, j++ ) ) + { + L64_sum = 0; + move64(); + FOR( k = 0; k < add( len, i ); k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + temp = W_extract_h( L64_sum ); + res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) ); + + corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len + i ), &tmp_e ) ); + move32(); + corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) ); + move16(); + max_e = s_max( max_e, corrEstTemp_e[j] ); + } + + /* second part of noncausal corr est. */ + for ( ; i <= lagSearchRange[1]; ( i++, j++ ) ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < sub( len, i ); k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + temp = W_extract_h( L64_sum ); + res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) ); + + corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len - i ), &tmp_e ) ); + move32(); + corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) ); + move16(); + max_e = s_max( max_e, corrEstTemp_e[j] ); + move16(); + } + + + FOR( i = 0; i < j; i++ ) + { + corrEst[i] = L_shr( corrEst[i], sub( max_e, corrEstTemp_e[i] ) ); + move32(); + } + + *corrEst_e = max_e; + move16(); + v_multc_fixed( corrEst, scale, corrEst, j ); + *corrEst_e = add( *corrEst_e, temp2_e ); + move16(); + + return; +} +#else +static void utilCrossCorr( + const float *buf1, + const float *buf2, + const float *win, + float *corrEst, /* o : correlation estimate */ + const int16_t *lagSearchRange, + const int16_t len, + const int16_t winSymmFlag ) +{ + float tempBuf1[L_FRAME48k]; + float tempBuf2[L_FRAME48k]; + float temp, scale; + int16_t i, j; + + /* Apply windowing */ + if ( win != NULL ) + { + if ( winSymmFlag == 0 ) + { + v_mult( buf1, win, tempBuf1, len ); + v_mult( buf2, win, tempBuf2, len ); + } + else + { + v_mult( buf1, win, tempBuf1, ( len >> 1 ) ); + v_mult( buf2, win, tempBuf2, ( len >> 1 ) ); + + for ( i = ( len >> 1 ); i < len; i++ ) + { + tempBuf1[i] = win[len - 1 - i] * buf1[i]; + tempBuf2[i] = win[len - 1 - i] * buf2[i]; + } + } + } + else + { + mvr2r( buf1, tempBuf1, len ); + mvr2r( buf2, tempBuf2, len ); + } + + temp = sum2_f( tempBuf1, len ); + temp *= sum2_f( tempBuf2, len ); + scale = ( temp == 0 ) ? 1.0f : inv_sqrt( temp ); + + /* starting point of lag search range should be less than the ending point */ + assert( lagSearchRange[0] <= lagSearchRange[1] ); + + /* first part of noncausal corr est. */ + for ( i = lagSearchRange[0], j = 0; i <= min( 0, lagSearchRange[1] ); i++, j++ ) { temp = dotp( tempBuf1 - i, tempBuf2, ( len + i ) ); corrEst[j] = temp / ( len + i ); @@ -462,7 +974,7 @@ static void utilCrossCorr( return; } - +#endif /*--------------------------------------------------------------- * corrStatsEst() * @@ -470,292 +982,503 @@ static void utilCrossCorr( * ---------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static void corrStatsEst( - STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */ - const float *buf1, /* i : channel 1 */ - const float *buf2, /* i : channel 2 */ - const int16_t bufLenDS, /* i : buffer length */ - const int16_t dsFactor, /* i : buffer length */ - const int16_t vad_flag1, /* i : VAD flag channel 1 */ - const int16_t vad_flag2, /* i : VAD flag channel 2 */ +static Word16 TRUNC_FX( Word32 inp, Word16 exp ) +{ + Word16 ouptut; + Word32 temp; + + temp = L_shr( inp, sub( 31, exp ) ); + test(); + IF( GT_32( temp, 32767 ) || LT_32( temp, -32768 ) ) + { + IF( temp < 0 ) + { + ouptut = -32768; + } + ELSE + { + ouptut = 32767; + } + move16(); + } + ELSE + { + IF( NE_32( temp, L_shl_sat( 1, sub( 31, exp ) ) ) ) + { + Word32 temp1 = L_add_sat( inp, L_shl_sat( 1, sub( 31, add( exp, 1 ) ) ) ); + ouptut = (Word16) L_shr( temp1, sub( 31, exp ) ); + + IF( temp < 0 ) + { + ouptut = add( ouptut, 1 ); + } + } + ELSE + { + ouptut = (Word16) temp; + move16(); + } + } + return ouptut; +} +static void corrStatsEst_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */ + Word32 *buf1_fx, /* i : channel 1 q_com*/ + Word32 *buf2_fx, /* i : channel 2 q_com*/ + Word16 q_com, + const Word16 bufLenDS, /* i : buffer length */ + const Word16 dsFactor, /* i : buffer length */ + const Word16 vad_flag1, /* i : VAD flag channel 1 */ + const Word16 vad_flag2, /* i : VAD flag channel 2 */ STEREO_CLASSIF_HANDLE hStereoClassif /* i/o: stereo classifier handle */ ) { - int16_t lagSearchRange[2]; - float corrEst[2 * L_NCSHIFT_DS + 1]; - int16_t corrLagStats[3]; - float *tempRK; - const float *winInterp; - float rInterp[MAX_INTERPOLATE]; - int16_t interpMin, interpMax, interpLen; - int16_t i, j, k, m; - float tempF, alpha; - float win_bias; - int16_t tempLen, win_width; - float loc_weight_win[4 * L_NCSHIFT_DS + 1]; - float X_hat, Y_hat, XY_hat, X_SQR_hat; - float alpha_reg, beta_reg, reg_prv_corr, dist_reg_prv_corr, bias_par, width_par; - float k1, k2, temp_A, temp_B; - int16_t stmp; - float corrEst_ncorr; + Word16 lagSearchRange[2]; + Word32 corrEst_fx[2 * L_NCSHIFT_DS + 1]; + Word16 corrLagStats[3]; + Word32 *tempRK_fx; + const Word32 *winInterp_fx; + Word32 rInterp_fx[MAX_INTERPOLATE]; + Word16 rInterp_exp[MAX_INTERPOLATE]; + Word16 interpMin, interpMax, interpLen; + Word16 i, j, k, m; + Word16 win_bias_fx; + Word16 tempLen, win_width; + Word16 loc_weight_win_fx[4 * L_NCSHIFT_DS + 1]; + Word32 X_hat_fx, Y_hat_fx, XY_hat_fx, X_SQR_hat_fx; + Word32 alpha_reg_fx, beta_reg_fx, reg_prv_corr_fx, dist_reg_prv_corr_fx, bias_par_fx, width_par_fx; + Word16 alpha_reg_exp, beta_reg_exp, reg_prv_corr_exp, dist_reg_prv_corr_exp, bias_par_exp, width_par_exp; + + Word16 alpha_fx; + Word16 k1_fx, k2_fx; + Word32 temp_A_fx, temp_B_fx, tempF_fx; + Word16 stmp; + Word32 corrEst_ncorr_fx, temp32; + Word16 corrEst_exp, corrEst_ncorr_exp, temp; + Word16 X_hat_exp, Y_hat_exp, XY_hat_exp, X_SQR_hat_exp, exp; /* init of regression parameters*/ - X_hat = 0; - X_SQR_hat = 0; - XY_hat = 0; + X_hat_fx = 0; + move32(); + X_hat_exp = 0; + move16(); + X_SQR_hat_fx = 0; + move32(); + X_SQR_hat_exp = 0; + move16(); + XY_hat_fx = 0; + move32(); + XY_hat_exp = 0; + move16(); /* Initializations */ - alpha = 0.7f; + alpha_fx = 22938; /* 0.7 in Q15*/ + move16(); lagSearchRange[0] = -L_NCSHIFT_DS; + move16(); lagSearchRange[1] = L_NCSHIFT_DS; + move16(); tempLen = ( 2 * L_NCSHIFT_DS + 1 ); + move16(); - set_s( corrLagStats, 0, 3 ); + set16_fx( corrLagStats, 0, 3 ); /* First iteration of xcorr estimation */ - utilCrossCorr_mod( hStereoTCA, buf1, buf2, corrEst, lagSearchRange, bufLenDS - L_XCORRMEM_DS ); + utilCrossCorr_mod_fx( hStereoTCA, buf1_fx, buf2_fx, q_com, corrEst_fx, &corrEst_exp, lagSearchRange, sub( bufLenDS, L_XCORRMEM_DS ) ); /* calculate features for the UNCLR classifier */ - unclr_calc_corr_features( hStereoClassif, hStereoTCA, buf1, buf2, bufLenDS - L_XCORRMEM_DS, corrEst, lagSearchRange, &corrEst_ncorr ); + unclr_calc_corr_features_fx( hStereoClassif, hStereoTCA, buf1_fx, buf2_fx, q_com, sub( bufLenDS, L_XCORRMEM_DS ), corrEst_fx, corrEst_exp, lagSearchRange, &corrEst_ncorr_fx, &corrEst_ncorr_exp ); - for ( i = 1; i < 3; i++ ) + FOR( i = 1; i < 3; i++ ) { - v_add( hStereoTCA->corrEstPrev[i], hStereoTCA->corrEstPrev[0], hStereoTCA->corrEstPrev[0], tempLen ); + v_add_32( hStereoTCA->corrEstPrev_fx[i], hStereoTCA->corrEstPrev_fx[0], hStereoTCA->corrEstPrev_fx[0], tempLen ); } /* back up the corrEst */ - for ( i = 0; i < 2; i++ ) + FOR( i = 0; i < 2; i++ ) { - mvr2r( hStereoTCA->corrEstPrev[i + 1], hStereoTCA->corrEstPrev[i], tempLen ); + Copy32( hStereoTCA->corrEstPrev_fx[i + 1], hStereoTCA->corrEstPrev_fx[i], tempLen ); } - mvr2r( corrEst, hStereoTCA->corrEstPrev[2], tempLen ); - -#ifdef IVAS_FLOAT_FIXED - Word32 buf1_fx[160]; - Word32 buf2_fx[160]; - Word16 buf1_q, buf2_q, guard_bits; - Word32 temp_A_fx, temp_B_fx; - f2me_buf( buf1, buf1_fx, &buf1_q, 160 ); - f2me_buf( buf2, buf2_fx, &buf2_q, 160 ); - buf1_q = sub( 31, buf1_q ); - buf2_q = sub( 31, buf2_q ); - Word16 buf_q = s_min( buf1_q, buf2_q ); - guard_bits = find_guarded_bits_fx( 160 ); - scale_sig32( buf1_fx, 160, sub( sub( buf_q, guard_bits ), buf1_q ) ); - scale_sig32( buf2_fx, 160, sub( sub( buf_q, guard_bits ), buf2_q ) ); - buf_q = sub( buf_q, guard_bits ); -#endif -#ifdef IVAS_FLOAT_FIXED - temp_A_fx = sumAbs_fx( buf1_fx, L_FRAME_DS - L_XCORRMEM_DS ) + sumAbs_fx( buf2_fx, L_FRAME_DS - L_XCORRMEM_DS ); - temp_B_fx = sumAbs_fx( buf1_fx + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) + sumAbs_fx( buf2_fx + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ); - temp_A = fixedToFloat( temp_A_fx, buf_q ); - temp_B = fixedToFloat( temp_B_fx, buf_q ); -#else - temp_A = sumAbs( buf1, L_FRAME_DS - L_XCORRMEM_DS ) + sumAbs( buf2, L_FRAME_DS - L_XCORRMEM_DS ); - temp_B = sumAbs( buf1 + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) + sumAbs( buf2 + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ); -#endif - tempF = temp_A + temp_B + hStereoTCA->mem_tempF; - hStereoTCA->mem_tempF = temp_B; + temp = getScaleFactor32( corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + scale_sig32( corrEst_fx, 2 * L_NCSHIFT_DS + 1, temp ); + corrEst_exp = sub( corrEst_exp, temp ); - alpha = 0.93f; - if ( tempF > 4.0f * hStereoTCA->ica_envVarLT ) - { - alpha = 0.83f; - } - else if ( tempF > 2.0f * hStereoTCA->ica_envVarLT ) + IF( GT_16( corrEst_exp, hStereoTCA->corrEstPrev_exp ) ) { - alpha = 0.85f; + scale_sig32( hStereoTCA->corrEstPrev_fx[0], 2 * L_NCSHIFT_DS + 1, sub( hStereoTCA->corrEstPrev_exp, corrEst_exp ) ); + scale_sig32( hStereoTCA->corrEstPrev_fx[1], 2 * L_NCSHIFT_DS + 1, sub( hStereoTCA->corrEstPrev_exp, corrEst_exp ) ); + Copy32( corrEst_fx, hStereoTCA->corrEstPrev_fx[2], tempLen ); + hStereoTCA->corrEstPrev_exp = corrEst_exp; + move16(); } - else if ( tempF > hStereoTCA->ica_envVarLT ) + ELSE { - alpha = 0.90f; + Copy32( corrEst_fx, hStereoTCA->corrEstPrev_fx[2], tempLen ); + scale_sig32( hStereoTCA->corrEstPrev_fx[2], 2 * L_NCSHIFT_DS + 1, sub( corrEst_exp, hStereoTCA->corrEstPrev_exp ) ); } + scale_sig32( hStereoTCA->corrEstPrev_fx[0], 2 * L_NCSHIFT_DS + 1, -1 ); + scale_sig32( hStereoTCA->corrEstPrev_fx[1], 2 * L_NCSHIFT_DS + 1, -1 ); + scale_sig32( hStereoTCA->corrEstPrev_fx[2], 2 * L_NCSHIFT_DS + 1, -1 ); + hStereoTCA->corrEstPrev_exp = add( hStereoTCA->corrEstPrev_exp, 1 ); + move16(); + Word32 buf1_fx_temp[L_FRAME_DS]; + Word32 buf2_fx_temp[L_FRAME_DS]; - hStereoTCA->corrStatsSmoothFac = alpha; + Copy32( buf1_fx, buf1_fx_temp, L_FRAME_DS ); + Copy32( buf2_fx, buf2_fx_temp, L_FRAME_DS ); - /* long term corr Stats estimation */ - v_multc( hStereoTCA->corrEstLT, alpha, hStereoTCA->corrEstLT, 2 * L_NCSHIFT_DS + 1 ); - v_multc( corrEst, 1.0f - alpha, corrEst, 2 * L_NCSHIFT_DS + 1 ); - v_add( hStereoTCA->corrEstLT, corrEst, hStereoTCA->corrEstLT, 2 * L_NCSHIFT_DS + 1 ); + scale_sig32( buf1_fx_temp, L_FRAME_DS, -4 ); + scale_sig32( buf2_fx_temp, L_FRAME_DS, -4 ); - hStereoTCA->ica_envVarLT = SMOOTH_ENV_FACTOR * hStereoTCA->ica_envVarLT + ( 1 - SMOOTH_ENV_FACTOR ) * tempF; + temp_A_fx = L_add( sumAbs_fx( buf1_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ) ); + temp_B_fx = L_add( sumAbs_fx( buf1_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) ); - mvr2r( hStereoTCA->corrEstLT, corrEst, 2 * L_NCSHIFT_DS + 1 ); - Y_hat = hStereoTCA->delay_0_mem[0]; - /* Note: keep X_hat and X_SQR_hat calculations inside the loop to allow future tuning of MAX_DELAYREGLEN */ - for ( i = 1; i < MAX_DELAYREGLEN; i++ ) - { - X_hat += (float) i; - Y_hat += hStereoTCA->delay_0_mem[i]; - XY_hat += i * hStereoTCA->delay_0_mem[i]; - X_SQR_hat += (float) ( i * i ); - } - X_hat *= INV_MAX_DELAYREGLEN; - Y_hat *= INV_MAX_DELAYREGLEN; - XY_hat *= INV_MAX_DELAYREGLEN; - X_SQR_hat *= INV_MAX_DELAYREGLEN; + tempF_fx = BASOP_Util_Add_Mant32Exp( L_add( temp_A_fx, temp_B_fx ), sub( 31, sub( q_com, 4 ) ), hStereoTCA->mem_tempF_fx, hStereoTCA->mem_tempF_exp, &temp ); + Word16 tempF_exp = temp; + hStereoTCA->mem_tempF_fx = temp_B_fx; + move32(); + hStereoTCA->mem_tempF_exp = sub( 31, sub( q_com, 4 ) ); + move16(); - beta_reg = 0; - tempF = X_SQR_hat - ( X_hat * X_hat ); - if ( tempF != 0 ) + alpha_fx = 30474 /* 0.93f in Q15*/; + move16(); + IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 2 ), &temp ) > 0 ) { - beta_reg = ( XY_hat - X_hat * Y_hat ) / tempF; + alpha_fx = 27197 /* 0.83f in Q15*/; } - alpha_reg = ( Y_hat - beta_reg * X_hat ); - reg_prv_corr = beta_reg * MAX_DELAYREGLEN + alpha_reg; - - if ( TRUNC( reg_prv_corr ) <= -L_NCSHIFT_DS ) + ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 1 ), &temp ) > 0 ) { - reg_prv_corr = -L_NCSHIFT_DS + 1; + alpha_fx = 27853 /* 0.85f in Q15*/; } - - if ( TRUNC( reg_prv_corr ) >= L_NCSHIFT_DS ) + ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, hStereoTCA->ica_envVarLT_exp, &temp ) > 0 ) { - reg_prv_corr = L_NCSHIFT_DS - 1; + alpha_fx = 29491 /* 0.9f in Q15*/; } + move16(); + hStereoTCA->corrStatsSmoothFac_fx = alpha_fx; + move32(); - bias_par = A_BIAS * hStereoTCA->smooth_dist_reg_prv_corr + B_BIAS; - bias_par = min( bias_par, XH_BIAS ); - bias_par = max( bias_par, XL_BIAS ); + /* long term corr Stats estimation */ + v_multc_fixed_16( hStereoTCA->corrEstLT_fx, alpha_fx, hStereoTCA->corrEstLT_fx, 2 * L_NCSHIFT_DS + 1 ); + v_multc_fixed_16( corrEst_fx, sub( MAX_16, alpha_fx ), corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + v_add_fixed_me( hStereoTCA->corrEstLT_fx, hStereoTCA->corrEstLT_exp, corrEst_fx, corrEst_exp, hStereoTCA->corrEstLT_fx, &hStereoTCA->corrEstLT_exp, 2 * L_NCSHIFT_DS + 1, 0 ); - width_par = A_WIDTH * hStereoTCA->smooth_dist_reg_prv_corr + B_WIDTH; - width_par = min( width_par, XH_WIDTH ); - width_par = max( width_par, XL_WIDTH ); + hStereoTCA->ica_envVarLT_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->ica_envVarLT_fx, SMOOTH_ENV_FACTOR_FX_Q15 ), hStereoTCA->ica_envVarLT_exp, Mpy_32_16_1( tempF_fx, ONE_IN_Q15 - SMOOTH_ENV_FACTOR_FX_Q15 ), tempF_exp, &hStereoTCA->ica_envVarLT_exp ); // SMOOTH_ENV_FACTOR_FX_Q15 + move32(); - win_width = (int16_t) ( width_par * ( 4 * L_NCSHIFT_DS + 1 ) ); - win_bias = bias_par; - k1 = 0.5f * ( 1.0f + win_bias ); - k2 = 0.5f * ( 1.0f - win_bias ); + Copy32( hStereoTCA->corrEstLT_fx, corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + corrEst_exp = hStereoTCA->corrEstLT_exp; + move16(); - for ( i = 0; i < ( 2 * L_NCSHIFT_DS - 2 * win_width ); i++ ) + Y_hat_fx = hStereoTCA->delay_0_mem_fx[0]; + move32(); + Y_hat_exp = hStereoTCA->delay_0_mem_exp; + move16(); + + /* Note: keep X_hat and X_SQR_hat calculations inside the loop to allow future tuning of MAX_DELAYREGLEN */ + FOR( i = 1; i < MAX_DELAYREGLEN; i++ ) { - loc_weight_win[i] = win_bias; + X_hat_fx = BASOP_Util_Add_Mant32Exp( X_hat_fx, X_hat_exp, L_shl( i, 27 ), 4, &X_hat_exp ); + Y_hat_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, hStereoTCA->delay_0_mem_fx[i], hStereoTCA->delay_0_mem_exp, &Y_hat_exp ); + XY_hat_fx = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, Mpy_32_32( hStereoTCA->delay_0_mem_fx[i], L_shl( i, 27 ) ), add( 4, hStereoTCA->delay_0_mem_exp ), &XY_hat_exp ); + X_SQR_hat_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, Mpy_32_32( L_shl( i, 27 ), L_shl( i, 27 ) ), 8, &X_SQR_hat_exp ); } - for ( i = ( 2 * L_NCSHIFT_DS - 2 * win_width ); i <= ( 2 * L_NCSHIFT_DS + 2 * win_width ); i++ ) + X_hat_fx = Mpy_32_16_1( X_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + Y_hat_fx = Mpy_32_16_1( Y_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + XY_hat_fx = Mpy_32_16_1( XY_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + X_SQR_hat_fx = Mpy_32_16_1( X_SQR_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + + beta_reg_fx = 0; + move32(); + beta_reg_exp = 0; + move16(); + tempF_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, L_negate( Mpy_32_32( X_hat_fx, X_hat_fx ) ), shl( X_hat_exp, 1 ), &tempF_exp ); + + IF( tempF_fx != 0 ) { - loc_weight_win[i] = k1 + k2 * cosf( EVS_PI * ( ( i - 2 * L_NCSHIFT_DS ) / ( 2.0f * win_width ) ) ); + temp32 = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, L_negate( Mpy_32_32( X_hat_fx, Y_hat_fx ) ), add( X_hat_exp, Y_hat_exp ), &exp ); + beta_reg_fx = BASOP_Util_Divide3232_Scale_cadence( temp32, tempF_fx, &beta_reg_exp ); + if ( beta_reg_fx ) + { + beta_reg_exp = add( beta_reg_exp, sub( exp, tempF_exp ) ); + } } - for ( i = ( 2 * L_NCSHIFT_DS + 2 * win_width ); i < ( 4 * L_NCSHIFT_DS + 1 ); i++ ) + alpha_reg_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, L_negate( Mpy_32_32( X_hat_fx, beta_reg_fx ) ), add( X_hat_exp, beta_reg_exp ), &alpha_reg_exp ); + reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( alpha_reg_fx, alpha_reg_exp, Mpy_32_32( beta_reg_fx, L_shl( MAX_DELAYREGLEN, 27 ) ), add( 4, beta_reg_exp ), ®_prv_corr_exp ); + + IF( LE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), -L_NCSHIFT_DS ) ) { - loc_weight_win[i] = win_bias; + reg_prv_corr_fx = -L_NCSHIFT_DS + 1; + move32(); + reg_prv_corr_exp = 31; + move16(); } - for ( i = 0, j = L_NCSHIFT_DS - TRUNC( reg_prv_corr ); i < 2 * L_NCSHIFT_DS + 1; i++, j++ ) + IF( GE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), L_NCSHIFT_DS ) ) { - corrEst[i] *= loc_weight_win[j]; + reg_prv_corr_fx = L_NCSHIFT_DS - 1; + move32(); + reg_prv_corr_exp = 31; + move16(); } - if ( hStereoTCA->prevTargetGain < 0.8f && vad_flag1 ) + bias_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_BIAS_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, L_shl( B_BIAS_FX_Q15, Q16 ), 0, &bias_par_exp ); + + Word32 XH_BIAS_tmp = L_shl( XH_BIAS_FX_Q15, Q16 ); + Word32 XL_BIAS_tmp = L_shl( XL_BIAS_FX_Q15, Q16 ); + + IF( bias_par_exp < 0 ) + { + bias_par_fx = L_shl( bias_par_fx, bias_par_exp ); + bias_par_exp = 0; + move16(); + } + ELSE + { + XH_BIAS_tmp = L_shr( XH_BIAS_tmp, bias_par_exp ); + XL_BIAS_tmp = L_shr( XL_BIAS_tmp, bias_par_exp ); + } + + bias_par_fx = L_min( bias_par_fx, XH_BIAS_tmp ); + bias_par_fx = L_max( bias_par_fx, XL_BIAS_tmp ); + bias_par_fx = L_shr( bias_par_fx, bias_par_exp ); + bias_par_exp = 0; + move16(); + + width_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_WIDTH_FX_Q31 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, B_WIDTH_FX_Q31, 0, &width_par_exp ); + Word32 XH_WIDTH_tmp = L_shl( XH_WIDTH_FX_Q15, Q16 ); + Word32 XL_WIDTH_tmp = L_shl( XL_WIDTH_FX_Q15, Q16 ); + + IF( width_par_exp < 0 ) + { + width_par_fx = L_shl( width_par_fx, width_par_exp ); + width_par_exp = 0; + move16(); + } + ELSE + { + XH_WIDTH_tmp = L_shr( XH_WIDTH_tmp, width_par_exp ); + XL_WIDTH_tmp = L_shr( XL_WIDTH_tmp, width_par_exp ); + } + width_par_fx = L_min( width_par_fx, XH_WIDTH_tmp ); + width_par_fx = L_max( width_par_fx, XL_WIDTH_tmp ); + width_par_fx = L_shl( width_par_fx, width_par_exp ); + width_par_exp = 0; + move16(); + + win_width = (Word16) L_shr( Mpy_32_32( width_par_fx, 1350565888 /* ( 4L_NCSHIFT_DS + 1 ) in Q23 */ ), sub( 31, add( width_par_exp, 8 ) ) ); + + win_bias_fx = round_fx( bias_par_fx ); // Q15 + + k1_fx = add( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15 + k2_fx = sub( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15 + + FOR( i = 0; i < sub( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i++ ) + { + loc_weight_win_fx[i] = win_bias_fx; // Q15 + move16(); + } + + FOR( i = sub( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i <= add( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i++ ) + { + Word16 cos_inp = BASOP_Util_Divide1616_Scale( sub( i, 2 * L_NCSHIFT_DS ), shl( win_width, 1 ), &exp ); + cos_inp = shr_sat( cos_inp, sub( 0, exp ) ); + cos_inp = getCosWord16R2( shr( cos_inp, 1 ) ); + loc_weight_win_fx[i] = add( k1_fx, mult( k2_fx, cos_inp ) ); + move16(); + } + + FOR( i = add( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i < ( 4 * L_NCSHIFT_DS + 1 ); i++ ) + { + loc_weight_win_fx[i] = win_bias_fx; // Q15 + move16(); + } + + Word16 x = TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ); + move16(); + for ( i = 0, j = sub( L_NCSHIFT_DS, x ); i < 2 * L_NCSHIFT_DS + 1; i++, j++ ) + { + corrEst_fx[i] = Mpy_32_16_1( corrEst_fx[i], loc_weight_win_fx[j] ); + move32(); + } + test(); + test(); + IF( LT_32( hStereoTCA->prevTargetGain_fx, 429496730 /*0.8f in Q29*/ ) && vad_flag1 ) { /* ch 2 is prev reference channel */ - v_multc( corrEst, 1.2f, corrEst, L_NCSHIFT_DS + 1 ); - v_multc( corrEst + L_NCSHIFT_DS + 1, 0.833f, corrEst + L_NCSHIFT_DS + 1, L_NCSHIFT_DS ); + v_multc_fixed( corrEst_fx, 644245095 /*1.2f in Q29*/, corrEst_fx, L_NCSHIFT_DS + 1 ); + v_multc_fixed( corrEst_fx + L_NCSHIFT_DS + 1, 447213470 /* 0.833 in Q29*/, corrEst_fx + L_NCSHIFT_DS + 1, L_NCSHIFT_DS ); + corrEst_exp = add( corrEst_exp, 2 ); } - else if ( hStereoTCA->prevTargetGain > 1.2f && vad_flag1 ) + ELSE IF( GT_32( hStereoTCA->prevTargetGain_fx, 644245094 /*1.2f in Q29*/ ) && vad_flag1 ) { /* ch 1 is prev reference channel */ - v_multc( corrEst, 0.833f, corrEst, L_NCSHIFT_DS ); - v_multc( corrEst + L_NCSHIFT_DS, 1.2f, corrEst + L_NCSHIFT_DS, L_NCSHIFT_DS + 1 ); + v_multc_fixed( corrEst_fx, 447213470 /* 0.833 f in Q29*/, corrEst_fx, L_NCSHIFT_DS ); + v_multc_fixed( corrEst_fx + L_NCSHIFT_DS, 644245095 /*1.2f in Q29*/, corrEst_fx + L_NCSHIFT_DS, L_NCSHIFT_DS + 1 ); + corrEst_exp = add( corrEst_exp, 2 ); } - - if ( corrEst_ncorr > 0.8f && vad_flag1 ) + test(); + IF( BASOP_Util_Add_Mant32Exp( corrEst_ncorr_fx, corrEst_ncorr_exp, -429496730 /*0.8f in Q29*/, 2, &exp ) > 0 && vad_flag1 ) { - i = max( 0, hStereoTCA->prevCorrLagStats[0] - 1 + L_NCSHIFT_DS ); - j = min( 2 * L_NCSHIFT_DS, hStereoTCA->prevCorrLagStats[0] + 1 + L_NCSHIFT_DS ); - k = j - i + 1; - v_multc( corrEst + i, 1.2f, corrEst + i, k ); + i = s_max( 0, add( hStereoTCA->prevCorrLagStats[0], -1 + L_NCSHIFT_DS ) ); + j = s_min( 2 * L_NCSHIFT_DS, add( hStereoTCA->prevCorrLagStats[0], 1 + L_NCSHIFT_DS ) ); + k = add( sub( j, i ), 1 ); + + v_multc_fixed( corrEst_fx, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx, i ); // to allign in same exp + v_multc_fixed( corrEst_fx + i, 644245095 /*1.2f in Q29*/, corrEst_fx + i, k ); + v_multc_fixed( corrEst_fx + i + k, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx + i + k, sub( 2 * L_NCSHIFT_DS + 1, i + k ) ); // to allign in same exp + corrEst_exp = add( corrEst_exp, 2 ); } /* Initial corr lag estimate */ - corrLagStats[0] = maximum( corrEst, ( lagSearchRange[1] - lagSearchRange[0] + 1 ), &tempF ); - corrLagStats[0] += lagSearchRange[0]; + corrLagStats[0] = maximum_32_fx( corrEst_fx, add( sub( lagSearchRange[1], lagSearchRange[0] ), 1 ), &tempF_fx ); + move16(); + tempF_exp = corrEst_exp; + move16(); + corrLagStats[0] = add( corrLagStats[0], lagSearchRange[0] ); + move16(); - stmp = corrLagStats[0] * dsFactor; - hStereoClassif->unclr_fv[E_corrLagStats0] = (float) stmp; - hStereoClassif->xtalk_fv[E_corrLagStats0] = (float) stmp; - hStereoClassif->xtalk_fv[E_ica_corr_value0] = tempF; + stmp = i_mult( corrLagStats[0], dsFactor ); + hStereoClassif->unclr_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_ica_corr_value0] = L_shl( tempF_fx, sub( tempF_exp, Q16 ) ); + move32(); - if ( vad_flag1 == 0 && alpha > 0.7f ) + test(); + if ( vad_flag1 == 0 && GT_16( alpha_fx, 22938 /* 0.7f in Q15 */ ) ) { corrLagStats[0] = 0; + move16(); } - dist_reg_prv_corr = fabsf( reg_prv_corr - corrLagStats[0] ); - - if ( vad_flag1 == 1 && vad_flag2 == 1 ) + dist_reg_prv_corr_fx = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, -corrLagStats[0], Q31, &dist_reg_prv_corr_exp ) ); + test(); + IF( EQ_16( vad_flag1, 1 ) && EQ_16( vad_flag2, 1 ) ) { - hStereoTCA->smooth_dist_reg_prv_corr = SMOOTH_DIST_FACTOR * hStereoTCA->smooth_dist_reg_prv_corr + ( 1.0f - SMOOTH_DIST_FACTOR ) * dist_reg_prv_corr; - - mvr2r( &( hStereoTCA->delay_0_mem[1] ), &( hStereoTCA->delay_0_mem[0] ), MAX_DELAYREGLEN - 1 ); - hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] = 0.2f * hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] + 0.8f * corrLagStats[0]; + hStereoTCA->smooth_dist_reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, SMOOTH_DIST_FACTOR_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, Mpy_32_16_1( dist_reg_prv_corr_fx, MAX_16 - SMOOTH_DIST_FACTOR_FX_Q15 ), dist_reg_prv_corr_exp, &hStereoTCA->smooth_dist_reg_prv_corr_exp ); + move32(); + Copy32( &( hStereoTCA->delay_0_mem_fx[1] ), &( hStereoTCA->delay_0_mem_fx[0] ), MAX_DELAYREGLEN - 1 ); - if ( fabsf( reg_prv_corr - hStereoTCA->delay_0_mem[0] ) > 25 ) + hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], 429496730 /* 0.2 in Q31*/ ), hStereoTCA->delay_0_mem_exp, L_mult0( 26214 /* 0.8 in Q15*/, corrLagStats[0] ), Q16, &temp ); + move32(); + Word32 inpp = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, -hStereoTCA->delay_0_mem_fx[0], hStereoTCA->delay_0_mem_exp, &exp ) ); + inpp = L_shr( inpp, sub( Q31, exp ) ); + IF( GT_32( inpp, 25 ) ) { - set_f( &( hStereoTCA->delay_0_mem[0] ), hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1], MAX_DELAYREGLEN - 1 ); + set32_fx( &( hStereoTCA->delay_0_mem_fx[0] ), hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], MAX_DELAYREGLEN - 1 ); + hStereoTCA->delay_0_mem_exp = temp; + move16(); + } + ELSE + { + IF( GT_16( temp, hStereoTCA->delay_0_mem_exp ) ) + { + scale_sig32( hStereoTCA->delay_0_mem_fx, MAX_DELAYREGLEN - 1, sub( hStereoTCA->delay_0_mem_exp, temp ) ); + hStereoTCA->delay_0_mem_exp = temp; + move16(); + } + ELSE + { + hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = L_shl( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], sub( temp, hStereoTCA->delay_0_mem_exp ) ); + move32(); + } } } - else + ELSE { - hStereoTCA->smooth_dist_reg_prv_corr = 0.; + hStereoTCA->smooth_dist_reg_prv_corr_fx = 0; + move32(); + hStereoTCA->smooth_dist_reg_prv_corr_exp = 0; + move16(); } - - if ( vad_flag1 == 0 || vad_flag2 == 0 ) + test(); + IF( vad_flag1 == 0 || vad_flag2 == 0 ) { - corrLagStats[0] = TRUNC( hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] ); + corrLagStats[0] = TRUNC_FX( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], hStereoTCA->delay_0_mem_exp ); + move32(); } /* second iteration of xcorr update @ inputFs with interp*/ - tempRK = hStereoTCA->corrEstLT - lagSearchRange[0] + corrLagStats[0]; - set_f( rInterp, 0, MAX_INTERPOLATE ); + tempRK_fx = hStereoTCA->corrEstLT_fx + add( -lagSearchRange[0], corrLagStats[0] ); + set32_fx( rInterp_fx, 0, MAX_INTERPOLATE ); + set16_fx( rInterp_exp, 0, MAX_INTERPOLATE ); /* select the Rk interp sinc window */ - winInterp = ica_sincInterp4 + SINC_ORDER1; - if ( dsFactor == 2 ) + winInterp_fx = ica_sincInterp4_fx + SINC_ORDER1; + + IF( EQ_16( dsFactor, 2 ) ) { - winInterp = ica_sincInterp2 + SINC_ORDER1; + winInterp_fx = ica_sincInterp2_fx + SINC_ORDER1; } - else if ( dsFactor == 6 ) + ELSE IF( EQ_16( dsFactor, 6 ) ) { - winInterp = ica_sincInterp6 + SINC_ORDER1; + winInterp_fx = ica_sincInterp6_fx + SINC_ORDER1; } - corrLagStats[1] = corrLagStats[0] * dsFactor; - - interpMin = max( -( dsFactor - 1 ), -corrLagStats[1] - L_NCSHIFT_DS * dsFactor ); - interpMax = min( ( dsFactor - 1 ), L_NCSHIFT_DS * dsFactor - corrLagStats[1] ); - interpLen = interpMax - interpMin + 1; + corrLagStats[1] = i_mult( corrLagStats[0], dsFactor ); + move16(); + interpMin = s_max( -sub( dsFactor, 1 ), -add( corrLagStats[1], i_mult( L_NCSHIFT_DS, dsFactor ) ) ); + interpMax = s_min( sub( dsFactor, 1 ), sub( i_mult( L_NCSHIFT_DS, dsFactor ), corrLagStats[1] ) ); + interpLen = add( sub( interpMax, interpMin ), 1 ); for ( i = interpMin, k = 0; i <= interpMax; i++, k++ ) { - rInterp[k] = 0.0f; - for ( j = -SINC_ORDER1 / dsFactor; j <= SINC_ORDER1 / dsFactor; j++ ) + rInterp_fx[k] = 0; + move32(); + FOR( j = -idiv1616( SINC_ORDER1, dsFactor ); j <= idiv1616( SINC_ORDER1, dsFactor ); j++ ) { - m = j * dsFactor; - if ( ( m - i >= -SINC_ORDER1 ) && ( m - i <= SINC_ORDER1 ) ) + m = i_mult( j, dsFactor ); + test(); + IF( GE_16( sub( m, i ), -SINC_ORDER1 ) && LE_16( sub( m, i ), SINC_ORDER1 ) ) { - if ( j > lagSearchRange[1] - corrLagStats[0] ) + IF( GT_16( j, sub( lagSearchRange[1], corrLagStats[0] ) ) ) { - rInterp[k] += winInterp[m - i] * tempRK[lagSearchRange[1] - corrLagStats[0]]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[1] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } - else if ( j < lagSearchRange[0] - corrLagStats[0] ) + ELSE IF( LT_16( j, sub( lagSearchRange[0], corrLagStats[0] ) ) ) { - rInterp[k] += winInterp[m - i] * tempRK[lagSearchRange[0] - corrLagStats[0]]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[0] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } - else + ELSE { - rInterp[k] += winInterp[m - i] * tempRK[j]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[j], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } } } } - corrLagStats[1] += ( maximum( rInterp, interpLen, &tempF ) + interpMin ); + temp = rInterp_exp[0]; + move16(); + FOR( i = 0; i < MAX_INTERPOLATE; i++ ) + { + temp = s_max( temp, rInterp_exp[i] ); + } + + FOR( i = 0; i < MAX_INTERPOLATE; i++ ) + { + rInterp_fx[i] = L_shl( rInterp_fx[i], sub( rInterp_exp[i], temp ) ); + move32(); + } + + corrLagStats[1] = add( corrLagStats[1], add( maximum_32_fx( rInterp_fx, interpLen, &tempF_fx ), interpMin ) ); + move16(); /* save corr lag stats for the current frame */ - mvs2s( corrLagStats, hStereoTCA->corrLagStats, 3 ); + Copy( corrLagStats, hStereoTCA->corrLagStats, 3 ); return; } @@ -1028,6 +1751,153 @@ static void corrStatsEst( } #endif +#ifdef IVAS_FLOAT_FIXED +/*--------------------------------------------------------------- + * Function estDownmixGain_fx() + * + * Down mix gain estimation module; convert L/R to M/S. + * ---------------------------------------------------------------*/ + +static void estDownmixGain_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */ + const Word32 *chan1, /* i : reference signal Qx */ + const Word32 *chan2, /* i/o: target signal to be scaled Qx */ + const Word16 q_chan, /* i : Q of the channel signal */ + const Word16 ncShift, /* i : shift */ + const Word16 length, /* i : input frame length */ + const Word16 element_mode, /* i : element mode */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ + const Word16 tdm_LRTD_flag /* i : LRTD stereo mode flag */ +) +{ + Word16 i, i1, i2; + Word32 tempN, tempD; + Word16 alpha, temp; + Word16 currentGain, currentGain_e; + Word32 currentGain_log10; + Word32 unclr_instTargetGain; + Word32 prevTargetGain_log10; + Word16 exp = 0; + Word16 shift = 0; + move16(); // exp + move16(); // shift + + IF( hStereoTCA->refChanIndx == L_CH_INDX ) + { + i1 = 0; + move16(); + i2 = ncShift; + move16(); + } + ELSE + { + i1 = ncShift; + move16(); + i2 = 0; + move16(); + } + + /* abs sample sum estimation */ + tempN = 0; + move32(); + tempD = 0; + move32(); + FOR( i = 0; i < length; i++ ) + { + tempN = L_add( tempN, L_abs( chan1[i1 + i] ) ); + tempD = L_add( tempD, L_abs( chan2[i2 + i] ) ); + } + + alpha = hStereoTCA->corrStatsSmoothFac_fx; + move16(); + IF( tempD == 0 ) + { + currentGain_e = norm_l( hStereoTCA->prevTargetGain_fx ); + currentGain = extract_h( L_shl( hStereoTCA->prevTargetGain_fx, currentGain_e ) ); + currentGain_e = add( currentGain_e, hStereoTCA->prevTargetGain_fx_e ); + } + ELSE + { + currentGain = BASOP_Util_Divide3232_Scale( tempN, tempD, &exp ); + currentGain_e = exp; + move16(); + } + + currentGain = s_max( EPSILON_FX, currentGain ); + hStereoTCA->instTargetGain_fx = L_deposit_h( currentGain ); + move32(); + hStereoTCA->instTargetGain_fx_e = currentGain_e; + move16(); + prevTargetGain_log10 = BASOP_Util_Log10( hStereoTCA->prevTargetGain_fx, hStereoTCA->prevTargetGain_fx_e ); // Output in Q25 + currentGain_log10 = BASOP_Util_Log10( L_deposit_h( currentGain ), currentGain_e ); // Output in Q25 + // multiplication result will be Q25 should be fit to Q15 hence right shift by 10. + // Q25 - Q10 = Q15 + currentGain = extract_l( L_shr( Madd_32_16( Mpy_32_16_1( prevTargetGain_log10, alpha ), currentGain_log10, sub( MAX_16, alpha ) ), Q10 ) ); + currentGain_e = 0; + move16(); + + test(); + IF( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif != NULL ) + { + Word16 exp_chan = sub( Q31, q_chan ); + Word16 exp_div; + // tempD = powf( 10, currentGain ); + // 10 ^ currentGain = 2 ^ (3.32192809488 * currentGain) + // 3.32192809488 in Q13 27213 + tempD = BASOP_util_Pow2( L_mult( currentGain, 27213 ), add( currentGain_e, Q2 ), &exp ); + unclr_instTargetGain = L_deposit_h( BASOP_Util_Divide3232_Scale( tempN, L_add( tempD, EPSILON_FX ), &exp_div ) ); + exp = add( sub( exp_chan, exp ), exp_div ); + unclr_instTargetGain = BASOP_Util_Log10( L_add( unclr_instTargetGain, L_shr( MAX_32, sub( Q31, exp ) ) ), exp ); + // unclr_fv_fx is expected in Q15 - log result will be in Q25 - hence rightshift by 10. + hStereoClassif->unclr_fv_fx[E_ica_instTargetGain] = L_shr( unclr_instTargetGain, Q10 ); + move32(); + } + + test(); + IF( EQ_16( tdm_LRTD_flag, 1 ) ) + { + currentGain = 0; + move32(); + } + ELSE IF( GT_16( hStereoTCA->LRTD_G_ATT_cnt, 1 ) ) /* lrtd_mode == 1 but tdm_LRTD_flag still 0 */ + { + currentGain = BASOP_Util_Divide1616_Scale( currentGain, hStereoTCA->LRTD_G_ATT_cnt, ¤tGain_e ); // Q = 15 + 0 - (15 - exp) + /* Division result Q has to be got back to the Q of initial currentGain hence the shift operation below */ + IF( currentGain_e != 0 ) + { + currentGain = shr( currentGain, sub( Q15, currentGain_e ) ); + currentGain_e = 0; + move16(); + } + } + + + IF( GE_16( norm_s( currentGain ), sub( currentGain_e, 1 ) ) ) + { + /* convert currentGain into Q14 */ + currentGain = shl( currentGain, sub( currentGain_e, 1 ) ); + currentGain_e = 1; + move16(); + } + ELSE + { + shift = sub( currentGain_e, 1 ); + move16(); + } + + /* quantize the target gain */ + hStereoTCA->indx_ica_gD = usquant_fx( currentGain, &temp, shr( STEREO_TCA_GDMIN_FX_Q14, shift ), shr( STEREO_TCA_GDSTEP_FX_Q13, shift ), 1 << STEREO_BITS_TCA_GD ); + move16(); + // hStereoTCA->targetGain_fx = powf( 10, temp ); + // 10 ^ temp = 2 ^ (3.32192809488 * temp) + // 3.32192809488 in Q13 27213 + // exponent of power function input will be 2 more since constant is in Q13 + hStereoTCA->targetGain_fx = BASOP_util_Pow2( L_mult( temp, 27213 ), add( currentGain_e, 2 ), &hStereoTCA->targetGain_fx_e ); + move32(); + + return; +} +#else /*--------------------------------------------------------------- * Function estDownmixGain() * @@ -1098,143 +1968,904 @@ static void estDownmixGain( return; } +#endif /*--------------------------------------------------------------- * Function icaMemUpdate() * * Recalculates the memories corresponding to the previous frame. * ---------------------------------------------------------------*/ - -static void icaMemUpdate( - Encoder_State **sts, /* i/o: encoder state structure */ - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - float *bufChanL, /* i/o: L signal correction from previous frame */ - float *bufChanR, /* i/o: R signal correction from previous frame */ - const int16_t lMemRecalc, /* i : memory length at input Sampling Rate */ - const int16_t lMemRecalc_SCh, /* i : SCh memory length at input Sampling Rate*/ - const int16_t input_frame /* i : frame length */ +#ifdef IVAS_FLOAT_FIXED +static void icaMemUpdate_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word32 *bufChanL, /* i/o: L signal correction from previous frame q_com*/ + Word32 *bufChanR, /* i/o: R signal correction from previous frame q_com*/ + Word16 q_com, + const Word16 lMemRecalc, /* i : memory length at input Sampling Rate */ + const Word16 lMemRecalc_SCh, /* i : SCh memory length at input Sampling Rate*/ + const Word16 input_frame /* i : frame length */ ) { - float *ptr1, *ptr2; - int16_t i; - float ratio_L, One_m_Ratio; + Word32 *ptr1, *ptr2; + Word16 i; + Word32 ratio_L, One_m_Ratio; - if ( hCPE->element_mode == IVAS_CPE_TD ) + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) { /* Recalc of the memories - Downmix @ inputFs */ /*----------------------------------------------------------------* * Create first part of the mixture using the old ratios *----------------------------------------------------------------*/ - if ( hCPE->hStereoTD->tdm_last_SM_flag ) + IF( hCPE->hStereoTD->tdm_last_SM_flag ) { - ratio_L = hCPE->hStereoTD->tdm_last_ratio_SM; - One_m_Ratio = ratio_L - 1.0f; + ratio_L = hCPE->hStereoTD->tdm_last_ratio_SM_fx; + move32(); + One_m_Ratio = L_sub( ratio_L, MAX_32 ); } - else + ELSE { - ratio_L = hCPE->hStereoTD->tdm_last_ratio; - One_m_Ratio = 1.0f - ratio_L; + ratio_L = hCPE->hStereoTD->tdm_last_ratio_fx; + move32(); + One_m_Ratio = L_sub( MAX_32, ratio_L ); } - ptr1 = sts[0]->input - lMemRecalc - lMemRecalc_SCh; - ptr2 = sts[1]->input - lMemRecalc - lMemRecalc_SCh; + ptr1 = sts[0]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); + ptr2 = sts[1]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); - if ( hCPE->last_element_mode == IVAS_CPE_TD ) + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) { - if ( hCPE->hStereoTD->flag_skip_DMX ) + IF( hCPE->hStereoTD->flag_skip_DMX ) { - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) { ptr1[i] = bufChanL[i]; + move32(); ptr2[i] = bufChanR[i]; + move32(); } } - else + ELSE { - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + FOR( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) { - ptr1[i] = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; - ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + ptr1[i] = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); + move32(); + ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); } } } - else + ELSE { - float fac, incr, tmp1, tmp2; + Word16 fac, incr; + Word32 tmp1, tmp2; /* reset the past input signal (the signal is used in SWB BWE) */ - set_f( sts[1]->input - input_frame, 0, input_frame ); + set32_fx( sts[1]->input32_fx - input_frame, 0, input_frame ); - if ( hCPE->hStereoTD->flag_skip_DMX ) + IF( hCPE->hStereoTD->flag_skip_DMX ) { /* reconstruction of the Secondary channel past segment */ - for ( i = 0; i < lMemRecalc_SCh; i++ ) + FOR( i = 0; i < lMemRecalc_SCh; i++ ) { - ptr2[i] = bufChanL[i] * One_m_Ratio + bufChanR[i] * ratio_L; + ptr2[i] = L_add( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); } /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ - fac = 1.0f / (float) lMemRecalc; - incr = fac; + fac = div_s( 1, lMemRecalc ); // Q15 + incr = fac; // Q15 + move16(); + + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) + { + tmp1 = bufChanL[i]; + move32(); + tmp2 = bufChanR[i]; + move32(); + + ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); + move32(); + + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + move32(); + + fac = add_sat( fac, incr ); + } + } + ELSE + { + /* reconstruction of the Secondary channel past segment */ + FOR( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = div_s( 1, lMemRecalc ); // Q15 + incr = fac; // Q15 + move16(); + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) + { + tmp1 = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); + tmp2 = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + + ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); + move32(); + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + move32(); + + fac = add_sat( fac, incr ); + } + } + } + } + + IF( hCPE->hStereoICBWE != NULL ) + { + assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); + i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); + Copy_Scale_sig_32_16( bufChanL + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], i, -Q16 ); + Copy_Scale_sig_32_16( bufChanR + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], i, -Q16 ); + hCPE->hStereoICBWE->q_dataChan_fx = sub( q_com, Q16 ); + move16(); + } + + return; +} +#else +static void icaMemUpdate( + Encoder_State **sts, /* i/o: encoder state structure */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + float *bufChanL, /* i/o: L signal correction from previous frame */ + float *bufChanR, /* i/o: R signal correction from previous frame */ + const int16_t lMemRecalc, /* i : memory length at input Sampling Rate */ + const int16_t lMemRecalc_SCh, /* i : SCh memory length at input Sampling Rate*/ + const int16_t input_frame /* i : frame length */ +) +{ + float *ptr1, *ptr2; + int16_t i; + float ratio_L, One_m_Ratio; + + if ( hCPE->element_mode == IVAS_CPE_TD ) + { + /* Recalc of the memories - Downmix @ inputFs */ + /*----------------------------------------------------------------* + * Create first part of the mixture using the old ratios + *----------------------------------------------------------------*/ + + if ( hCPE->hStereoTD->tdm_last_SM_flag ) + { + ratio_L = hCPE->hStereoTD->tdm_last_ratio_SM; + One_m_Ratio = ratio_L - 1.0f; + } + else + { + ratio_L = hCPE->hStereoTD->tdm_last_ratio; + One_m_Ratio = 1.0f - ratio_L; + } + + ptr1 = sts[0]->input - lMemRecalc - lMemRecalc_SCh; + ptr2 = sts[1]->input - lMemRecalc - lMemRecalc_SCh; + + if ( hCPE->last_element_mode == IVAS_CPE_TD ) + { + if ( hCPE->hStereoTD->flag_skip_DMX ) + { + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + ptr1[i] = bufChanL[i]; + ptr2[i] = bufChanR[i]; + } + } + else + { + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + ptr1[i] = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; + ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + } + } + } + else + { + float fac, incr, tmp1, tmp2; + + /* reset the past input signal (the signal is used in SWB BWE) */ + set_f( sts[1]->input - input_frame, 0, input_frame ); + + if ( hCPE->hStereoTD->flag_skip_DMX ) + { + /* reconstruction of the Secondary channel past segment */ + for ( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = bufChanL[i] * One_m_Ratio + bufChanR[i] * ratio_L; + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = 1.0f / (float) lMemRecalc; + incr = fac; + + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + tmp1 = bufChanL[i]; + tmp2 = bufChanR[i]; + + ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + + fac += incr; + } + } + else + { + /* reconstruction of the Secondary channel past segment */ + for ( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = 1.0f / (float) lMemRecalc; + incr = fac; + + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + tmp1 = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; + tmp2 = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + + ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + + fac += incr; + } + } + } + } + + if ( hCPE->hStereoICBWE != NULL ) + { + assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); + i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); + mvr2r( bufChanL + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[0], i ); + mvr2r( bufChanR + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[1], i ); + } + + return; +} +#endif +/*--------------------------------------------------------------- + * stereo_tca_enc() + * + * Stereo temporal inter-channel adjustment/allocation processing module; + * Downmix, convert L/R to M/S. + * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_tca_enc( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const int16_t input_frame /* i : length of a frame per channel */ +) +{ + /* temp variables */ + int16_t i, dsFactor, lMemRecalc; + Encoder_State **sts; + STEREO_TCA_ENC_HANDLE hStereoTCA; + + /* Buffers, input Left and right channels @ input_Fs*/ + int16_t lMemRecalc_SCh; + float bufChanL[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + float bufChanR[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + float input_mem_loc[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; + float *ptrChanL, *ptrChanR; +#ifdef IVAS_FLOAT_FIXED + set_f( bufChanL, 0.0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set_f( bufChanR, 0.0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set_f( input_mem_loc[0], 0.0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + set_f( input_mem_loc[1], 0.0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + Word32 input_mem_loc_fx[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; + Word32 bufChanL_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + Word32 bufChanR_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + Word32 *ptrChanL_fx, *ptrChanR_fx; + + set32_fx( bufChanL_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set32_fx( bufChanR_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set32_fx( input_mem_loc_fx[0], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + set32_fx( input_mem_loc_fx[1], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); +#endif + /* Buffers at internal sampling rate, i.e., CORR_INTER_FS */ + float bufChanL_DS[L_FRAME_DS + ADDED_MEM_DS]; + float bufChanR_DS[L_FRAME_DS + ADDED_MEM_DS]; + float *ptrChanL_DS, *ptrChanR_DS; +#ifdef IVAS_FLOAT_FIXED + Word32 bufChanL_DS_fx[L_FRAME_DS + ADDED_MEM_DS]; + Word32 bufChanR_DS_fx[L_FRAME_DS + ADDED_MEM_DS]; + Word32 *ptrChanL_DS_fx, *ptrChanR_DS_fx; +#endif + float *target; +#ifdef IVAS_FLOAT_FIXED + Word32 *target_fx; +#endif + int16_t target_idx; + + int16_t prevNCShift, currentNCShift; + int16_t tempLag[2]; + float corrEstStage2[N_MAX_SHIFT_CHANGE + 1]; +#ifdef IVAS_FLOAT_FIXED + Word32 corrEstStage2_fx[N_MAX_SHIFT_CHANGE + 1]; + Word16 corrEstStage2_exp; + Word16 q_com; +#endif +#ifdef IVAS_FLOAT_FIXED + Word16 q_target; +#endif + /* temp variables */ + float tempF, tempF1; +#ifdef IVAS_FLOAT_FIXED + Word32 tempF1_fx; + Word16 tempF1_exp; +#endif + int16_t tempS, tempS_buff[3]; + int16_t maxCorrStatsDev, L_shift_adapt; + int16_t musicMode = 0, neighborLimit; + int32_t input_Fs; + int16_t prev_ICA_flag; + + /* initialization */ + sts = hCPE->hCoreCoder; + hStereoTCA = hCPE->hStereoTCA; + + input_Fs = sts[0]->input_Fs; + + lMemRecalc = NS2SA( input_Fs, L_MEM_RECALC_NS ); + lMemRecalc_SCh = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); + + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + return; + } + + /* populate L/R memories into current buffers */ + mvr2r( hStereoTCA->memChanL, bufChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( hStereoTCA->memChanR, bufChanR, lMemRecalc + lMemRecalc_SCh ); + + /* pointers to the current frame */ + ptrChanL = bufChanL + lMemRecalc + lMemRecalc_SCh; + ptrChanR = bufChanR + lMemRecalc + lMemRecalc_SCh; +#ifdef IVAS_FLOAT_FIXED + ptrChanL_fx = bufChanL_fx + lMemRecalc + lMemRecalc_SCh; + ptrChanR_fx = bufChanR_fx + lMemRecalc + lMemRecalc_SCh; +#endif + /* copy interleaved stereo data to two channels, e.g., L, R */ + mvr2r( sts[0]->input, ptrChanL, input_frame ); + mvr2r( sts[1]->input, ptrChanR, input_frame ); + + /* UNCLR classifier update */ + if ( hCPE->hStereoClassif->lrtd_mode == 0 ) /* Normal TD mode, no attenuation */ + { + hStereoTCA->LRTD_G_ATT_cnt = 1; + } + else if ( hCPE->hStereoTD != NULL ) + { + if ( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) /* lrtd_mode == 1, but in td section */ + { + hStereoTCA->LRTD_G_ATT_cnt++; + hStereoTCA->LRTD_G_ATT_cnt = min( 1000, hStereoTCA->LRTD_G_ATT_cnt ); + } + } + + if ( hCPE->element_mode != IVAS_CPE_TD ) + { + hStereoTCA->refChanIndx = L_CH_INDX; + hStereoTCA->corrStatsSmoothFac = 0.7f; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame ); + // worst case input_frame value is 960 so taking 10 as guard bits + q_com = s_min( q_com, L_get_q_buf1( ptrChanR, input_frame ) ) - 10; + + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame ); // not modified + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame ); + q_target = L_get_q_buf1( &hStereoTCA->prevTargetGain, 1 ); + hStereoTCA->prevTargetGain_fx = float_to_fix( hStereoTCA->prevTargetGain, q_target ); + hStereoTCA->prevTargetGain_fx_e = Q31 - q_target; + hStereoTCA->corrStatsSmoothFac_fx = float_to_fix16( hStereoTCA->corrStatsSmoothFac, Q15 ); +#endif + estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, 0, input_frame, hCPE->element_mode, NULL, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hStereoTCA->instTargetGain = fix_to_float( hStereoTCA->instTargetGain_fx, Q31 - hStereoTCA->instTargetGain_fx_e ); + hStereoTCA->targetGain = fix_to_float( hStereoTCA->targetGain_fx, Q31 - hStereoTCA->targetGain_fx_e ); +#endif +#else + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, 0, input_frame, hCPE->element_mode, NULL, 0 ); +#endif + + hStereoTCA->prevTargetGain = hStereoTCA->targetGain; +#ifdef DEBUG_MODE_INFO + hStereoTCA->indx_ica_NCShift = 0; +#endif + + /* back up the L/R missing target */ + mvr2r( bufChanL + input_frame, hStereoTCA->memChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( bufChanR + input_frame, hStereoTCA->memChanR, lMemRecalc + lMemRecalc_SCh ); + + hStereoTCA->lMemRecalc = 0; + hStereoTCA->lMemRecalc_12k8 = 0; + hStereoTCA->lMemRecalc_16k = 0; + + return; + } + else if ( hCPE->last_element_mode != IVAS_CPE_TD ) + { + tempF = hStereoTCA->targetGain; + tempF1 = hStereoTCA->prevTargetGain; + tempS = hStereoTCA->prevRefChanIndx; + mvs2s( hStereoTCA->prevCorrLagStats, tempS_buff, 3 ); + stereo_tca_init_enc( hStereoTCA, input_Fs ); +#ifdef IVAS_FLOAT_FIXED + stereo_tca_init_enc_fx( hStereoTCA, input_Fs ); +#endif + hStereoTCA->targetGain = tempF; + hStereoTCA->prevTargetGain = tempF1; + + if ( hCPE->hStereoClassif->lrtd_mode == 1 ) + { + hStereoTCA->targetGain = min( hStereoTCA->targetGain, 1.0f ); + hStereoTCA->prevTargetGain = min( hStereoTCA->prevTargetGain, 1.0f ); + + hStereoTCA->prevTargetGain = 1; + } + + hStereoTCA->prevRefChanIndx = tempS; + mvs2s( tempS_buff, hStereoTCA->prevCorrLagStats, 3 ); + + /* populate memory */ + if ( hCPE->last_element_mode == IVAS_CPE_MDCT ) + { + mvr2r( sts[0]->input - lMemRecalc - lMemRecalc_SCh, bufChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( sts[1]->input - lMemRecalc - lMemRecalc_SCh, bufChanR, lMemRecalc + lMemRecalc_SCh ); + } + } + + /* populate L/R DS memories into current buffers */ + mvr2r( hStereoTCA->memChanL_DS, bufChanL_DS, ADDED_MEM_DS ); + mvr2r( hStereoTCA->memChanR_DS, bufChanR_DS, ADDED_MEM_DS ); + + /* pointers to the current frame of DS */ + ptrChanL_DS = bufChanL_DS + ADDED_MEM_DS; + ptrChanR_DS = bufChanR_DS + ADDED_MEM_DS; +#ifdef IVAS_FLOAT_FIXED + ptrChanL_DS_fx = bufChanL_DS_fx + ADDED_MEM_DS; + ptrChanR_DS_fx = bufChanR_DS_fx + ADDED_MEM_DS; +#endif + /* resample factor */ + dsFactor = (int16_t) ( input_Fs / CORR_INTER_FS ); + + /* resample the stereo channels */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame ); + q_com = min( q_com, L_get_q_buf1( ptrChanR, input_frame ) ); + q_com = min( q_com, L_get_q_buf1( hStereoTCA->memdecim, 12 ) ) - 4; + + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame ); + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame ); + floatToFixed_arrL32( hStereoTCA->memdecim, hStereoTCA->memdecim_fx, q_com, 12 ); +#endif + + deEmphResample( hStereoTCA, ptrChanL_fx, ptrChanR_fx, ptrChanL_DS_fx, ptrChanR_DS_fx, input_frame, dsFactor ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( ptrChanL_DS_fx, ptrChanL_DS, q_com, input_frame / dsFactor ); + fixedToFloat_arrL32( ptrChanR_DS_fx, ptrChanR_DS, q_com, input_frame / dsFactor ); + fixedToFloat_arrL32( hStereoTCA->memdecim_fx, hStereoTCA->memdecim, q_com, 12 ); +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + +#endif +#else + deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); +#endif + /**********************NEED to Allign first 40 index in each channel ************************************/ + /* inter-channel corrStats estimation */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( bufChanL_DS, L_FRAME_DS + ADDED_MEM_DS ); + q_com = min( q_com, L_get_q_buf1( bufChanR_DS, L_FRAME_DS + ADDED_MEM_DS ) ) - 4; + + floatToFixed_arrL32( bufChanL_DS, bufChanL_DS_fx, q_com, L_FRAME_DS + ADDED_MEM_DS ); + floatToFixed_arrL32( bufChanR_DS, bufChanR_DS_fx, q_com, L_FRAME_DS + ADDED_MEM_DS ); + hStereoTCA->prevTargetGain_fx = floatToFixed_32( hStereoTCA->prevTargetGain, Q29 ); +#endif + + corrStatsEst_fx( hStereoTCA, bufChanL_DS_fx + ADDED_MEM_DS, bufChanR_DS_fx + ADDED_MEM_DS, q_com, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hStereoTCA->corrStatsSmoothFac = me2f_16( hStereoTCA->corrStatsSmoothFac_fx, 0 ); +#endif +#else + corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); +#endif + /*-----------------------------------------------------------------* + * refine the ICA stats + *-----------------------------------------------------------------*/ + + prev_ICA_flag = 0; + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec && abs( hStereoTCA->prevCorrLagStats[2] ) != 0 ) + { + prev_ICA_flag = 1; + } + + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) + { + /* initialize the refinement search for NC-shift */ + hStereoTCA->corrLagStats[2] = hStereoTCA->corrLagStats[1]; + + maxCorrStatsDev = N_MAX_SHIFT_CHANGE; + if ( hStereoTCA->corrStatsSmoothFac <= 0.7f ) + { + maxCorrStatsDev = 160; /* L_NCSHIFT_MAX @ 32kHz */ + } + + if ( input_Fs < 32000 ) + { + maxCorrStatsDev = (int16_t) ( maxCorrStatsDev * input_Fs / 32000.0f ); + } + + musicMode = ( hCPE->hCoreCoder[0]->sp_aud_decision0 == 1 || sts[0]->last_core > ACELP_CORE ); + if ( musicMode ) + { + maxCorrStatsDev = 1; + set_s( hStereoTCA->corrLagStats + 1, 0, 2 ); + } + + tempS = ( hStereoTCA->corrLagStats[1] - hStereoTCA->prevCorrLagStats[2] ); + if ( abs( tempS ) > maxCorrStatsDev ) + { + hStereoTCA->corrLagStats[2] = hStereoTCA->prevCorrLagStats[2] + ( ( tempS > 0 ) ? maxCorrStatsDev : -maxCorrStatsDev ); + } + + neighborLimit = maxCorrStatsDev; + + /* refine and search based on the corrlag stats */ + if ( tempS != 0 && dsFactor != 1 && prev_ICA_flag == 0 ) + { + tempF = 0; + if ( !musicMode ) + { + tempLag[0] = min( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); + tempLag[1] = max( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); + + neighborLimit = min( 3, maxCorrStatsDev ); + if ( hStereoTCA->prevCorrLagStats[2] < hStereoTCA->corrLagStats[2] ) + { + tempLag[1] = min( tempLag[1], tempLag[0] + neighborLimit ); + } + else + { + tempLag[0] = max( tempLag[0], tempLag[1] - neighborLimit ); + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ptrChanL_q = Q_factor_arrL( ptrChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + Word16 ptrChanR_q = Q_factor_arrL( ptrChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanL, ptrChanL_fx, ptrChanL_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanR, ptrChanR_fx, ptrChanR_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); +#endif + utilCrossCorr_fx( ptrChanL_fx, ptrChanL_q, ptrChanR_fx, ptrChanR_q, NULL, corrEstStage2_fx, &corrEstStage2_exp, tempLag, input_frame, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( corrEstStage2_fx, corrEstStage2, ( Q31 - corrEstStage2_exp ), N_MAX_SHIFT_CHANGE + 1 ); +#endif +#else + utilCrossCorr( ptrChanL, ptrChanR, NULL, corrEstStage2, tempLag, input_frame, 0 ); +#endif + hStereoTCA->corrLagStats[2] = maximum( corrEstStage2, ( tempLag[1] - tempLag[0] + 1 ), &tempF ); + hStereoTCA->corrLagStats[2] += tempLag[0]; + } + + if ( abs( tempS ) > neighborLimit ) + { + tempLag[0] = hStereoTCA->corrLagStats[1]; + tempLag[1] = hStereoTCA->corrLagStats[1]; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ptrChanL_q = Q_factor_arrL( ptrChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + Word16 ptrChanR_q = Q_factor_arrL( ptrChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanL, ptrChanL_fx, ptrChanL_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanR, ptrChanR_fx, ptrChanR_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); +#endif + utilCrossCorr_fx( ptrChanL_fx, ptrChanL_q, ptrChanR_fx, ptrChanR_q, NULL, &tempF1_fx, &tempF1_exp, tempLag, input_frame, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + tempF1 = fixedToFloat( tempF1_fx, Q31 - tempF1_exp ); +#endif +#else + utilCrossCorr( ptrChanL, ptrChanR, NULL, &tempF1, tempLag, input_frame, 0 ); +#endif + if ( tempF1 > tempF || musicMode ) + { + hStereoTCA->corrLagStats[2] = hStereoTCA->prevCorrLagStats[2] + ( ( tempS > 0 ) ? min( (int16_t) abs( tempS ), maxCorrStatsDev ) : max( (int16_t) -abs( tempS ), -maxCorrStatsDev ) ); + } + } + + /* restrict the reference channel for +/- variation */ + if ( ( hStereoTCA->corrLagStats[2] < 0 && hStereoTCA->prevCorrLagStats[2] > 0 ) || ( hStereoTCA->corrLagStats[2] > 0 && hStereoTCA->prevCorrLagStats[2] < 0 ) ) + { + hStereoTCA->corrLagStats[2] = 0; + } + } + + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec /*hCPE->hStereoClassif->lrtd_mode*/ == 1 ) /* Content is considered as uncorrelated -> ICA shift is turned off */ + { + hStereoTCA->corrLagStats[2] = 0; + + if ( hCPE->hStereoTD->tdm_LRTD_flag == 1 && prev_ICA_flag == 0 ) + { + hStereoTCA->prevCorrLagStats[2] = 0; + } + } + + /* Perform the following: + 1. adjust samples, + 2. interp shift variation, + 3. gain estimation */ + prevNCShift = (int16_t) abs( hStereoTCA->prevCorrLagStats[2] ); + currentNCShift = (int16_t) abs( hStereoTCA->corrLagStats[2] ); + + if ( hStereoTCA->prevRefChanIndx == L_CH_INDX ) + { + mvr2r( ptrChanL - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR + prevNCShift - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + } + else + { + mvr2r( ptrChanL + prevNCShift - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + } + + target = ptrChanR; +#ifdef IVAS_FLOAT_FIXED + target_fx = ptrChanR_fx; +#endif + target_idx = R_CH_INDX; + /* identify target signal to correct for shift variations */ + if ( ( prevNCShift == 0 && hStereoTCA->corrLagStats[2] < 0 ) || ( hStereoTCA->prevRefChanIndx == R_CH_INDX ) ) + { + target = ptrChanL; +#ifdef IVAS_FLOAT_FIXED + target_fx = ptrChanL_fx; +#endif + target_idx = L_CH_INDX; + } + + /* target signal adjustment for temporal shift variations */ + if ( ( prevNCShift - currentNCShift ) != 0 ) + { + L_shift_adapt = L_SHIFT_ADAPT_16k; + if ( input_Fs > INT_FS_16k ) + { + L_shift_adapt = L_SHIFT_ADAPT_MAX; + } + + /* Note!! : Always keep the assert (prevNCShift>>1) below according to the equation used here to get tempS */ + tempS = ( currentNCShift >> 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_com1 = L_get_q_buf1( bufChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ) - 4; + Word16 q_com2 = L_get_q_buf1( bufChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ) - 4; + floatToFixed_arrL32( bufChanR, bufChanR_fx, q_com1, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + floatToFixed_arrL32( bufChanL, bufChanL_fx, q_com2, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); +#endif + if ( abs( currentNCShift - prevNCShift ) <= min( N_MAX_SHIFT_CHANGE, N_MAX_SHIFT_CHANGE * input_Fs / 32000.0f ) ) + { +#ifdef IVAS_FLOAT_FIXED + adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 0 ); +#else + adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 0 ); +#endif + } + else + { + tempS = min( max( tempS, prevNCShift - currentNCShift + L_shift_adapt - input_frame ), prevNCShift - currentNCShift + lMemRecalc ); +#ifdef IVAS_FLOAT_FIXED + adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); +#else + adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); +#endif + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( bufChanR_fx, bufChanR, q_com1, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + fixedToFloat_arrL32( bufChanL_fx, bufChanL, q_com2, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); +#endif + if ( target_idx == L_CH_INDX ) + { + mvr2r( target - tempS, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); + } + else + { + v_multc( target - tempS, hStereoTCA->prevTargetGain, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); + } + } + + /* reference channel index */ + if ( hStereoTCA->corrLagStats[2] >= 0 ) + { + hStereoTCA->refChanIndx = L_CH_INDX; + } + else + { + hStereoTCA->refChanIndx = R_CH_INDX; + } + + /* Estimate and quantize the gain for scaling */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame ); + // worst case input_frame value is 960 so taking 10 as guard bits + q_com = s_min( q_com, L_get_q_buf1( ptrChanR, input_frame ) ) - 10; + + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame ); // not modified + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame ); + q_target = L_get_q_buf1( &hStereoTCA->prevTargetGain, 1 ); + hStereoTCA->prevTargetGain_fx = float_to_fix( hStereoTCA->prevTargetGain, q_target ); + hStereoTCA->prevTargetGain_fx_e = Q31 - q_target; + hStereoTCA->corrStatsSmoothFac_fx = float_to_fix16( hStereoTCA->corrStatsSmoothFac, Q15 ); +#endif + estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, currentNCShift, ( input_frame - currentNCShift ), hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hStereoTCA->instTargetGain = fix_to_float( hStereoTCA->instTargetGain_fx, Q31 - hStereoTCA->instTargetGain_fx_e ); + hStereoTCA->targetGain = fix_to_float( hStereoTCA->targetGain_fx, Q31 - hStereoTCA->targetGain_fx_e ); +#endif + +#else + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, ( input_frame - currentNCShift ), hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); +#endif + + /* quantize the corrStats */ + hStereoTCA->indx_ica_NCShift = (int16_t) usquant( ( (float) currentNCShift ) / dsFactor, &tempF, 0, 1.0f, 1 << STEREO_BITS_TCA_CORRSTATS ); + } + else + { + hStereoTCA->refChanIndx = L_CH_INDX; + hStereoTCA->corrLagStats[2] = 0; + hStereoTCA->prevCorrLagStats[2] = 0; + hStereoTCA->indx_ica_NCShift = 0; + + currentNCShift = 0; /* only to avoid compilation warning */ + target = ptrChanL; /* only to avoid compilation warning */ + target_idx = L_CH_INDX; /* only to avoid compilation warning */ + + mvr2r( ptrChanL - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + + /* Estimate and quantize the gain for scaling */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame ); + // worst case input_frame value is 960 so taking 10 as guard bits + q_com = s_min( q_com, L_get_q_buf1( ptrChanR, input_frame ) ) - 10; + + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame ); // not modified + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame ); + q_target = L_get_q_buf1( &hStereoTCA->prevTargetGain, 1 ); + hStereoTCA->prevTargetGain_fx = float_to_fix( hStereoTCA->prevTargetGain, q_target ); + hStereoTCA->prevTargetGain_fx_e = Q31 - q_target; + hStereoTCA->corrStatsSmoothFac_fx = float_to_fix16( hStereoTCA->corrStatsSmoothFac, Q15 ); +#endif + estDownmixGain_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, q_com, 0, input_frame, hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hStereoTCA->instTargetGain = fix_to_float( hStereoTCA->instTargetGain_fx, Q31 - hStereoTCA->instTargetGain_fx_e ); + hStereoTCA->targetGain = fix_to_float( hStereoTCA->targetGain_fx, Q31 - hStereoTCA->targetGain_fx_e ); +#endif +#else + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, 0, input_frame, hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); +#endif + } + + /*-----------------------------------------------------------------* + * updates and memory backups + *-----------------------------------------------------------------*/ - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) - { - tmp1 = bufChanL[i]; - tmp2 = bufChanR[i]; + /* back up the L/R missing target */ + mvr2r( bufChanL + input_frame, hStereoTCA->memChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( bufChanR + input_frame, hStereoTCA->memChanR, lMemRecalc + lMemRecalc_SCh ); - ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; - /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ - ptr2[i] = tmp2; + IF( currentNCShift != 0 ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + q_com = s_min( q_com, L_get_q_buf1( ptrChanR, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ) ) - 4; + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); +#endif + /* Temporal channel adjustment of the LA samples based on the NC shift */ + tcaTargetCh_LA_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, &q_com, currentNCShift, input_frame ); - fac += incr; - } - } - else - { - /* reconstruction of the Secondary channel past segment */ - for ( i = 0; i < lMemRecalc_SCh; i++ ) - { - ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; - } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( ptrChanL_fx, ptrChanL, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + fixedToFloat_arrL32( ptrChanR_fx, ptrChanR, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); +#endif + } +#else + if ( currentNCShift != 0 ) + { + /* Temporal channel adjustment of the LA samples based on the NC shift */ + tcaTargetCh_LA( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, input_frame ); + } +#endif + /* Update of changed samples corresponding to the memory */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( input_mem_loc[0], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + q_com = s_min( q_com, L_get_q_buf1( input_mem_loc[1], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ) ) - 4; + floatToFixed_arrL32( input_mem_loc[0], input_mem_loc_fx[0], q_com, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + floatToFixed_arrL32( input_mem_loc[1], input_mem_loc_fx[1], q_com, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + + floatToFixed_arrL32( sts[0]->input_buff, sts[0]->input_buff32_fx, q_com, 1965 ); + floatToFixed_arrL32( sts[1]->input_buff, sts[1]->input_buff32_fx, q_com, 1965 ); +#endif + icaMemUpdate_fx( sts, hCPE, input_mem_loc_fx[0], input_mem_loc_fx[1], q_com, lMemRecalc, lMemRecalc_SCh, input_frame ); - /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ - fac = 1.0f / (float) lMemRecalc; - incr = fac; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( sts[0]->input_buff32_fx, sts[0]->input_buff, q_com, 1965 ); + fixedToFloat_arrL32( sts[1]->input_buff32_fx, sts[1]->input_buff, q_com, 1965 ); + if ( hCPE->hStereoICBWE != NULL ) + { + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], hCPE->hStereoICBWE->icbwe_inp_mem[0], hCPE->hStereoICBWE->q_dataChan_fx, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], hCPE->hStereoICBWE->icbwe_inp_mem[1], hCPE->hStereoICBWE->q_dataChan_fx, NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ) ); + } +#endif +#else + icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); +#endif + /* populate the st->input target buffer */ + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) + { + mvr2r( target + currentNCShift, sts[target_idx]->input, input_frame ); + } - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) - { - tmp1 = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; - tmp2 = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + if ( hCPE->element_mode != IVAS_CPE_DFT ) + { + /* Scale the Right channel with the gain */ + int16_t j; + int16_t l_ica_ovl = NS2SA( input_Fs, STEREO_L_TCA_OVLP_NS ); + float winSlope = 1.0f / (float) l_ica_ovl; - ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; - /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ - ptr2[i] = tmp2; + tempF1 = hStereoTCA->targetGain; + tempF = hStereoTCA->prevTargetGain; - fac += incr; - } - } + for ( i = 0, j = 0; i < l_ica_ovl; i++, j++ ) + { + sts[1]->input[i] = ( 1.0f - j * winSlope ) * tempF * sts[1]->input[i] + ( j * winSlope ) * tempF1 * sts[1]->input[i]; + } + for ( ; i < input_frame; i++ ) + { + sts[1]->input[i] *= tempF1; } } - if ( hCPE->hStereoICBWE != NULL ) - { - assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); - i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); - mvr2r( bufChanL + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[0], i ); - mvr2r( bufChanR + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[1], i ); - } + /* update L/R DS memories */ + mvr2r( bufChanL_DS + L_FRAME_DS, hStereoTCA->memChanL_DS, ADDED_MEM_DS ); + mvr2r( bufChanR_DS + L_FRAME_DS, hStereoTCA->memChanR_DS, ADDED_MEM_DS ); - return; -} + /* save the reference channel index for next frame */ + hStereoTCA->prevRefChanIndx = hStereoTCA->refChanIndx; -/*--------------------------------------------------------------- - * stereo_tca_enc() - * - * Stereo temporal inter-channel adjustment/allocation processing module; - * Downmix, convert L/R to M/S. - * ---------------------------------------------------------------*/ + /* save the corr lag stats for next frame */ + mvs2s( hStereoTCA->corrLagStats, hStereoTCA->prevCorrLagStats, 3 ); + /* save the target gain for next frame */ + hStereoTCA->prevTargetGain = hStereoTCA->targetGain; + + return; +} +#else void stereo_tca_enc( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int16_t input_frame /* i : length of a frame per channel */ @@ -1251,7 +2882,6 @@ void stereo_tca_enc( float bufChanR[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; float input_mem_loc[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; float *ptrChanL, *ptrChanR; - /* Buffers at internal sampling rate, i.e., CORR_INTER_FS */ float bufChanL_DS[L_FRAME_DS + ADDED_MEM_DS]; float bufChanR_DS[L_FRAME_DS + ADDED_MEM_DS]; @@ -1292,7 +2922,6 @@ void stereo_tca_enc( /* pointers to the current frame */ ptrChanL = bufChanL + lMemRecalc + lMemRecalc_SCh; ptrChanR = bufChanR + lMemRecalc + lMemRecalc_SCh; - /* copy interleaved stereo data to two channels, e.g., L, R */ mvr2r( sts[0]->input, ptrChanL, input_frame ); mvr2r( sts[1]->input, ptrChanR, input_frame ); @@ -1367,17 +2996,17 @@ void stereo_tca_enc( /* pointers to the current frame of DS */ ptrChanL_DS = bufChanL_DS + ADDED_MEM_DS; ptrChanR_DS = bufChanR_DS + ADDED_MEM_DS; - /* resample factor */ dsFactor = (int16_t) ( input_Fs / CORR_INTER_FS ); /* resample the stereo channels */ - deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); + deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); + /**********************NEED to Allign first 40 index in each channel ************************************/ /* inter-channel corrStats estimation */ - corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); + corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); /*-----------------------------------------------------------------* * refine the ICA stats *-----------------------------------------------------------------*/ @@ -1520,7 +3149,6 @@ void stereo_tca_enc( tempS = min( max( tempS, prevNCShift - currentNCShift + L_shift_adapt - input_frame ), prevNCShift - currentNCShift + lMemRecalc ); adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); } - if ( target_idx == L_CH_INDX ) { mvr2r( target - tempS, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); @@ -1578,10 +3206,9 @@ void stereo_tca_enc( /* Temporal channel adjustment of the LA samples based on the NC shift */ tcaTargetCh_LA( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, input_frame ); } - /* Update of changed samples corresponding to the memory */ - icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); + icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); /* populate the st->input target buffer */ if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) { @@ -1623,7 +3250,7 @@ void stereo_tca_enc( return; } - +#endif /*-------------------------------------------------------------------* * stereo_tca_init_enc() * @@ -1654,22 +3281,29 @@ void stereo_tca_init_enc( set_f( hStereoTCA->memChanR, 0.0f, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH ); set_f( hStereoTCA->memChanL_DS, 0.0f, ADDED_MEM_DS ); set_f( hStereoTCA->memChanR_DS, 0.0f, ADDED_MEM_DS ); + set_f( hStereoTCA->memdecim, 0.0f, 12 ); +#ifndef IVAS_FLOAT_FIXED hStereoTCA->mem_tempF = 0.; set_f( hStereoTCA->corrEstPrev[0], 0.0f, 2 * L_NCSHIFT_DS + 1 ); set_f( hStereoTCA->corrEstPrev[1], 0.0f, 2 * L_NCSHIFT_DS + 1 ); set_f( hStereoTCA->corrEstPrev[2], 0.0f, 2 * L_NCSHIFT_DS + 1 ); - set_f( hStereoTCA->corrEstLT, 0.0f, 2 * L_NCSHIFT_DS + 1 ); - set_f( hStereoTCA->memdecim, 0.0f, 12 ); hStereoTCA->ica_envVarLT = 2000.0f; - set_f( hStereoTCA->C_mem, 0.0f, 2 * L_NCSHIFT_DS + 1 ); hStereoTCA->E1_mem = 0.0f; hStereoTCA->E2_mem = 0.0f; set_f( hStereoTCA->delay_0_mem, 0.0f, MAX_DELAYREGLEN ); hStereoTCA->smooth_dist_reg_prv_corr = 1.0f; +#endif hStereoTCA->LRTD_G_ATT_cnt = 1; - + set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + set16_fx( hStereoTCA->C_mem_exp, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + hStereoTCA->E1_mem_fx = 0; + move32(); + hStereoTCA->E2_mem_fx = 0; + move32(); + hStereoTCA->E1_E2_mem_exp = 0; + move16(); return; } @@ -1683,11 +3317,11 @@ void stereo_tca_init_enc_fx( hStereoTCA->lMemRecalc = NS2SA_FX2( input_Fs, L_MEM_RECALC_NS ); move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_12k8 ), input_Fs, &div_e ); - hStereoTCA->lMemRecalc_12k8 = shr( div1, sub( 15, div_e ) ); + hStereoTCA->lMemRecalc_12k8 = shr( div1, 1 + sub( 15, div_e ) ); move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_16k ), input_Fs, &div_e ); - hStereoTCA->lMemRecalc_16k = shr( div1, sub( 15, div_e ) ); + hStereoTCA->lMemRecalc_16k = shr( div1, 1 + sub( 15, div_e ) ); move16(); hStereoTCA->refChanIndx = L_CH_INDX; @@ -1701,6 +3335,12 @@ void stereo_tca_init_enc_fx( move32(); move32(); move32(); + hStereoTCA->targetGain_fx_e = Q2; // Q31 - Q29 + hStereoTCA->prevTargetGain_fx_e = Q2; // Q31 - Q29 + hStereoTCA->instTargetGain_fx_e = Q2; // Q31 - Q29 + move16(); + move16(); + move16(); hStereoTCA->corrStatsSmoothFac_fx = 22937; // Q15 move16(); @@ -1714,22 +3354,35 @@ void stereo_tca_init_enc_fx( set32_fx( hStereoTCA->memChanR_DS_fx, 0, ADDED_MEM_DS ); hStereoTCA->mem_tempF_fx = 0; move32(); + hStereoTCA->mem_tempF_exp = 0; + move16(); set32_fx( hStereoTCA->corrEstPrev_fx[0], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[1], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[2], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); - + hStereoTCA->corrEstPrev_exp = 0; + move16(); set32_fx( hStereoTCA->corrEstLT_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + hStereoTCA->corrEstLT_exp = 0; + move16(); set32_fx( hStereoTCA->memdecim_fx, 0, 12 ); hStereoTCA->ica_envVarLT_fx = 2097152000; // 2000 in Q20 move32(); + hStereoTCA->ica_envVarLT_exp = 11; // 2000 in Q20 + move16(); set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + set16_fx( hStereoTCA->C_mem_exp, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); hStereoTCA->E1_mem_fx = 0; - hStereoTCA->E2_mem_fx = 0; move32(); + hStereoTCA->E2_mem_fx = 0; move32(); + hStereoTCA->E1_E2_mem_exp = 0; + move16(); set32_fx( hStereoTCA->delay_0_mem_fx, 0, MAX_DELAYREGLEN ); - hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX16B; // Q15 + hStereoTCA->delay_0_mem_exp = 0; + move16(); + hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX_32; // Q15 + hStereoTCA->smooth_dist_reg_prv_corr_exp = 0; // Q15 hStereoTCA->LRTD_G_ATT_cnt = 1; move16(); move16(); @@ -1740,7 +3393,219 @@ void stereo_tca_init_enc_fx( * Function unclr_calc_corr_features() * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void unclr_calc_corr_features_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + Word32 buf1[], /* i : left channel q_com*/ + Word32 buf2[], /* i : right channel q_com*/ + Word16 q_com, + const Word16 length, /* i : length of input signal buffers */ + Word32 corrEst[], /* i : buffer containing inter-channel correlation values corrEst_exp*/ + Word16 corrEst_exp, + const Word16 lagSearchRange[], /* i : minimum and maximum lags for corrEst[] */ + Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers corrEst_ncorr_exp*/ + Word16 *corrEst_ncorr_exp ) +{ + Word16 i, corrLagMax, d_corrLagMax, tempLen, k; + Word32 num, den; + Word32 corrL, corrR, ener, ener_side, mono_i, side_i, ic_Lm, ic_Rm, tdm_es_em, m_corrL_corrR, d_corrL_corrR; + Word32 sum_prod, corrEstMax; + Word16 corrL_exp, corrR_exp, ener_exp, ener_side_exp, sum_prod_exp, exp, exp1, exp2, num_exp, den_exp; + + corrL = ONE_IN_Q31; + move32(); + corrL_exp = 0; + move16(); + corrR = ONE_IN_Q31; + move32(); + corrR_exp = 0; + move16(); + ener = ONE_IN_Q31; + move32(); + ener_exp = 0; + move16(); + ener_side = ONE_IN_Q31; + move32(); + ener_side_exp = 0; + move16(); + sum_prod = 0; + move32(); + sum_prod_exp = 0; + move16(); + + FOR( i = 0; i < length; i++ ) + { + mono_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_shr( buf2[i], 1 ), sub( 31, q_com ), &exp ); + corrL = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, Mpy_32_32( buf1[i], mono_i ), add( sub( 31, q_com ), exp ), &corrL_exp ); + corrR = BASOP_Util_Add_Mant32Exp( corrR, corrR_exp, Mpy_32_32( buf2[i], mono_i ), add( sub( 31, q_com ), exp ), &corrR_exp ); + ener = BASOP_Util_Add_Mant32Exp( ener, ener_exp, Mpy_32_32( mono_i, mono_i ), shl( exp, 1 ), &ener_exp ); + + side_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_negate( L_shr( buf2[i], 1 ) ), sub( 31, q_com ), &exp ); + ener_side = BASOP_Util_Add_Mant32Exp( ener_side, ener_side_exp, Mpy_32_32( side_i, side_i ), shl( exp, 1 ), &ener_side_exp ); + sum_prod = BASOP_Util_Add_Mant32Exp( sum_prod, sum_prod_exp, Mpy_32_32( buf1[i], buf2[i] ), sub( 62, shl( q_com, 1 ) ), &sum_prod_exp ); + } + + /* average energy of L and R channels */ + hStereoClassif->ave_ener_L_fx = Mpy_32_32( hStereoTCA->E1_mem_fx, 13421772 /* 1/length in Q31*/ ); + move32(); + hStereoClassif->ave_ener_L_fx_e = hStereoTCA->E1_E2_mem_exp; + move16(); + hStereoClassif->ave_ener_R_fx = Mpy_32_32( hStereoTCA->E2_mem_fx, 13421772 /* 1/length in Q31*/ ); + move32(); + hStereoClassif->ave_ener_R_fx_e = hStereoTCA->E1_E2_mem_exp; + move16(); + + /* unnormalized L/R correlation */ + IF( sum_prod ) + { + sum_prod = BASOP_Util_Log10( L_abs( sum_prod ), sum_prod_exp ); + sum_prod_exp = 6; + move16(); + } + ELSE + { + sum_prod = 0; + move32(); + sum_prod_exp = 0; + move16(); + } + + hStereoClassif->unclr_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15 + move32(); + /* S/M energy ratio */ + Word32 inp1 = Sqrt32( Mpy_32_32( ener_side, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_side_exp ); + inp1 = BASOP_Util_Log10( inp1, ener_side_exp ); + Word16 temp = ener_exp; + move16(); + Word32 inp2 = Sqrt32( Mpy_32_32( ener, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_exp ); + inp2 = BASOP_Util_Log10( inp2, ener_exp ); + ener_exp = temp; + move16(); + + tdm_es_em = L_abs( Mpy_32_32( L_sub( inp1, inp2 ), 1342177280 ) ); /* Q25 + Q27 - Q31 = 21*/ + + hStereoClassif->unclr_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15 + move32(); + + /* L/R correlation values (zero lag, maximum) */ + corrLagMax = maximum_l( corrEst, sub( lagSearchRange[1], add( lagSearchRange[0], 1 ) ), &corrEstMax ); + d_corrLagMax = sub( corrLagMax, hStereoClassif->unclr_corrLagMax_prev ); + + hStereoClassif->unclr_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 ); + move32(); + hStereoClassif->unclr_corrLagMax_prev = corrLagMax; + move32(); + hStereoClassif->xtalk_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 ); + move32(); + + if ( corrEstMax < 0 ) + { + corrEstMax = 0; + move32(); + } + + hStereoClassif->unclr_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->unclr_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->unclr_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); + move32(); + + /* L/M and R/M correlation */ + if ( corrL < 0 ) + { + corrL = 0; + move32(); + } + + if ( corrR < 0 ) + { + corrR = 0; + move32(); + } + + ic_Lm = BASOP_Util_Divide3232_Scale_cadence( corrL, ener, &exp1 ); + exp1 = add( exp1, sub( corrL_exp, ener_exp ) ); + ic_Rm = BASOP_Util_Divide3232_Scale_cadence( corrR, ener, &exp2 ); + exp2 = add( exp2, sub( corrR_exp, ener_exp ) ); + + m_corrL_corrR = L_sub( L_max( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ), L_min( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ) ); // s_max(exp1, exp2) + + inp1 = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, corrR, corrR_exp, &exp ); + IF( inp1 ) + { + d_corrL_corrR = BASOP_Util_Log10( L_abs( inp1 ), exp ); // Q25 + } + ELSE + { + d_corrL_corrR = 0; + move32(); + } + + hStereoClassif->unclr_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15 + move32(); + hStereoClassif->unclr_fv_fx[E_d_corrL_corrR] = L_shr( d_corrL_corrR, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15 + move32(); + + /* norm. x-correlation btw. current and previous correlation buffers */ + tempLen = ( 2 * L_NCSHIFT_DS + 1 ); + + Word64 L64_sum = 0; + move64(); + FOR( k = 0; k < tempLen; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, corrEst[k], hStereoTCA->corrEstPrev_fx[2][k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + num = W_extract_h( L64_sum ); // ener_side_q + num_exp = sub( 31, sub( add( add( add( sub( 31, corrEst_exp ), sub( 31, hStereoTCA->corrEstPrev_exp ) ), 1 ), k ), 32 ) ); + + exp1 = corrEst_exp; + move16(); + inp1 = sum2_32_exp_fx( corrEst, tempLen, &exp1, 3 ); + + exp2 = hStereoTCA->corrEstPrev_exp; + move16(); + inp2 = sum2_32_exp_fx( hStereoTCA->corrEstPrev_fx[2], tempLen, &exp2, 3 ); + den_exp = add( exp1, exp2 ); + den = Sqrt32( Mpy_32_32( inp1, inp2 ), &den_exp ); + + IF( den == 0 ) + { + *corrEst_ncorr = 0; + move16(); + *corrEst_ncorr_exp = 0; + move32(); + } + ELSE + { + *corrEst_ncorr = BASOP_Util_Divide3232_Scale_cadence( num, den, &exp ); + *corrEst_ncorr_exp = add( exp, sub( num_exp, den_exp ) ); + } + + hStereoClassif->unclr_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); + move32(); + + return; +} +#else static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ @@ -1839,3 +3704,4 @@ static void unclr_calc_corr_features( return; } +#endif diff --git a/lib_enc/ivas_stereo_icbwe_enc.c b/lib_enc/ivas_stereo_icbwe_enc.c index 1c5d7de02fa669284184558949c022899eca97af..63a5f0e11749017cb8061e1993af4660813bc1ed 100644 --- a/lib_enc/ivas_stereo_icbwe_enc.c +++ b/lib_enc/ivas_stereo_icbwe_enc.c @@ -44,6 +44,7 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "ivas_rom_com_fx.h" #endif /*-------------------------------------------------------------------* @@ -51,7 +52,7 @@ * * core switching reset of IC BWE memory *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void ic_bwe_enc_reset( STEREO_ICBWE_ENC_HANDLE hStereoICBWE /* i/o: Stereo ICBWE handle */ ) @@ -73,13 +74,60 @@ static void ic_bwe_enc_reset( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +static void ic_bwe_enc_reset_fx( + STEREO_ICBWE_ENC_HANDLE hStereoICBWE /* i/o: Stereo ICBWE handle */ +) +{ + /* unscaled & scaled SHB synthesis memory */ + set32_fx( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 0, LPC_SHB_ORDER ); + hStereoICBWE->mem_lpc_shbsynth_nonref_e = 0; + move16(); + /* inter-channel BWE spectral shape adj. */ + hStereoICBWE->prevSpecMapping_fx = 0; + move32(); + hStereoICBWE->prevgsMapping_fx = ONE_IN_Q31; + move32(); + hStereoICBWE->prevgsMapping_e = 0; + move16(); + set32_fx( &( hStereoICBWE->memShbSpecMapping_fx ), 0, 1 ); + hStereoICBWE->memShbSpecMapping_e = 0; + move16(); + set32_fx( hStereoICBWE->memShbSpecXcorr_fx, 0, 6 ); + hStereoICBWE->memShbSpecXcorr_e = 0; + move16(); + set32_fx( hStereoICBWE->memGsEnerMap_fx, ONE_IN_Q31, 2 ); + hStereoICBWE->memGsEnerMap_e = 0; + move16(); + set32_fx( hStereoICBWE->mem_nrg_L_fx, 0, 2 ); + hStereoICBWE->mem_nrg_L_fx_e = 0; + move16(); + set32_fx( hStereoICBWE->mem_nrg_R_fx, 0, 2 ); + hStereoICBWE->mem_nrg_R_fx_e = 0; + move16(); + set32_fx( hStereoICBWE->mem_nrg_DMX_fx, 0, 2 ); + hStereoICBWE->mem_nrg_DMX_fx_e = 0; + move16(); + hStereoICBWE->gDes_pastFrame_fx = ONE_IN_Q31; + move32(); + hStereoICBWE->gDes_pastFrame_e = 0; + move16(); + hStereoICBWE->icbweRefEner_fx = 0; + move32(); + hStereoICBWE->icbweRefEner_fx_e = 0; + move16(); + + return; +} +#endif /*--------------------------------------------------------------------------* * ic_bwe_specMapping() * * Encode and apply the spectral shape mapping of ref to the non-ref channel *---------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static int16_t ic_bwe_enc_specMapping( const float *shb_frame_target, /* i : target shb */ float *shb_synth_nonref, /* o : non-ref shb synth */ @@ -169,6 +217,218 @@ static int16_t ic_bwe_enc_specMapping( return idx; } +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +static Word16 ic_bwe_enc_specMapping_ivas_fx( + const Word32 *shb_frame_target_fx, /* i : target shb */ + Word16 shb_frame_target_e, + Word32 *shb_synth_nonref_fx, /* o : non-ref shb synth */ + Word16 shb_synth_nonref_e, + Word32 *specMapping_fx, /* i/o: current frame's mapping */ + Word32 *memShbSpecMapping_fx, /* i/o: current frame's mapping */ + Word32 *memShbSpecXcorr_fx, /* i/o: ic bwe spec mapping scorr memory */ + Word16 *memShbSpecXcorr_e ) +{ + Word16 idx; + + Word16 Txx1_fx = 0, Txx2_fx = 0, Txx3_fx = 0, T_desired_fx = 0; + Word16 Txx1_e = 0, Txx2_e = 0, Txx3_e = 0, T_desired_e = 0; + Word16 T_nonref_target_fx, temp_fx; + Word32 temp0_fx, temp1_fx, temp2_fx, temp3_fx; + Word16 a_fx, b_fx, c_fx, a_e, b_e, c_e; + Word16 u_fx, u1_fx, u2_fx, u_e = 0, u1_e, u2_e; + Word16 temp0_exp, temp1_exp, temp2_exp, temp3_exp, exp, T_nonref_target_e; + Word16 exp_buf[6]; + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + /* Calculate rxx(1)/rxx(0) of the non ref target */ + + temp0_fx = dotp_fixed_ivas_fx( shb_frame_target_fx, shb_frame_target_e, shb_frame_target_fx, shb_frame_target_e, L_FRAME16k - 1, &temp0_exp ); + temp1_fx = dotp_fixed_ivas_fx( shb_frame_target_fx, shb_frame_target_e, shb_frame_target_fx + 1, shb_frame_target_e, L_FRAME16k - 1, &temp1_exp ); + + /* Smoothing */ + temp0_fx = L_shr( temp0_fx, 1 ); + temp1_fx = L_shr( temp1_fx, 1 ); + + + memShbSpecXcorr_fx[0] = temp0_fx; // tem0_exp + memShbSpecXcorr_fx[1] = L_shr( temp1_fx, temp0_exp - temp1_exp ); // temp0_exp + exp = sub( temp0_exp, temp1_exp ); + exp_buf[0] = exp; + exp_buf[1] = exp; + move32(); + move32(); + move16(); + move16(); + + IF( temp0_fx != 0 ) + { + T_nonref_target_fx = BASOP_Util_Divide3232_Scale( temp1_fx, temp0_fx, &T_nonref_target_e ); // exp + } + ELSE + { + T_nonref_target_fx = 0; + T_nonref_target_e = 31; + move32(); + move16(); + } + + /* Calculate rxx(1)/rxx(0) of the non ref synth */ + temp0_fx = dotp_fixed_ivas_fx( shb_synth_nonref_fx, shb_synth_nonref_e, shb_synth_nonref_fx, shb_synth_nonref_e, L_FRAME16k - 3, &temp0_exp ); + temp1_fx = dotp_fixed_ivas_fx( shb_synth_nonref_fx, shb_synth_nonref_e, shb_synth_nonref_fx + 1, shb_synth_nonref_e, L_FRAME16k - 3, &temp1_exp ); + temp2_fx = dotp_fixed_ivas_fx( shb_synth_nonref_fx, shb_synth_nonref_e, shb_synth_nonref_fx + 2, shb_synth_nonref_e, L_FRAME16k - 3, &temp2_exp ); + temp3_fx = dotp_fixed_ivas_fx( shb_synth_nonref_fx, shb_synth_nonref_e, shb_synth_nonref_fx + 3, shb_synth_nonref_e, L_FRAME16k - 3, &temp3_exp ); + + /* Smoothing */ + temp0_fx = L_shr( temp0_fx, 1 ); + temp1_fx = L_shr( temp1_fx, 1 ); + temp2_fx = L_shr( temp2_fx, 1 ); + temp3_fx = L_shr( temp3_fx, 1 ); + + exp_buf[2] = temp0_exp; + exp_buf[3] = temp1_exp; + exp_buf[4] = temp2_exp; + exp_buf[5] = temp3_exp; + exp = exp_buf[0]; + move16(); + move16(); + move16(); + move16(); + move16(); + FOR( Word16 i = 0; i < 6; i++ ) + { + IF( LT_16( exp, exp_buf[i] ) ) + { + exp = exp_buf[i]; + move16(); + } + } + memShbSpecXcorr_fx[2] = L_shr( temp0_fx, sub( exp, temp0_exp ) ); + memShbSpecXcorr_fx[3] = L_shr( temp1_fx, sub( exp, temp1_exp ) ); + memShbSpecXcorr_fx[4] = L_shr( temp2_fx, sub( exp, temp2_exp ) ); + memShbSpecXcorr_fx[5] = L_shr( temp3_fx, sub( exp, temp3_exp ) ); + *memShbSpecXcorr_e = exp; + + move32(); + move32(); + move32(); + move32(); + move16(); + + + IF( temp0_fx != 0 ) + { + Txx1_fx = BASOP_Util_Divide3232_Scale( temp1_fx, temp0_fx, &Txx1_e ); + Txx2_fx = BASOP_Util_Divide3232_Scale( temp2_fx, temp0_fx, &Txx2_e ); + Txx3_fx = BASOP_Util_Divide3232_Scale( temp3_fx, temp0_fx, &Txx3_e ); + } + + T_desired_fx = T_nonref_target_fx; + T_desired_e = T_nonref_target_e; + move32(); + move16(); + + Word16 tmp, tmp1; + exp = BASOP_Util_Add_MantExp( Txx3_fx, Txx3_e, Txx1_fx, Txx1_e, &tmp ); + tmp1 = mult( Txx2_fx, T_desired_fx ); // Txx2_e + T_desired_e + a_e = BASOP_Util_Add_MantExp( tmp1, sub( add( Txx2_e, T_desired_e ), 1 ), negate( tmp ), exp, &a_fx ); + + exp = BASOP_Util_Add_MantExp( Txx2_fx, Txx2_e, 32767, 1, &tmp ); + tmp1 = mult( Txx1_fx, T_desired_fx ); // Txx1_e + T_desired_e + b_e = BASOP_Util_Add_MantExp( tmp1, sub( add( Txx1_e, T_desired_e ), 1 ), negate( tmp ), exp, &b_fx ); + + c_e = BASOP_Util_Add_MantExp( T_desired_fx, T_desired_e, negate( Txx1_fx ), Txx1_e, &c_fx ); + + u_fx = extract_l( *specMapping_fx ); + + tmp = mult( b_fx, b_fx ); // b_e + b_e; + tmp1 = mult( a_fx, c_fx ); // a_e + c_e + 2 + + exp = BASOP_Util_Add_MantExp( tmp, add( b_e, b_e ), tmp1, add( a_e, add( c_e, 2 ) ), &temp_fx ); + test(); + IF( temp_fx >= 0 && a_fx != 0 ) + { + temp_fx = Sqrt16( temp_fx, &exp ); + exp = BASOP_Util_Add_MantExp( negate( b_fx ), b_e, temp_fx, exp, &tmp ); + u1_e = BASOP_Util_Divide1616_Scale( tmp, a_fx, &u1_fx ); + u1_e = add( u1_e, sub( exp, add( a_e, 1 ) ) ); + + exp = BASOP_Util_Add_MantExp( negate( b_fx ), b_e, negate( temp_fx ), exp, &tmp ); + u2_e = BASOP_Util_Divide1616_Scale( tmp, a_fx, &u2_fx ); + u2_e = add( u2_e, sub( exp, add( a_e, 1 ) ) ); + + test(); + IF( ( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( abs_s( u1_fx ) ), u1_e, 1, 31 ) < 0 ) && ( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( abs_s( u2_fx ) ), u2_e, 1, 31 ) < 0 ) ) + { + IF( ( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( abs_s( u1_fx ) ), u1_e, L_deposit_h( abs_s( u2_fx ) ), u2_e ) < 0 ) ) + { + u_fx = u1_fx; + u_e = u1_e; + } + ELSE + { + u_fx = u2_fx; + u_e = u2_e; + } + move32(); + move16(); + } + ELSE IF( ( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( abs_s( u1_fx ) ), u1_e, 1, 31 ) < 0 ) ) + { + u_fx = u1_fx; + u_e = u1_e; + move32(); + move16(); + } + ELSE IF( ( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( abs_s( u2_fx ) ), u2_e, 1, 31 ) < 0 ) ) + { + u_fx = u2_fx; + u_e = u2_e; + move32(); + move16(); + } + } + + IF( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( u_fx ), u_e, 0, 0 ) > 0 ) + { + u_fx = 0; + u_e = 0; + move32(); + move16(); + } + + IF( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( u_fx ), u_e, -1288490188, 0 ) < 0 ) // -0.6 in Q31 + { + u_fx = -1288490188 >> 16; //-0.6 in Q31 -> Q15 + u_e = 0; + move32(); + move16(); + } + + + /* Quantize spec. mapping **/ + Word16 specMapping16; + idx = usquant_fx( shr( u_fx, sub( 0, u_e ) ), &specMapping16, -19660, 6553, 1 << STEREO_ICBWE_SPBITS ); // -0.6 in in Q15 -> -19660, 0.2 in Q15 -> 6553 + *specMapping_fx = L_deposit_h( specMapping16 ); + move32(); + + /* IC-BWE spec mapping */ + deemph_fx_32( 0, shb_synth_nonref_fx, extract_h( *specMapping_fx ), L_FRAME16k, memShbSpecMapping_fx ); + + return idx; +} + +#endif + /*----------------------------------------------------------------------* * ic_bwe_gsMapping() @@ -177,6 +437,7 @@ static int16_t ic_bwe_enc_specMapping( *-----------------------------------------------------------------------*/ /*! r: return quant. index value */ +#ifndef IVAS_FLOAT_FIXED static int16_t ic_bwe_enc_gsMapping( const float relG_targ, /* i : gDes, rel gain target */ const float *shbSynth, /* i : ref synth signal */ @@ -224,14 +485,108 @@ static int16_t ic_bwe_enc_gsMapping( return idx; } +#endif +/*----------------------------------------------------------------------* + * ic_bwe_gsMapping() + * + * Encode and apply the gain shape mapping of ref to the non-ref channel + *-----------------------------------------------------------------------*/ + +/*! r: return quant. index value */ +static Word16 ic_bwe_enc_gsMapping_ivas_fx( + const Word32 relG_targ_fx, /* i : gDes, rel gain target */ + Word16 relG_targ_e, + const Word16 *shbSynth_fx, /* i : ref synth signal */ + Word16 shbSynth_e, /* i : ref synth signal */ + Word32 *synthSHB_nonref_fx, /* i : nonref synth signal */ + Word16 *synthSHB_nonref_e, /* i : nonref synth signal */ + Word32 *gsMapping_fx, /* i/o: gs mapping */ + Word16 *gsMapping_e, /* i/o: gs mapping */ + Word32 *memEner_fx, /* */ + Word16 *memEner_e, + const Word16 element_mode /* i : element mode */ +) +{ + Word16 i; + Word16 idx = 0, temp1; + move16(); + Word32 temp1_fx32 = 0, temp2_fx32 = 0; + move32(); + move32(); + Word32 L_mult; + Word16 temp2_fx, gsMapping_fx16; + + /* rel gain of synth signals */ + Word16 exp1 = shbSynth_e, exp2 = *synthSHB_nonref_e, temp1_exp = 0, temp2_exp = 0, exp = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + FOR( i = 0; i < L_FRAME16k; i++ ) + { + temp1_fx32 = BASOP_Util_Add_Mant32Exp( temp1_fx32, temp1_exp, L_abs( L_deposit_h( shbSynth_fx[i] ) ), exp1, &temp1_exp ); + temp2_fx32 = BASOP_Util_Add_Mant32Exp( temp2_fx32, temp2_exp, L_abs( synthSHB_nonref_fx[i] ), exp2, &temp2_exp ); + } + + + memEner_fx[0] = temp1_fx32; + memEner_fx[1] = L_shr( temp2_fx32, abs_s( sub( temp1_exp, temp2_exp ) ) ); + move32(); + move32(); + *memEner_e = s_max( temp1_exp, temp2_exp ); + move16(); + + + IF( temp2_fx32 == 0 ) + { + *gsMapping_fx = *gsMapping_fx; + move32(); + } + ELSE + { + L_mult = Mpy_32_32( relG_targ_fx, temp1_fx32 ); // relG_targ_e + temp1_e + temp1 = BASOP_Util_Divide3232_Scale( L_mult, temp1_fx32, &exp ); // exp = exp - ( relG_targ_e + temp1_e + temp2_e ) + exp = add( exp, sub( add( relG_targ_e, temp1_exp ), temp2_exp ) ); + *gsMapping_fx = L_deposit_h( temp1 ); // exp + move32(); + } + + temp2_fx32 = BASOP_Util_Log10( *gsMapping_fx, exp ); /* no impact from prev_gsMapping */ // Q25 + /* quantize the IC-BWE GS mapping*/ + IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + temp2_fx = extract_l( L_shr( temp2_fx32, Q10 ) ); // Q15 + gsMapping_fx16 = 0; + move16(); + idx = squant_fx( temp2_fx, &gsMapping_fx16, icbwe_gsMapping_tbl_fx, 1 << STEREO_ICBWE_GSBITS ); // Q12 + // idx = squant_fx( temp2, gsMapping, icbwe_gsMapping_tbl_fx, 1 << STEREO_ICBWE_GSBITS ); + } + ELSE + { + temp2_fx = extract_l( L_shr( temp2_fx32, Q10 ) ); // Q15 + gsMapping_fx16 = 0; + move16(); + idx = squant_fx( temp2_fx, &gsMapping_fx16, icbwe_gsMappingDFT_tbl_fx, 1 << STEREO_ICBWE_GSBITS ); // Q12 + } + *gsMapping_fx = L_deposit_h( gsMapping_fx16 ); // Q28 + move32(); + Word16 e; + L_mult = Mult_32_16( *gsMapping_fx, 27213 /*=log2(10)*2^13*/ ); // Q27 + Q13 - Q15 -> Q26 + *gsMapping_fx = BASOP_util_Pow2( L_mult, 5, &e ); + move32(); + *gsMapping_e = e; // Q31 + move16(); + return idx; +} /*----------------------------------------------------------------------* * icbwe_dft_stereo_param() * * Estimate ICBWE parameters in DFT stereo *-----------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void icbwe_dft_stereo_param( STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: */ STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : */ @@ -325,57 +680,218 @@ static void icbwe_dft_stereo_param( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +static void icbwe_dft_stereo_param_ivas_fx( + STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : */ + Encoder_State *st, /* i/o: */ + Word32 *shb_synth_nonref_fx, /* i/o: */ + Word16 shb_synth_nonref_e /* i/o: */ +) +{ + Word16 slopeILD_fx; + Word32 normFac_fx; + Word16 gsIndx, spIndx, gDes_fx; + Word32 *nrg_L_fx, *nrg_R_fx, *nrg_DMX_fx; + Word32 sum_nrg_L_fx, sum_nrg_R_fx, sum_nrg_DMX_fx; + const Word32 spec_table_fx[4] = { -1288490189, -858993459, -429496730, 0 }; // Q31 + const Word16 slope_table_fx16[4] = { -17788, -10577, -4822, 0 }; // Q13 -/*-------------------------------------------------------------------* - * stereo_icBWE_enc() - * - * Encode the spatial mapping of reference to the non-reference channels in HB - *-------------------------------------------------------------------*/ + BSTR_ENC_HANDLE hBstr = st->hBstr; + normFac_fx = 1342177280; /* 1000 * (10/((14400+10400)/2 - (6400+10400)/2)) */ // Q29 + move32(); -void stereo_icBWE_enc( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const float shb_speech_ref[], /* i : SHB speech ref channel */ - float shb_speech_nonref[], /* i/o: SHB speech non-ref channel */ - const float *voice_factors /* i : voicing factors */ -) -{ - int16_t i, j, k, nbSubFr; - STEREO_DFT_ENC_DATA_HANDLE hStereoDft; - STEREO_ICBWE_ENC_HANDLE hStereoICBWE; - BSTR_ENC_HANDLE hBstr; - Encoder_State *st; - int16_t spIndx, gsIndx; - float shb_frame_ref[L_LOOK_16k + L_FRAME16k]; - float excSHB_nonref[L_FRAME16k]; - float shb_frame_nonref[L_LOOK_16k + L_FRAME16k]; - float shb_synth_nonref[L_FRAME16k]; + nrg_L_fx = hStereoDft->nrg_L_fx; + nrg_R_fx = hStereoDft->nrg_R_fx; + nrg_DMX_fx = hStereoDft->nrg_DMX_fx; - float nlMixFac[NB_SUBFR16k]; - float temp1, temp2; - float gDes, gTarget; - int16_t nonRefMemLen, refMemLen; - /* initialization */ - hStereoDft = hCPE->hStereoDft; - hStereoICBWE = hCPE->hStereoICBWE; - st = hCPE->hCoreCoder[0]; - hBstr = st->hBstr; + hStereoICBWE->mem_nrg_L_fx[0] = nrg_L_fx[0]; // hStereoICBWE->nrg_L_fx_e[0] + hStereoICBWE->mem_nrg_R_fx[0] = nrg_R_fx[0]; // hStereoICBWE->nrg_R_fx_e[0] + hStereoICBWE->mem_nrg_DMX_fx[0] = nrg_DMX_fx[0]; // hStereoICBWE->nrg_DMX_fx_e[0] + hStereoICBWE->mem_nrg_L_fx[1] = L_shr( nrg_L_fx[1], abs_s( sub( hStereoDft->nrg_L_fx_e[0], hStereoDft->nrg_L_fx_e[1] ) ) ); // hStereoICBWE->nrg_L_fx_e[1] + hStereoICBWE->mem_nrg_R_fx[1] = L_shr( nrg_R_fx[1], abs_s( sub( hStereoDft->nrg_R_fx_e[0], hStereoDft->nrg_R_fx_e[1] ) ) ); // hStereoICBWE-> nrg_R_fx_e[1] + hStereoICBWE->mem_nrg_DMX_fx[1] = L_shr( nrg_DMX_fx[1], abs_s( sub( hStereoDft->nrg_DMX_fx_e[0], hStereoDft->nrg_DMX_fx_e[1] ) ) ); // hStereoICBWE->nrg_DMX_fx_e[1] + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + hStereoICBWE->mem_nrg_L_fx_e = s_max( hStereoDft->nrg_L_fx_e[0], hStereoDft->nrg_L_fx_e[1] ); + hStereoICBWE->mem_nrg_R_fx_e = s_max( hStereoDft->nrg_R_fx_e[0], hStereoDft->nrg_R_fx_e[1] ); + hStereoICBWE->mem_nrg_DMX_fx_e = s_max( hStereoDft->nrg_DMX_fx_e[0], hStereoDft->nrg_DMX_fx_e[1] ); + move16(); + move16(); + move16(); - gTarget = hCPE->hStereoTCA->targetGain; /* i : gain norm for target (or R) channel */ + Word16 sum_nrg_L_e = hStereoICBWE->mem_nrg_L_fx_e, sum_nrg_R_e = hStereoICBWE->mem_nrg_R_fx_e, sum_nrg_DMX_e = hStereoICBWE->mem_nrg_DMX_fx_e; + sum_nrg_L_fx = sum_32_fx( hStereoICBWE->mem_nrg_L_fx, 2, &sum_nrg_L_e ); // hStereoICBWE->mem_nrg_L_fx_e + sum_nrg_R_fx = sum_32_fx( hStereoICBWE->mem_nrg_R_fx, 2, &sum_nrg_R_e ); // hStereoICBWE->mem_nrg_R_fx_e + sum_nrg_DMX_fx = sum_32_fx( hStereoICBWE->mem_nrg_DMX_fx, 2, &sum_nrg_DMX_e ); // hStereoICBWE->mem_nrg_DMX_fx_e - nonRefMemLen = L_MEM_RECALC_TBE_16K + L_FILT16k; + /* refChanIndex_bwe refinement */ - if ( st->element_mode == IVAS_CPE_TD ) + test(); + test(); + test(); + test(); + IF( ( ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_R_fx, sum_nrg_R_e, Mpy_32_32( 1374389534, sum_nrg_L_fx ), sum_nrg_L_e ) < 0 ) && EQ_16( hStereoICBWE->refChanIndx_bwe, hStereoICBWE->prev_refChanIndx_bwe ) ) || ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_R_fx, sum_nrg_R_e, Mpy_32_32( 773094113, sum_nrg_L_fx ), sum_nrg_L_e ) < 0 ) ) // 0.64 in Q31 -> 1374389534, 0.36 in Q31 -> 773094113 { - refMemLen = L_MEM_RECALC_TBE_16K + 20; + hStereoICBWE->refChanIndx_bwe = L_CH_INDX; + move16(); } - else if ( st->element_mode == IVAS_CPE_DFT && st->core_brate > SID_2k40 ) + ELSE IF( ( ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_L_fx, sum_nrg_L_e, Mpy_32_32( 1374389534, sum_nrg_R_fx ), sum_nrg_R_e ) < 0 ) && EQ_16( hStereoICBWE->refChanIndx_bwe, hStereoICBWE->prev_refChanIndx_bwe ) ) || ( BASOP_Util_Cmp_Mant32Exp( sum_nrg_L_fx, sum_nrg_L_e, Mpy_32_32( 773094113, sum_nrg_R_fx ), sum_nrg_R_e ) < 0 ) ) // 0.64 in Q31 -> 1374389534, 0.36 in Q31 -> 773094113 { - refMemLen = 20; + hStereoICBWE->refChanIndx_bwe = R_CH_INDX; + move16(); } - else - { + + /* Initialization of spIndx */ + slopeILD_fx = 0; + move32(); + + spIndx = squant_fx( slopeILD_fx, &slopeILD_fx, slope_table_fx16, 1 << STEREO_ICBWE_SPBITS_DFT ); + + test(); + test(); + test(); + IF( ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, WB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && EQ_16( st->flag_ACELP16k, 1 ) ) + { + /* Spec Mapping Estimate */ + Word16 tmp1, exp1; + Word32 L_tmp, L_tmp1; + L_tmp = Mpy_32_32( hStereoICBWE->mem_nrg_L_fx[1], hStereoICBWE->mem_nrg_R_fx[0] ); // hStereoICBWE->mem_nrg_L_fx_e[1] + hStereoICBWE->mem_nrg_R_fx_e[1] + L_tmp1 = Mpy_32_32( hStereoICBWE->mem_nrg_R_fx[1], hStereoICBWE->mem_nrg_L_fx[0] ); // hStereoICBWE->mem_nrg_L_fx_e[1] + hStereoICBWE->mem_nrg_R_fx_e[1] + tmp1 = BASOP_Util_Divide3232_Scale( L_tmp, L_tmp1, &exp1 ); + exp1 = add( exp1, sub( add( hStereoICBWE->mem_nrg_L_fx_e, hStereoICBWE->mem_nrg_R_fx_e ), add( hStereoICBWE->mem_nrg_L_fx_e, hStereoICBWE->mem_nrg_R_fx_e ) ) ); + L_tmp = BASOP_Util_Log10( L_deposit_h( tmp1 ), exp1 ); + L_tmp = Mpy_32_32( normFac_fx, L_tmp ); // // Q25 + Q29 - Q31 -> Q23 + slopeILD_fx = extract_l( L_shr( L_tmp, 16 ) ); // Q23 - Q16 -> Q7 + IF( hStereoICBWE->refChanIndx_bwe == L_CH_INDX ) + { + slopeILD_fx = negate( slopeILD_fx ); + } + ELSE + { + slopeILD_fx = slopeILD_fx; + move16(); + } + spIndx = squant_fx( slopeILD_fx, &slopeILD_fx, slope_table_fx16, 1 << STEREO_ICBWE_SPBITS_DFT ); + IF( Mpy_32_32( spec_table_fx[spIndx], hStereoICBWE->prevSpecMapping_fx ) < 0 ) + { + slopeILD_fx = 0; + move32(); + spIndx = squant_fx( slopeILD_fx, &slopeILD_fx, slope_table_fx16, 1 << STEREO_ICBWE_SPBITS_DFT ); + } + + hStereoICBWE->prevSpecMapping_fx = spec_table_fx[spIndx]; // q31 + /* ic bwe spec mapping application */ + deemph_fx_32( 0, shb_synth_nonref_fx, extract_l( L_shr( hStereoICBWE->prevSpecMapping_fx, 16 ) ), L_FRAME16k, &hStereoICBWE->memShbSpecMapping_fx ); // shb_synth_nonref_e + } + ELSE + { + hStereoICBWE->memShbSpecMapping_fx = 0; + hStereoICBWE->prevSpecMapping_fx = 0; + move32(); + move32(); + } + + /* gsMapping estimate */ + + Word16 exp; + IF( hStereoICBWE->refChanIndx_bwe == L_CH_INDX ) + { + gDes_fx = BASOP_Util_Divide3232_Scale( sum_nrg_R_fx, sum_nrg_DMX_fx, &exp ); + exp = add( exp, sub( sum_nrg_R_e, sum_nrg_DMX_e ) ); + } + ELSE + { + gDes_fx = BASOP_Util_Divide3232_Scale( sum_nrg_L_fx, sum_nrg_DMX_fx, &exp ); + exp = add( exp, sub( sum_nrg_L_e, sum_nrg_DMX_e ) ); + } + + gDes_fx = Sqrt16( gDes_fx, &exp ); + Word16 exp1 = hStereoICBWE->gDes_pastFrame_e, exp2, tmp; + Word32 tmp321 = 0, tmp322 = 0; + move32(); + move32(); + /* Geometric Mean */ + tmp321 = Sqrt32( hStereoICBWE->gDes_pastFrame_fx, &exp1 ); // exp1 + exp2 = exp; + move16(); + tmp = Sqrt16( gDes_fx, &exp2 ); + tmp322 = Mpy_32_32( tmp321, L_deposit_h( tmp ) ); // exp1 + exp2 + hStereoICBWE->gDes_pastFrame_fx = tmp322; + hStereoICBWE->gDes_pastFrame_e = add( exp1, exp2 ); + move32(); + move16(); + + gsIndx = ic_bwe_enc_gsMapping_ivas_fx( hStereoICBWE->gDes_pastFrame_fx, hStereoICBWE->gDes_pastFrame_e, hStereoICBWE->shbSynthRef_fx, hStereoICBWE->shbSynthRef_e, shb_synth_nonref_fx, &shb_synth_nonref_e, &( hStereoICBWE->prevgsMapping_fx ), &( hStereoICBWE->prevgsMapping_e ), hStereoICBWE->memGsEnerMap_fx, &hStereoICBWE->memGsEnerMap_e, st->element_mode ); + + hStereoICBWE->gDes_pastFrame_fx = L_deposit_h( gDes_fx ); + hStereoICBWE->gDes_pastFrame_e = exp; + move32(); + move16(); + + push_indice( hBstr, IND_STEREO_ICBWE_REF, hStereoICBWE->refChanIndx_bwe, STEREO_ICBWE_REFBITS ); + IF( EQ_16( st->flag_ACELP16k, 1 ) ) + { + push_indice( hBstr, IND_STEREO_ICBWE_SP, spIndx, STEREO_ICBWE_SPBITS_DFT ); + } + + /* IC BWE GS mapping */ + push_indice( hBstr, IND_STEREO_ICBWE_GS, gsIndx, STEREO_ICBWE_GSBITS_DFT ); + + return; +} +#endif +#ifndef IVAS_FLOAT_FIXED +void stereo_icBWE_enc( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const float shb_speech_ref[], /* i : SHB speech ref channel */ + float shb_speech_nonref[], /* i/o: SHB speech non-ref channel */ + const float *voice_factors /* i : voicing factors */ +) +{ + int16_t i, j, k, nbSubFr; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + STEREO_ICBWE_ENC_HANDLE hStereoICBWE; + BSTR_ENC_HANDLE hBstr; + Encoder_State *st; + int16_t spIndx, gsIndx; + float shb_frame_ref[L_LOOK_16k + L_FRAME16k]; + float excSHB_nonref[L_FRAME16k]; + float shb_frame_nonref[L_LOOK_16k + L_FRAME16k]; + float shb_synth_nonref[L_FRAME16k]; + + float nlMixFac[NB_SUBFR16k]; + float temp1, temp2; + float gDes, gTarget; + int16_t nonRefMemLen, refMemLen; + + /* initialization */ + hStereoDft = hCPE->hStereoDft; + hStereoICBWE = hCPE->hStereoICBWE; + st = hCPE->hCoreCoder[0]; + hBstr = st->hBstr; + + gTarget = hCPE->hStereoTCA->targetGain; /* i : gain norm for target (or R) channel */ + + nonRefMemLen = L_MEM_RECALC_TBE_16K + L_FILT16k; + + if ( st->element_mode == IVAS_CPE_TD ) + { + refMemLen = L_MEM_RECALC_TBE_16K + 20; + } + else if ( st->element_mode == IVAS_CPE_DFT && st->core_brate > SID_2k40 ) + { + refMemLen = 20; + } + else + { ic_bwe_enc_reset( hStereoICBWE ); return; @@ -569,6 +1085,480 @@ void stereo_icBWE_enc( return; } +#endif + +void stereo_icBWE_enc_ivas_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word32 shb_speech_ref_fx[], /* i : SHB speech ref channel */ + const Word16 shb_speech_ref_e, /* i : SHB speech ref channel */ + Word32 shb_speech_nonref_fx[], /* i/o: SHB speech non-ref channel */ + Word16 shb_speech_nonref_e, /* i/o: SHB speech non-ref channel */ + const Word32 *voice_factors_fx /* i : voicing factors Q31 */ +) +{ + Word16 i, j, k, nbSubFr; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + STEREO_ICBWE_ENC_HANDLE hStereoICBWE; + BSTR_ENC_HANDLE hBstr; + Encoder_State *st; + Word16 spIndx, gsIndx; + + Word16 nonRefMemLen, refMemLen; + Word16 shb_synth_nonref_e = 0, max_e; + move16(); + + Word32 nlMixFac_fx[NB_SUBFR16k]; + Word32 excSHB_nonref_fx[L_FRAME16k]; + set32_fx( excSHB_nonref_fx, 0, L_FRAME16k ); + Word32 shb_synth_nonref_fx[L_FRAME16k]; + Word32 shb_frame_nonref_fx[L_LOOK_16k + L_FRAME16k], gTarget_fx; + Word32 shb_frame_ref_fx[L_LOOK_16k + L_FRAME16k]; + Word32 gDes_fx; + Word32 temp1_fx, temp2_fx; + Word16 temp1_e, temp2_e, shb_frame_ref_e, shb_frame_nonref_e, gDes_e, tmp, exp; + + + /* initialization */ + hStereoDft = hCPE->hStereoDft; + hStereoICBWE = hCPE->hStereoICBWE; + st = hCPE->hCoreCoder[0]; + hBstr = st->hBstr; + + gTarget_fx = hCPE->hStereoTCA->targetGain_fx; /* i : gain norm for target (or R) channel */ // Q29 + move32(); + + nonRefMemLen = L_MEM_RECALC_TBE_16K + L_FILT16k; + move16(); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + refMemLen = L_MEM_RECALC_TBE_16K + 20; + move16(); + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && GT_32( st->core_brate, SID_2k40 ) ) + { + refMemLen = 20; + move16(); + } + ELSE + { + ic_bwe_enc_reset_fx( hStereoICBWE ); + return; + } + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + /* memory resets */ + set16_fx( hStereoICBWE->mem_shb_speech_nonref_fx, 0, L_LOOK_16k ); + set32_fx( shb_speech_nonref_fx, 0, L_FRAME16k ); + + /* core switching reset */ + test(); + test(); + test(); + IF( st->last_core != ACELP_CORE || st->core != ACELP_CORE || LT_16( st->bwidth, SWB ) || EQ_16( st->extl, -1 ) ) + { + + ic_bwe_enc_reset_fx( hStereoICBWE ); + test(); + test(); + test(); + IF( st->core != ACELP_CORE || LT_16( st->bwidth, SWB ) || LT_32( st->input_Fs, 32000 ) || EQ_16( st->extl, -1 ) ) + { + return; + } + } + + set32_fx( hStereoICBWE->memShbSpecXcorr_fx, 0, 6 ); + + hStereoICBWE->prevRefEner_fx = 0; + hStereoICBWE->prevNonRefEner_fx = 0; + move32(); + move32(); + + /* SHB frame buffer offsets for TBE processing << re-adjust check >>*/ + + max_e = s_max( hStereoICBWE->mem_shb_speech_ref_e, shb_speech_ref_e ); + Copy_Scale_sig( hStereoICBWE->mem_shb_speech_ref_fx, hStereoICBWE->mem_shb_speech_ref_fx, L_LOOK_16k, negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ) ); // mem_shb_speech_ref_e + + set32_fx( shb_frame_ref_fx, 0, L_LOOK_16k + L_FRAME16k ); + Copy_Scale_sig_16_32( hStereoICBWE->mem_shb_speech_ref_fx, shb_frame_ref_fx, L_LOOK_16k, negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ) + Q16 ); // mem_shb_speech_ref_e + + hStereoICBWE->mem_shb_speech_ref_e = max_e; + shb_frame_ref_e = max_e; + move16(); + move16(); + /* shb_frame_ref_ICBWE @ (8.75 - shb_speech_delay (=1.25) ms) after shb_speech */ + + shb_synth_nonref_e = max_e; + move16(); + + Copy_Scale_sig32( shb_speech_ref_fx, shb_frame_ref_fx + L_LOOK_16k - refMemLen, L_FRAME16k, negate( sub( max_e, shb_speech_ref_e ) ) ); + Copy_Scale_sig_32_16( shb_frame_ref_fx + L_FRAME16k, hStereoICBWE->mem_shb_speech_ref_fx, L_LOOK_16k, negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ) - Q16 ); // mem_shb_speech_ref_e + + test(); + test(); + IF( ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && EQ_16( st->flag_ACELP16k, 1 ) ) + { + Copy32( voice_factors_fx, nlMixFac_fx, NB_SUBFR16k ); // Q31 + /*if( gDes < 0.5f || gDes > 2.0f )*/ + test(); + IF( LT_32( gTarget_fx, 268435456 ) || GT_32( gTarget_fx, 1073741824 ) ) // 0.5 in Q29 or 2.0 in Q29 + { + v_multc_fixed( voice_factors_fx, 1073741824, nlMixFac_fx, NB_SUBFR16k ); // Q31, 0.5 in Q31 -> 1073741824 + } + + IF( st->flag_ACELP16k == 0 ) + { + nbSubFr = NB_SUBFR; + move16(); + } + ELSE + { + nbSubFr = NB_SUBFR16k; + move16(); + } + + Word16 exp_buf[L_FRAME16k]; + set16_fx( exp_buf, 0, L_FRAME16k ); + FOR( ( i = 0, k = 0 ); i < nbSubFr; i++ ) + { + test(); + IF( EQ_16( st->coder_type, UNVOICED ) || EQ_16( hStereoICBWE->MSFlag, 1 ) ) + { + temp1_fx = 0; + temp1_e = 0; + temp2_fx = ONE_IN_Q31; + temp2_e = 0; + move16(); + move32(); + move16(); + move32(); + } + ELSE + { + temp1_e = 0, temp2_e = 0; + move16(); + move32(); + temp1_fx = Sqrt32( nlMixFac_fx[i], &temp1_e ); + temp2_fx = Sqrt32( L_sub( ONE_IN_Q31, nlMixFac_fx[i] ), &temp2_e ); + } + + tmp = BASOP_Util_Divide1616_Scale( L_FRAME16k, nbSubFr, &exp ); + tmp = shr( tmp, sub( Q15, exp ) ); + FOR( j = 0; j < tmp; ( j++, k++ ) ) + { + excSHB_nonref_fx[k] = extract_l( BASOP_Util_Add_Mant32Exp( Mpy_32_32( temp1_fx, hStereoICBWE->nlExc16k_fx[k] ), add( temp1_e, hStereoICBWE->nlExc16k_e ), Mpy_32_32( temp2_fx, hStereoICBWE->mixExc16k_fx[k] ), add( temp2_e, hStereoICBWE->mixExc16k_e ), &exp_buf[k] ) ); + move32(); + } + } + + max_e = exp_buf[0]; + move16(); + FOR( j = 0; j < L_FRAME16k; j++ ) + { + IF( GT_16( exp_buf[j], max_e ) ) + { + max_e = exp_buf[j]; + move16(); + } + } + + FOR( j = 0; j < L_FRAME16k; j++ ) + { + excSHB_nonref_fx[j] = L_shr( excSHB_nonref_fx[j], sub( max_e, exp_buf[j] ) ); + move32(); + } + /* LP synthesis */ + Word16 tmp_e = s_max( hCPE->hStereoICBWE->lpSHBRef_e, max_e ); + + Word32 lpSHBRef_fx32[LPC_SHB_ORDER + 1]; + + Copy_Scale_sig32( hCPE->hStereoICBWE->lpSHBRef_fx, lpSHBRef_fx32, LPC_SHB_ORDER + 1, negate( sub( tmp_e, hCPE->hStereoICBWE->lpSHBRef_e ) ) ); + Copy_Scale_sig32( excSHB_nonref_fx, excSHB_nonref_fx, L_FRAME16k, negate( sub( tmp_e, max_e ) ) ); + // set32_fx( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 0, LPC_SHB_ORDER ); + E_UTIL_synthesis_fx( 0, lpSHBRef_fx32, excSHB_nonref_fx, shb_synth_nonref_fx, L_FRAME16k, hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 1, LPC_SHB_ORDER ); + + shb_synth_nonref_e = tmp_e; + hStereoICBWE->mem_lpc_shbsynth_nonref_e = tmp_e; + move16(); + move16(); + } + ELSE + { + Copy_Scale_sig_32_16( shb_frame_ref_fx, hStereoICBWE->shbSynthRef_fx, L_FRAME16k, -16 ); // max_e + hStereoICBWE->shbSynthRef_e = shb_frame_ref_e; + move16(); + Copy32( shb_frame_ref_fx, shb_synth_nonref_fx, L_FRAME16k ); // max_e + shb_synth_nonref_e = shb_frame_ref_e; + move16(); + set32_fx( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 0, 10 ); + } + + icbwe_dft_stereo_param_ivas_fx( hStereoICBWE, hStereoDft, st, shb_synth_nonref_fx, shb_synth_nonref_e ); + hStereoICBWE->memShbSpecMapping_e = shb_synth_nonref_e; + move16(); + } + ELSE + { + + max_e = s_max( hStereoICBWE->mem_shb_speech_nonref_e, shb_speech_nonref_e ); + Copy_Scale_sig( hStereoICBWE->mem_shb_speech_ref_fx, hStereoICBWE->mem_shb_speech_ref_fx, L_LOOK_16k, negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ) ); // mem_shb_speech_ref_e + + set32_fx( shb_frame_ref_fx, 0, L_LOOK_16k + L_FRAME16k ); + Copy_Scale_sig_16_32( hStereoICBWE->mem_shb_speech_ref_fx, shb_frame_ref_fx, L_LOOK_16k, add( negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ), Q16 ) ); // mem_shb_speech_ref_e + + hStereoICBWE->mem_shb_speech_ref_e = max_e; + shb_frame_ref_e = max_e; + move16(); + move16(); + /* shb_frame_ref_ICBWE @ (8.75 - shb_speech_delay (=1.25) ms) after shb_speech */ + + Copy_Scale_sig32( shb_speech_ref_fx, shb_frame_ref_fx + L_LOOK_16k - refMemLen, L_FRAME16k, negate( sub( max_e, shb_speech_ref_e ) ) ); + Copy_Scale_sig_32_16( shb_frame_ref_fx + L_FRAME16k, hStereoICBWE->mem_shb_speech_ref_fx, L_LOOK_16k, sub( negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ), Q16 ) ); // mem_shb_speech_ref_e + + set32_fx( shb_frame_nonref_fx, 0, L_LOOK_16k + L_FRAME16k ); + + max_e = s_max( hStereoICBWE->mem_shb_speech_nonref_e, shb_speech_nonref_e ); + Copy_Scale_sig( hStereoICBWE->mem_shb_speech_nonref_fx, hStereoICBWE->mem_shb_speech_nonref_fx, L_LOOK_16k, negate( sub( max_e, hStereoICBWE->mem_shb_speech_nonref_e ) ) ); // mem_shb_speech_ref_e + + Copy_Scale_sig_16_32( hStereoICBWE->mem_shb_speech_nonref_fx, shb_frame_nonref_fx, L_LOOK_16k, add( negate( sub( max_e, hStereoICBWE->mem_shb_speech_nonref_e ) ), Q16 ) ); // mem_shb_speech_ref_e + + hStereoICBWE->mem_shb_speech_nonref_e = max_e; + shb_frame_nonref_e = max_e; + move16(); + move16(); + /* shb_frame_ref_ICBWE @ (8.75 - shb_speech_delay (=1.25) ms) after shb_speech */ + + Copy_Scale_sig32( shb_speech_nonref_fx, shb_frame_nonref_fx + L_LOOK_16k - nonRefMemLen, L_FRAME16k, negate( sub( max_e, shb_speech_nonref_e ) ) ); + Copy_Scale_sig_32_16( shb_frame_nonref_fx + L_FRAME16k, hStereoICBWE->mem_shb_speech_nonref_fx, L_LOOK_16k, sub( negate( sub( max_e, hStereoICBWE->mem_shb_speech_ref_e ) ), Q16 ) ); // mem_shb_speech_ref_e + + + /* core switching reset */ + test(); + test(); + test(); + test(); + IF( st->last_core != ACELP_CORE || st->core != ACELP_CORE || LT_16( st->bwidth, SWB ) || NE_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->extl, -1 ) ) + { + ic_bwe_enc_reset_fx( hStereoICBWE ); + test(); + test(); + test(); + test(); + IF( st->core != ACELP_CORE || LT_16( st->bwidth, SWB ) || LT_32( st->input_Fs, 32000 ) || NE_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->extl, -1 ) ) + { + return; + } + } + + /* resets done here. Need to move them to a separate function */ + test(); + test(); + IF( ( NE_16( hStereoICBWE->prev_refChanIndx_bwe, hStereoICBWE->refChanIndx_bwe ) ) || NE_16( st->last_extl, st->extl ) || NE_16( st->flag_ACELP16k, 1 ) ) + { + hStereoICBWE->prevSpecMapping_fx = 0; + hStereoICBWE->memShbSpecMapping_fx = 0; + move32(); + move32(); + set32_fx( hStereoICBWE->memShbSpecXcorr_fx, 0, 6 ); + } + + /* voice fac adjustment based on IC intensities */ + /*temp2 = (float)sqrt(sum2_f(shb_frame_ref + L_LOOK_16k - refMemLen, L_FRAME16k));*/ + + Word32 L_tmp, L_tmp1; + temp2_fx = hStereoICBWE->icbweRefEner_fx; + temp2_e = hStereoICBWE->icbweRefEner_e; + temp1_e = shb_frame_nonref_e; + move16(); + move32(); + move32(); + L_tmp = sum2_32_fx( shb_frame_nonref_fx + sub( L_LOOK_16k, refMemLen ), L_FRAME16k, &temp1_e ); + temp1_fx = Sqrt32( L_tmp, &temp1_e ); + + /*temp1 = 0.8f*hStereoICBWE->prevNonRefEner + 0.2f*temp1;*/ + /*temp2 = 0.8f*hStereoICBWE->prevRefEner + 0.2f*temp2;*/ + + IF( temp2_fx == 0 ) + { + gDes_fx = 1073741824; + gDes_e = 1; + move16(); + move32(); + } + ELSE + { + tmp = BASOP_Util_Divide3232_Scale( temp1_fx, temp2_fx, &exp ); + gDes_fx = L_deposit_h( tmp ); // exp + gDes_e = exp; + move16(); + } + tmp = gDes_e; + exp = hStereoICBWE->gDes_pastFrame_e; + move16(); + move16(); + L_tmp = Sqrt32( gDes_fx, &tmp ); + L_tmp1 = Sqrt32( hStereoICBWE->gDes_pastFrame_fx, &exp ); + + hStereoICBWE->gDes_pastFrame_fx = Mpy_32_32( L_tmp, L_tmp1 ); // tmp + exp + hStereoICBWE->gDes_pastFrame_e = add( tmp, exp ); + move32(); + move16(); + + hStereoICBWE->prevRefEner_fx = temp2_fx; + hStereoICBWE->prevRefEner_e = temp2_e; + hStereoICBWE->prevNonRefEner_fx = temp1_fx; + hStereoICBWE->prevNonRefEner_e = temp1_e; + move32(); + move32(); + move16(); + move16(); + + test(); + test(); + IF( ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && EQ_16( st->flag_ACELP16k, 1 ) ) + { + Copy32( voice_factors_fx, nlMixFac_fx, NB_SUBFR16k ); // Q31 + + test(); + IF( LT_32( gTarget_fx, 268435456 ) || GT_32( gTarget_fx, 1073741824 ) ) // + { + v_multc_fixed( voice_factors_fx, 1073741824, nlMixFac_fx, NB_SUBFR16k ); + } + + IF( st->flag_ACELP16k == 0 ) + { + nbSubFr = NB_SUBFR; + move16(); + } + ELSE + { + nbSubFr = NB_SUBFR16k; + move16(); + } + + Word16 exp_buf[L_FRAME16k]; + set16_fx( exp_buf, 0, L_FRAME16k ); + FOR( ( i = 0, k = 0 ); i < nbSubFr; i++ ) + { + test(); + IF( EQ_16( st->coder_type, UNVOICED ) || EQ_16( hStereoICBWE->MSFlag, 1 ) ) + { + + temp1_fx = 0; + temp1_e = 0; + temp2_fx = ONE_IN_Q31; + temp2_e = 0; + move32(); + move32(); + move16(); + move16(); + } + ELSE + { + temp1_e = 0, temp2_e = 0; + temp1_fx = Sqrt32( nlMixFac_fx[i], &temp1_e ); + temp2_fx = Sqrt32( L_sub( ONE_IN_Q31, nlMixFac_fx[i] ), &temp2_e ); + move32(); + move16(); + } + + FOR( j = 0; j < ( L_FRAME16k / nbSubFr ); ( j++, k++ ) ) + { + excSHB_nonref_fx[k] = extract_l( BASOP_Util_Add_Mant32Exp( Mpy_32_32( temp1_fx, hStereoICBWE->nlExc16k_fx[k] ), temp1_e + hStereoICBWE->nlExc16k_e, Mpy_32_32( temp2_fx, hStereoICBWE->mixExc16k_fx[k] ), temp2_e + hStereoICBWE->mixExc16k_e, &exp_buf[k] ) ); + move32(); + } + } + + max_e = exp_buf[0]; + move16(); + FOR( j = 0; j < L_FRAME16k; j++ ) + { + IF( GT_16( exp_buf[j], max_e ) ) + { + max_e = exp_buf[j]; + move16(); + } + } + + FOR( j = 0; j < L_FRAME16k; j++ ) + { + excSHB_nonref_fx[j] = L_shr( excSHB_nonref_fx[j], sub( max_e, exp_buf[j] ) ); + move32(); + } + /* LP synthesis */ + + Word16 tmp_e = s_max( hCPE->hStereoICBWE->lpSHBRef_e, max_e ); + + Word32 lpSHBRef_fx32[LPC_SHB_ORDER + 1]; + + Copy_Scale_sig32( hCPE->hStereoICBWE->lpSHBRef_fx, lpSHBRef_fx32, LPC_SHB_ORDER + 1, negate( sub( tmp_e, hCPE->hStereoICBWE->lpSHBRef_e ) ) ); + Copy_Scale_sig32( excSHB_nonref_fx, excSHB_nonref_fx, L_FRAME16k, negate( sub( tmp_e, max_e ) ) ); + + E_UTIL_synthesis_fx( 0, hStereoICBWE->lpSHBRef_fx, excSHB_nonref_fx, shb_synth_nonref_fx, L_FRAME16k, hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 1, LPC_SHB_ORDER ); + shb_synth_nonref_e = sub( 31, tmp_e ); + hStereoICBWE->mem_lpc_shbsynth_nonref_e = shb_synth_nonref_e; + move16(); + } + ELSE + { + Copy_Scale_sig_32_16( shb_frame_ref_fx, hStereoICBWE->shbSynthRef_fx, L_FRAME16k, -16 ); // max_e + hStereoICBWE->shbSynthRef_e = shb_frame_ref_e; + move16(); + Copy32( shb_frame_ref_fx, shb_synth_nonref_fx, L_FRAME16k ); + shb_synth_nonref_e = shb_frame_ref_e; + move16(); + set32_fx( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 0, 10 ); + } + + test(); + test(); + test(); + IF( ( EQ_16( st->extl, SWB_TBE ) || EQ_16( st->extl, WB_TBE ) || EQ_16( st->extl, FB_TBE ) ) && EQ_16( st->flag_ACELP16k, 1 ) ) + { + /* IC BWE spectral mapping */ + spIndx = ic_bwe_enc_specMapping_ivas_fx( shb_frame_nonref_fx, shb_frame_nonref_e, shb_synth_nonref_fx, shb_synth_nonref_e, &( hStereoICBWE->prevSpecMapping_fx ), &( hStereoICBWE->memShbSpecMapping_fx ), hStereoICBWE->memShbSpecXcorr_fx, &( hStereoICBWE->memShbSpecXcorr_e ) ); + } + ELSE + { + spIndx = 3; + hStereoICBWE->prevSpecMapping_fx = 0; + move16(); + move32(); + } + + push_indice( hBstr, IND_STEREO_ICBWE_REF, hStereoICBWE->refChanIndx_bwe, STEREO_ICBWE_REFBITS ); + + IF( EQ_16( st->flag_ACELP16k, 1 ) ) + { + push_indice( hBstr, IND_STEREO_ICBWE_SP, spIndx, STEREO_ICBWE_SPBITS ); + } + ELSE + { + hStereoICBWE->prevSpecMapping_fx = -1288490188; // -0.6 in Q31 + move32(); + } + + /* IC BWE GS mapping */ + + gsIndx = ic_bwe_enc_gsMapping_ivas_fx( hStereoICBWE->gDes_pastFrame_fx, hStereoICBWE->gDes_pastFrame_e, hStereoICBWE->shbSynthRef_fx, hStereoICBWE->shbSynthRef_e, shb_synth_nonref_fx, &shb_synth_nonref_e, &( hStereoICBWE->prevgsMapping_fx ), &( hStereoICBWE->prevgsMapping_e ), hStereoICBWE->memGsEnerMap_fx, &hStereoICBWE->memGsEnerMap_e, st->element_mode ); + + hStereoICBWE->gDes_pastFrame_fx = gDes_fx; + hStereoICBWE->gDes_pastFrame_e = gDes_e; + move32(); + move16(); + push_indice( hBstr, IND_STEREO_ICBWE_GS, gsIndx, STEREO_ICBWE_GSBITS ); + } + + /* IC-BWE updates */ + hStereoICBWE->prev_refChanIndx_bwe = hStereoICBWE->refChanIndx_bwe; + move16(); + + return; +} + /*-------------------------------------------------------------------* * stereo_icBWE_init_enc() @@ -618,15 +1608,15 @@ void stereo_icBWE_init_enc( set_f( hStereoICBWE->icbwe_inp_mem[0], 0, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); set_f( hStereoICBWE->icbwe_inp_mem[1], 0, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); #endif - +#ifndef IVAS_FLOAT_FIXED set_f( hStereoICBWE->mem_nrg_L, 0, 2 ); set_f( hStereoICBWE->mem_nrg_R, 0, 2 ); set_f( hStereoICBWE->mem_nrg_DMX, 0, 2 ); +#endif hStereoICBWE->gDes_pastFrame = 1.0f; hStereoICBWE->icbweRefEner = 0.0f; hStereoICBWE->MSFlag = 0; - return; } @@ -638,10 +1628,10 @@ void stereo_icBWE_init_enc_fx( set16_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, shl( L_FILT_MAX, 1 ) ); /* SHB ref channel */ - set32_fx( hStereoICBWE->mem_shb_speech_ref_fx, 0, L_LOOK_16k ); + set16_fx( hStereoICBWE->mem_shb_speech_ref_fx, 0, L_LOOK_16k ); /* SHB non-ref channel */ - set32_fx( hStereoICBWE->mem_shb_speech_nonref_fx, 0, L_LOOK_16k ); + set16_fx( hStereoICBWE->mem_shb_speech_nonref_fx, 0, L_LOOK_16k ); /* unscaled & scaled SHB synthesis memory */ set32_fx( hStereoICBWE->mem_lpc_shbsynth_nonref_fx, 0, LPC_SHB_ORDER ); @@ -675,16 +1665,39 @@ void stereo_icBWE_init_enc_fx( set16_fx( hStereoICBWE->memModifyFs_icbwe_fx[1], 0, shl( L_FILT32k, 1 ) ); set32_fx( hStereoICBWE->mem_nrg_L_fx, 0, 2 ); + hStereoICBWE->mem_nrg_L_fx_e = 0; + move16(); set32_fx( hStereoICBWE->mem_nrg_R_fx, 0, 2 ); + hStereoICBWE->mem_nrg_R_fx_e = 0; + move16(); set32_fx( hStereoICBWE->mem_nrg_DMX_fx, 0, 2 ); + hStereoICBWE->mem_nrg_DMX_fx_e = 0; + move16(); + hStereoICBWE->gDes_pastFrame_fx = MAX_32; // Q31 hStereoICBWE->icbweRefEner_fx = 0; move32(); move32(); - + hStereoICBWE->gDes_pastFrame_fx = MAX_32; // Q31 + move32(); + hStereoICBWE->gDes_pastFrame_e = 0; // Q31 + move16(); + hStereoICBWE->prevgsMapping_fx = MAX_32; + move32(); + hStereoICBWE->prevgsMapping_e = 0; + move16(); hStereoICBWE->MSFlag = 0; move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + set_f( hStereoICBWE->nlExc16k, 0, L_FRAME16k ); + set16_fx( hStereoICBWE->nlExc16k_fx, 0, L_FRAME16k ); + hStereoICBWE->nlExc16k_e = 0; + set_f( hStereoICBWE->mixExc16k, 0, L_FRAME16k ); + set16_fx( hStereoICBWE->mixExc16k_fx, 0, L_FRAME16k ); + hStereoICBWE->mixExc16k_e = 0; +#endif + return; } /*-------------------------------------------------------------------* diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 96108be8b1c354f82ceb9a6d40bbb4dd9601563e..4bd59385850c79bf00a1030d0ee954c48c602e50 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -1239,22 +1239,41 @@ void stereo_mdct_core_enc( float max_tb = 0; Word16 max_sb_fx = 0; Word16 max_tb_fx = 0; + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; FOR( Word16 sfb = 0; sfb < 23; sfb++ ) { f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); - max_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_tb ); - max_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_tb ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); - max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); - max_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_sb ); - max_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_sb ); f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); - f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); - hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); - hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); - hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); } FOR( i = 0; i < IGF_MAX_TILES; i++ ) @@ -1285,10 +1304,10 @@ void stereo_mdct_core_enc( me2f_buf( &p_powerSpec_fx[ch][0], sts[ch]->hTcxEnc->spectrum_e[n], &p_powerSpec[ch][0], hGrid->infoGranuleLen ); for ( Word16 sfb = 0; sfb < 23; sfb++ ) { - hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); - hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); - hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); - hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); @@ -1318,7 +1337,148 @@ void stereo_mdct_core_enc( { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + floatToFixed_arr16( &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold_flt[0][0], &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); + me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + } + + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } +#endif +#else ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#endif } } } @@ -1340,7 +1500,148 @@ void stereo_mdct_core_enc( { for ( n = 0; n < nSubframes; n++ ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + floatToFixed_arr16( &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold_flt[0][0], &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); + me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + } + + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } +#endif +#else ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#endif } } } @@ -1421,9 +1722,36 @@ void stereo_mdct_core_enc( push_next_indice( hBstr, hStereoMdct->split_ratio, SMDCT_NBBITS_SPLIT_RATIO ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + st->hTcxEnc->tcx_target_bits_fac = float_to_fix16( st->hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif ivas_mdct_quant_coder_fx( hCPE, tnsBits, tnsSize, p_param, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + st->hTcxEnc->tcx_target_bits_fac_flt = me2f_16( st->hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); + } +#endif pop_wmops(); return; diff --git a/lib_enc/ivas_stereo_switching_enc.c b/lib_enc/ivas_stereo_switching_enc.c index 165db27f982f92be65fef4a7adb4799a2ffdad4b..c7f07245d5cde83e453a0b67be3ba746518dce62 100644 --- a/lib_enc/ivas_stereo_switching_enc.c +++ b/lib_enc/ivas_stereo_switching_enc.c @@ -36,10 +36,89 @@ #include "rom_com.h" #include "prot.h" #include "ivas_prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_rom_com_fx.h" +#endif #include "ivas_rom_com.h" #include "assert.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#endif +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * Function allocate_CoreCoder_enc() + * + * Allocate CoreCoder modules + *-------------------------------------------------------------------*/ + +static ivas_error allocate_CoreCoder_enc_fx( + ENC_CORE_HANDLE st /* i/o: Core encoder state structure */ +) +{ + IF( st->hLPDmem == NULL && st->element_mode != IVAS_CPE_MDCT ) + { + IF( ( st->hLPDmem = (LPD_state_HANDLE) malloc( sizeof( LPD_state ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LPDmem\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + LPDmem_enc_init_fx( st->hLPDmem ); +#endif + LPDmem_enc_init( st->hLPDmem ); + } + + IF( st->hGSCEnc == NULL && st->element_mode != IVAS_CPE_MDCT ) + { + IF( ( st->hGSCEnc = (GSC_ENC_HANDLE) malloc( sizeof( GSC_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + GSC_enc_init_fx( st->hGSCEnc ); +#endif + GSC_enc_init( st->hGSCEnc ); + } + + IF( st->hNoiseEst == NULL ) + { + IF( ( st->hNoiseEst = (NOISE_EST_HANDLE) malloc( sizeof( NOISE_EST_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + noise_est_init_ivas_fx( st->hNoiseEst ); +#endif + } + + IF( st->hVAD == NULL ) + { + IF( ( st->hVAD = (VAD_HANDLE) malloc( sizeof( VAD_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + wb_vad_init_ivas_fx( st->hVAD ); +#endif + } + + IF( st->hSpMusClas == NULL ) + { + IF( ( st->hSpMusClas = (SP_MUS_CLAS_HANDLE) malloc( sizeof( SP_MUS_CLAS_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + speech_music_clas_init_ivas_fx( st->hSpMusClas ); +#endif + speech_music_clas_init( st->hSpMusClas ); + } + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * Function allocate_CoreCoder_enc() * @@ -74,7 +153,11 @@ static ivas_error allocate_CoreCoder_enc( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n" ) ); } +#ifndef IVAS_FLOAT_FIXED noise_est_init( st->hNoiseEst ); +#else + noise_est_init_ivas_fx( st->hNoiseEst ); +#endif } if ( st->hVAD == NULL ) @@ -83,7 +166,11 @@ static ivas_error allocate_CoreCoder_enc( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n" ) ); } +#ifndef IVAS_FLOAT_FIXED wb_vad_init( st->hVAD ); +#else + wb_vad_init_fx( st->hVAD ); +#endif } if ( st->hSpMusClas == NULL ) @@ -93,12 +180,14 @@ static ivas_error allocate_CoreCoder_enc( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n" ) ); } speech_music_clas_init( st->hSpMusClas ); +#if 1 + speech_music_clas_init_ivas_fx( st->hSpMusClas ); +#endif } return IVAS_ERR_OK; } - /*-------------------------------------------------------------------* * Function deallocate_CoreCoder_TCX_enc() * @@ -109,25 +198,25 @@ static void deallocate_CoreCoder_TCX_enc( ENC_CORE_HANDLE st /* i/o: Core encoder state structure */ ) { - if ( st->hTcxEnc != NULL ) + IF( st->hTcxEnc != NULL ) { free( st->hTcxEnc ); st->hTcxEnc = NULL; } - if ( st->hTcxCfg != NULL ) + IF( st->hTcxCfg != NULL ) { free( st->hTcxCfg ); st->hTcxCfg = NULL; } - if ( st->hIGFEnc != NULL ) + IF( st->hIGFEnc != NULL ) { free( st->hIGFEnc ); st->hIGFEnc = NULL; } - if ( st->hHQ_core != NULL ) + IF( st->hHQ_core != NULL ) { free( st->hHQ_core ); st->hHQ_core = NULL; @@ -137,76 +226,494 @@ static void deallocate_CoreCoder_TCX_enc( } -/*-------------------------------------------------------------------* - * Function deallocate_CoreCoder_enc() - * - * Deallocate CoreCoder modules - *-------------------------------------------------------------------*/ +/*-------------------------------------------------------------------* + * Function deallocate_CoreCoder_enc() + * + * Deallocate CoreCoder modules + *-------------------------------------------------------------------*/ + +static void deallocate_CoreCoder_enc( + ENC_CORE_HANDLE st /* i/o: Core encoder state structure */ +) +{ + IF( st->hLPDmem != NULL ) + { + free( st->hLPDmem ); + st->hLPDmem = NULL; + } + + IF( st->hGSCEnc != NULL ) + { + free( st->hGSCEnc ); + st->hGSCEnc = NULL; + } + + IF( st->hNoiseEst != NULL && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + free( st->hNoiseEst ); + st->hNoiseEst = NULL; + } + + IF( st->hVAD != NULL && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + free( st->hVAD ); + st->hVAD = NULL; + } + + IF( st->hSpMusClas != NULL && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + free( st->hSpMusClas ); + st->hSpMusClas = NULL; + } + + IF( st->cldfbAnaEnc != NULL ) + { + deleteCldfb_ivas( &st->cldfbAnaEnc ); + } + + IF( st->hBWE_TD != NULL ) + { + free( st->hBWE_TD ); + st->hBWE_TD = NULL; + } + + IF( st->cldfbSynTd != NULL ) + { + deleteCldfb_ivas( &st->cldfbSynTd ); + } + + IF( st->hBWE_FD != NULL ) + { + free( st->hBWE_FD ); + st->hBWE_FD = NULL; + } + + IF( st->element_mode != IVAS_CPE_MDCT ) + { + deallocate_CoreCoder_TCX_enc( st ); + } + + return; +} + +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * Function stereo_memory_enc() + * + * Dynamically allocate/deallocate data structures depending on the actual CPE mode + *-------------------------------------------------------------------*/ + +ivas_error stereo_memory_enc_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word32 input_Fs, /* i : input sampling rate */ + const Word16 max_bwidth, /* i : maximum audio bandwidth */ + const IVAS_FORMAT ivas_format, /* i : ivas format */ + const Word16 nchan_transport /* i : number transport chans */ +) +{ + Encoder_State *st; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + assert( hCPE->last_element_mode >= IVAS_CPE_DFT && "Switching from SCE to CPE is not a valid configuration!" ); + + /*--------------------------------------------------------------* + * save parameters from structures that will be freed + *---------------------------------------------------------------*/ + test(); + IF( hCPE->hStereoTCA != NULL && EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + set16_fx( hCPE->hStereoTCA->prevCorrLagStats, (Word16) hCPE->hStereoDft->hItd->itd[1], 3 ); + IF( hCPE->hStereoDft->hItd->itd[1] >= 0 ) + { + hCPE->hStereoTCA->prevRefChanIndx = L_CH_INDX; + } + ELSE + { + hCPE->hStereoTCA->prevRefChanIndx = R_CH_INDX; + } + move16(); + } + + /*--------------------------------------------------------------* + * allocate/deallocate data structures + *---------------------------------------------------------------*/ + + IF( NE_16( hCPE->element_mode, hCPE->last_element_mode ) ) + { + /*--------------------------------------------------------------* + * switching CPE mode to DFT stereo + *---------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + /* deallocate data structure of the previous CPE mode */ + IF( hCPE->hStereoTD != NULL ) + { + free( hCPE->hStereoTD ); + hCPE->hStereoTD = NULL; + } + + IF( hCPE->hStereoMdct != NULL ) + { + stereo_mdct_enc_destroy( &( hCPE->hStereoMdct ) ); + hCPE->hStereoMdct = NULL; + } + + /* deallocate CoreCoder secondary channel */ + deallocate_CoreCoder_enc( hCPE->hCoreCoder[1] ); + + /* allocate DFT stereo data structure */ + IF( NE_32( ( error = stereo_dft_enc_create( &( hCPE->hStereoDft ), input_Fs, max_bwidth ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* allocate ICBWE structure */ + IF( hCPE->hStereoICBWE == NULL ) + { + IF( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + stereo_icBWE_init_enc( hCPE->hStereoICBWE ); // To be removed +#endif + stereo_icBWE_init_enc_fx( hCPE->hStereoICBWE ); + } + + /* allocate HQ core in M channel */ + st = hCPE->hCoreCoder[0]; + IF( st->hHQ_core == NULL ) + { + IF( ( st->hHQ_core = (HQ_ENC_HANDLE) malloc( sizeof( HQ_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n" ) ); + } + + HQ_core_enc_init( st->hHQ_core ); + } + } + + /*--------------------------------------------------------------* + * switching CPE mode to TD stereo + *---------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + /* deallocate data structure of the previous CPE mode */ + 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; + } + + /* deallocated TCX/IGF structures for second channel */ + deallocate_CoreCoder_TCX_enc( hCPE->hCoreCoder[1] ); + + /* allocate TD stereo data structure */ + IF( hCPE->hStereoTD != NULL ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: TD Stereo memory already allocated\n" ); + } + + IF( ( hCPE->hStereoTD = (STEREO_TD_ENC_DATA_HANDLE) malloc( sizeof( STEREO_TD_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); + } + + stereo_td_init_enc_fx( hCPE->hStereoTD, hCPE->last_element_mode ); + /* allocate secondary channel */ +#ifdef IVAS_FLOAT_FIXED + IF( NE_32( ( error = allocate_CoreCoder_enc_fx( hCPE->hCoreCoder[1] ) ), IVAS_ERR_OK ) ) +#endif + IF( ( error = allocate_CoreCoder_enc( hCPE->hCoreCoder[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /*--------------------------------------------------------------* + * allocate DFT/TD stereo structures after MDCT stereo frame + *---------------------------------------------------------------*/ + test(); + test(); + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) && ( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) || EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) ) + { + /* Deallocate MDCT CNG structures */ + deleteCldfb_ivas( &hCPE->hCoreCoder[0]->cldfbAnaEnc ); + deleteCldfb_ivas( &hCPE->hCoreCoder[1]->cldfbAnaEnc ); + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + IF( hCPE->hCoreCoder[1]->hDtxEnc != NULL ) + { + free( hCPE->hCoreCoder[1]->hDtxEnc ); + hCPE->hCoreCoder[1]->hDtxEnc = NULL; + } + + IF( hCPE->hCoreCoder[1]->hFdCngEnc != NULL ) + { + deleteFdCngEnc( &hCPE->hCoreCoder[1]->hFdCngEnc ); + } + } + + IF( hCPE->hCoreCoder[0]->Opt_DTX_ON && hCPE->hCoreCoder[0]->hTdCngEnc == NULL ) + { + IF( ( hCPE->hCoreCoder[0]->hTdCngEnc = (TD_CNG_ENC_HANDLE) malloc( sizeof( TD_CNG_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); + } + + td_cng_enc_init( hCPE->hCoreCoder[0]->hTdCngEnc, hCPE->hCoreCoder[0]->Opt_DTX_ON, hCPE->hCoreCoder[0]->max_bwidth ); + } + + /* allocate TCA data structure */ + IF( hCPE->hStereoTCA != NULL ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: TCA Stereo memory already allocated\n" ); + } + + IF( ( hCPE->hStereoTCA = (STEREO_TCA_ENC_HANDLE) malloc( sizeof( STEREO_TCA_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); + } + + stereo_tca_init_enc( hCPE->hStereoTCA, input_Fs ); + + st = hCPE->hCoreCoder[0]; + + /* allocate primary channel substructures */ + IF( NE_32( ( error = allocate_CoreCoder_enc( st ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* allocate CLDFB for primary channel */ + IF( st->cldfbAnaEnc == NULL ) + { + IF( NE_32( ( error = openCldfb_ivas_enc( &st->cldfbAnaEnc, CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_1_25MS ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* allocate BWEs for primary channel */ + IF( st->hBWE_TD == NULL ) + { + IF( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); + } + + IF( st->cldfbSynTd == NULL ) + { + IF( NE_32( ( error = openCldfb_ivas_enc( &st->cldfbSynTd, CLDFB_SYNTHESIS, 16000, CLDFB_PROTOTYPE_1_25MS ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + InitSWBencBuffer( st->hBWE_TD ); + InitSWBencBuffer_fx( st ); + ResetSHBbuffer_Enc( st->hBWE_TD ); + + IF( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); + } + + fd_bwe_enc_init( st->hBWE_FD ); + } + + /* allocate stereo CNG structure */ + IF( hCPE->hStereoCng == NULL ) + { + IF( ( hCPE->hStereoCng = (STEREO_CNG_ENC_HANDLE) malloc( sizeof( STEREO_CNG_ENC ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo Cng for Unified/TD\n" ) ); + } + + stereo_enc_cng_init( hCPE->hStereoCng ); + } + } + + /*--------------------------------------------------------------* + * switching CPE mode to MDCT stereo + *---------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + Word16 i; + + /* deallocate data structure of the previous CPE mode */ + IF( hCPE->hStereoDft != NULL ) + { + stereo_dft_enc_destroy( &( hCPE->hStereoDft ) ); + hCPE->hStereoDft = NULL; + } + + IF( hCPE->hStereoTD != NULL ) + { + free( hCPE->hStereoTD ); + hCPE->hStereoTD = NULL; + } + + IF( hCPE->hStereoTCA != NULL ) + { + free( hCPE->hStereoTCA ); + hCPE->hStereoTCA = NULL; + } + + IF( hCPE->hStereoICBWE != NULL ) + { + free( hCPE->hStereoICBWE ); + hCPE->hStereoICBWE = NULL; + } + + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + /* deallocate core-coder substructures */ + deallocate_CoreCoder_enc( hCPE->hCoreCoder[i] ); + } + + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + /* allocate secondary channel */ + IF( NE_32( ( error = allocate_CoreCoder_enc( hCPE->hCoreCoder[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* allocate TCX/IGF structures for second channel */ + st = hCPE->hCoreCoder[1]; + + IF( ( st->hTcxEnc = (TCX_ENC_HANDLE) malloc( sizeof( TCX_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxEnc\n" ) ); + } + +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum_fx[0] = st->hTcxEnc->spectrum_long_fx; + st->hTcxEnc->spectrum_fx[1] = st->hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#endif // IVAS_FLOAT_FIXED + + st->hTcxEnc->spectrum[0] = st->hTcxEnc->spectrum_long; + st->hTcxEnc->spectrum[1] = st->hTcxEnc->spectrum_long + N_TCX10_MAX; +#ifdef IVAS_FLOAT_FIXED + st->hTcxEnc->spectrum_fx[0] = st->hTcxEnc->spectrum_long_fx; + st->hTcxEnc->spectrum_fx[1] = st->hTcxEnc->spectrum_long_fx + N_TCX10_MAX; +#endif + set_f( st->hTcxEnc->old_out, 0, L_FRAME32k ); + set_f( st->hTcxEnc->spectrum_long, 0, N_MAX ); + st->hTcxEnc->tfm_mem = 0.75f; + + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + st->last_core = ACELP_CORE; /* needed to set-up TCX core in SetTCXModeInfo() */ + move16(); + } + + IF( ( st->hTcxCfg = (TCX_CONFIG_HANDLE) malloc( sizeof( TCX_config ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n" ) ); + } + + IF( ( st->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); + } + st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode ); + move16(); + + /* allocate and initialize MDCT stereo structure */ + IF( ( hCPE->hStereoMdct = (STEREO_MDCT_ENC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MDCT Stereo \n" ) ); + } -static void deallocate_CoreCoder_enc( - ENC_CORE_HANDLE st /* i/o: Core encoder state structure */ -) -{ - if ( st->hLPDmem != NULL ) - { - free( st->hLPDmem ); - st->hLPDmem = NULL; - } + initMdctStereoEncData_fx( hCPE->hStereoMdct, ivas_format, hCPE->element_mode, hCPE->element_brate, hCPE->hCoreCoder[0]->max_bwidth, 0, NULL, 1 ); - if ( st->hGSCEnc != NULL ) - { - free( st->hGSCEnc ); - st->hGSCEnc = NULL; - } + test(); + hCPE->hStereoMdct->isSBAStereoMode = ( EQ_32( ivas_format, SBA_FORMAT ) && EQ_16( nchan_transport, 2 ) ); - if ( st->hNoiseEst != NULL && st->element_mode != IVAS_CPE_MDCT ) - { - free( st->hNoiseEst ); - st->hNoiseEst = NULL; - } + test(); + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && LE_32( hCPE->element_brate, MAX_MDCT_ITD_BRATE ) && EQ_16( ivas_format, STEREO_FORMAT ) ) + { + IF( NE_32( ( error = initMdctItdHandling( hCPE->hStereoMdct, input_Fs ) ), IVAS_ERR_OK ) ) + { + return error; + } + } - if ( st->hVAD != NULL && st->element_mode != IVAS_CPE_MDCT ) - { - free( st->hVAD ); - st->hVAD = NULL; - } + /* allocate/deallocate and initialize DTX/CNG structures */ + IF( hCPE->hCoreCoder[0]->Opt_DTX_ON ) + { + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + st = hCPE->hCoreCoder[i]; + IF( NE_32( ( error = openCldfb_ivas_enc( &st->cldfbAnaEnc, CLDFB_ANALYSIS, st->input_Fs, CLDFB_PROTOTYPE_1_25MS ) ), IVAS_ERR_OK ) ) + { + return error; + } - if ( st->hSpMusClas != NULL && st->element_mode != IVAS_CPE_MDCT ) - { - free( st->hSpMusClas ); - st->hSpMusClas = NULL; - } + st->currEnergyLookAhead = 6.1e-5f; - if ( st->cldfbAnaEnc != NULL ) - { - deleteCldfb_ivas( &st->cldfbAnaEnc ); - } + IF( st->hDtxEnc == NULL ) + { + IF( ( st->hDtxEnc = (DTX_ENC_HANDLE) malloc( sizeof( DTX_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX variables\n" ) ); + } + } + dtx_enc_init( st, 0, FIXED_SID_RATE ); - if ( st->hBWE_TD != NULL ) - { - free( st->hBWE_TD ); - st->hBWE_TD = NULL; - } + IF( st->hTdCngEnc != NULL ) + { + free( st->hTdCngEnc ); + st->hTdCngEnc = NULL; + } - if ( st->cldfbSynTd != NULL ) - { - deleteCldfb_ivas( &st->cldfbSynTd ); - } + IF( st->hFdCngEnc == NULL ) + { + IF( NE_32( ( error = createFdCngEnc( &st->hFdCngEnc ) ), IVAS_ERR_OK ) ) + { + return error; + } - if ( st->hBWE_FD != NULL ) - { - free( st->hBWE_FD ); - st->hBWE_FD = NULL; + initFdCngEnc( st->hFdCngEnc, st->input_Fs, st->cldfbAnaEnc->scale_flt ); + configureFdCngEnc( st->hFdCngEnc, st->bwidth, st->rf_mode && st->total_brate == ACELP_13k20 ? ACELP_9k60 : st->total_brate ); + } + } + } + } } - if ( st->element_mode != IVAS_CPE_MDCT ) + test(); + test(); + test(); + IF( EQ_16( ivas_format, STEREO_FORMAT ) && EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && LE_32( hCPE->element_brate, MAX_MDCT_ITD_BRATE ) && GT_32( hCPE->last_element_brate, MAX_MDCT_ITD_BRATE ) ) { - deallocate_CoreCoder_TCX_enc( st ); + /* allocate MDCT stereo ITD handling structure */ + IF( NE_32( ( error = initMdctItdHandling( hCPE->hStereoMdct, input_Fs ) ), IVAS_ERR_OK ) ) + { + return error; + } } - return; + return error; } - +#else /*-------------------------------------------------------------------* * Function stereo_memory_enc() @@ -434,6 +941,9 @@ ivas_error stereo_memory_enc( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) @@ -625,7 +1135,314 @@ ivas_error stereo_memory_enc( return error; } +#endif +#ifdef IVAS_FLOAT_FIXED + +static void v_multc_fixed_32_16( + const Word16 x[], /* i : Input vector */ + const Word32 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains c*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_16_1( c, x[i] ); + move32(); + } + + return; +} +/*-------------------------------------------------------------------* + * Function stereo_switching_enc() + * + * Handling of memories in case of CPE modes switching + *-------------------------------------------------------------------*/ + +void stereo_switching_enc_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 old_input_signal_pri[], /* i : old input signal of primary channel */ + const Word16 input_frame, /* i : input frame length */ + const Word16 q_inp ) +{ + Word16 i, n, dft_ovl, offset; + Word16 tmp_fx; + move16(); + Encoder_State **sts; + + sts = hCPE->hCoreCoder; + dft_ovl = extract_l( Mpy_32_32( imult3216( input_frame, STEREO_DFT_OVL_MAX ), 2236963 ) ); // 1/L_FRAME48k = 2236963 (Q31) + + /* update DFT analysis overlap memory */ + IF( GT_16( hCPE->element_mode, IVAS_CPE_DFT ) && hCPE->input_mem_fx[0] != NULL && NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + Copy( sts[n]->input_fx + input_frame - dft_ovl, hCPE->input_mem_fx[n], dft_ovl ); + } + } + + /* save original stereo input (MDCT overlap part) for both channels in unused old input of right channel for possible DFT->MDCT transition */ + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + Copy( sts[0]->input_fx + sub( (Word16) Mpy_32_32( sts[0]->input_Fs, 42949673 /* 1/50 in Q31*/ ), sts[0]->encoderLookahead_FB ), sts[1]->input_fx - shl( sts[0]->encoderLookahead_FB, 1 ), sts[0]->encoderLookahead_FB ); + + Copy( sts[1]->input_fx + sub( (Word16) Mpy_32_32( sts[1]->input_Fs, 42949673 /* 1/50 in Q31*/ ), sts[1]->encoderLookahead_FB ), sts[1]->input_fx - sts[1]->encoderLookahead_FB, sts[1]->encoderLookahead_FB ); + } + + + /* TD/MDCT -> DFT stereo switching */ + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && NE_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + /* window DFT synthesis overlap memory @input_Fs, primary channel */ + FOR( i = 0; i < dft_ovl; i++ ) + { + hCPE->hStereoDft->output_mem_dmx_fx[i] = Mpy_32_16_r( hCPE->hStereoDft->win_fx[dft_ovl - 1 - i], old_input_signal_pri[input_frame - dft_ovl + i] ); + } + /* reset 48kHz BWE overlap memory */ + set32_fx( hCPE->hStereoDft->output_mem_dmx_32k_fx, 0, STEREO_DFT_OVL_32k ); + + stereo_dft_enc_reset_fx( hCPE->hStereoDft ); + + /* update ITD parameters */ + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) + { + set32_fx( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoTCA->prevCorrLagStats[2], STEREO_DFT_ENC_DFT_NB ); + } + + /* Update the side_gain[] parameters */ + IF( hCPE->hStereoTCA != NULL && NE_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) ) + { + tmp_fx = usdequant_fx( hCPE->hStereoTCA->indx_ica_gD, STEREO_TCA_GDMIN_FX, STEREO_TCA_GDSTEP_FX ); + FOR( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) + { + hCPE->hStereoDft->side_gain_fx[STEREO_DFT_BAND_MAX + i] = L_deposit_h( tmp_fx ); + move32(); + } + } + + /* do not allow differential coding of DFT side parameters */ + hCPE->hStereoDft->res_pred_counter = STEREO_DFT_FEC_THRESHOLD; + move16(); + + /* update DFT synthesis overlap memory @12.8kHz */ + FOR( i = 0; i < STEREO_DFT_OVL_12k8; i++ ) + { + hCPE->hStereoDft->output_mem_dmx_12k8_fx[i] = L_shr( Mpy_32_16_r( hCPE->hStereoDft->win_12k8_fx[STEREO_DFT_OVL_12k8 - 1 - i], sts[0]->buf_speech_enc[L_FRAME32k + L_FRAME - STEREO_DFT_OVL_12k8 + i] ), q_inp ); + move32(); + } + Word16 q_dmx = Q16; + move16(); + /* update DFT synthesis overlap memory @16kHz, primary channel only */ + L_lerp_fx( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx_16k_fx, STEREO_DFT_OVL_16k, dft_ovl, &q_dmx ); + FOR( i = 0; i < STEREO_DFT_OVL_16k; i++ ) + { + hCPE->hStereoDft->output_mem_dmx_16k_fx[i] = L_shl( hCPE->hStereoDft->output_mem_dmx_16k_fx[i], q_dmx - Q16 ); + move32(); + } + + /* reset DFT synthesis overlap memory @8kHz, secondary channel */ + set32_fx( hCPE->hStereoDft->output_mem_res_8k_fx, 0, STEREO_DFT_OVL_8k ); + + hCPE->hCoreCoder[1]->vad_flag = 0; + move16(); + } + + /* MDCT -> TD stereo switching */ + test(); + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) ) + { + hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + hCPE->hStereoTD->tdm_last_ratio_idx_SM = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + hCPE->hStereoTD->tdm_last_SM_flag = 0; + move16(); + hCPE->hStereoTD->tdm_last_inst_ratio_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); + hCPE->hStereoTD->tdm_last_ratio_fx = tdm_ratio_tabl_fx[LRTD_STEREO_LEFT_IS_PRIM]; + move32(); + } + /* DFT -> TD stereo switching */ + ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); + hCPE->hStereoTD->tdm_last_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM; + move16(); + hCPE->hStereoTD->tdm_last_SM_flag = 0; + move16(); + hCPE->hStereoTD->tdm_last_inst_ratio_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); + + /* First frame after DFT frame AND the content is uncorrelated or xtalk -> the primary channel is forced to left */ + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + set_zero( sts[1]->input - input_frame, input_frame ); + set_zero_fx( sts[1]->input32_fx - input_frame, input_frame ); + + hCPE->hStereoTD->tdm_last_ratio_fx = tdm_ratio_tabl_fx[LRTD_STEREO_LEFT_IS_PRIM]; + + hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM; + + IF( LT_32( hCPE->hStereoTCA->instTargetGain_fx, 26843546 ) && ( hCPE->hCoreCoder[0]->vad_flag || hCPE->hCoreCoder[1]->vad_flag ) ) /* but if there is no content in the L channel -> the primary channel is forced to right */ + { + hCPE->hStereoTD->tdm_last_ratio_fx = tdm_ratio_tabl_fx[LRTD_STEREO_RIGHT_IS_PRIM]; + hCPE->hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM; + move16(); + } + } + } + + /* no secondary channel in the previous frame -> memory resets */ + test(); + IF( GT_16( hCPE->element_mode, IVAS_CPE_DFT ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) + { + IF( sts[0]->cldfbAnaEnc != NULL ) + { + offset = sub( sts[0]->cldfbAnaEnc->p_filter_length, sts[0]->cldfbAnaEnc->no_channels ); + for ( i = 0; i < offset; i++ ) + { + sts[0]->cldfbAnaEnc->cldfb_state_fx[i] = L_deposit_h( old_input_signal_pri[input_frame - offset - NS2SA( input_frame * FRAMES_PER_SEC, L_MEM_RECALC_TBE_NS ) + i] ); + move32(); + } + sts[0]->cldfbAnaEnc->Q_cldfb_state = Q16; + move16(); + } + + IF( sts[0]->cldfbSynTd != NULL ) + { + cldfb_reset_memory_fx( sts[0]->cldfbSynTd ); + sts[0]->currEnergyLookAhead_fx = 130996; + move32(); + } + + IF( hCPE->hStereoICBWE == NULL && sts[1]->cldfbAnaEnc != NULL ) + { + offset = sub( sts[1]->cldfbAnaEnc->p_filter_length, sts[1]->cldfbAnaEnc->no_channels ); + + IF( hCPE->hStereoTD != NULL && EQ_16( hCPE->hStereoTD->tdm_last_ratio_idx, LRTD_STEREO_LEFT_IS_PRIM ) ) + { + v_multc_fixed_32_16( hCPE->hCoreCoder[1]->old_input_signal_fx + sub( input_frame, add( offset, NS2SA( input_frame * FRAMES_PER_SEC, L_MEM_RECALC_TBE_NS ) ) ), -MAX_32, sts[1]->cldfbAnaEnc->cldfb_state_fx, offset ); + } + ELSE + { + FOR( i = 0; i < offset; i++ ) + { + sts[1]->cldfbAnaEnc->cldfb_state_fx[i] = L_shr( L_deposit_h( hCPE->hCoreCoder[1]->old_input_signal_fx[input_frame - offset - NS2SA( input_frame * FRAMES_PER_SEC, L_MEM_RECALC_TBE_NS ) + i] ), 5 ); + move32(); + } + } + + IF( sts[1]->cldfbSynTd != NULL ) + { + cldfb_reset_memory_fx( sts[1]->cldfbSynTd ); + sts[1]->currEnergyLookAhead_fx = 130996; + move32(); + } + } + + sts[1]->last_extl = -1; + move16(); + + /* no secondary channel in the previous frame -> memory resets */ + set16_fx( sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); + set16_fx( sts[1]->mem_decim_fx, 0, 2 * L_FILT_MAX ); + + sts[1]->mem_preemph_fx = 0; + move16(); + + set16_fx( sts[1]->buf_speech_enc, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + set16_fx( sts[1]->buf_speech_enc_pe, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + + IF( sts[1]->hTcxEnc != NULL ) + { + set16_fx( sts[1]->hTcxEnc->buf_speech_ltp, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + set16_fx( sts[1]->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + set16_fx( sts[1]->buf_synth, 0, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + sts[1]->mem_wsp_fx = 0; + move16(); + sts[1]->mem_wsp_enc = 0; + move16(); + init_gp_clip_fx( sts[1]->clip_var_fx ); + + set32_fx( sts[1]->Bin_E_fx, 0, L_FFT ); + set32_fx( sts[1]->Bin_E_old_fx, 0, L_FFT / 2 ); + + /* sts[1]->hLPDmem reset already done in allocation of handles */ + + sts[1]->last_L_frame = sts[0]->last_L_frame; + move16(); + pitch_ol_init_fx( &sts[1]->old_thres_fx, &sts[1]->old_pitch, &sts[1]->delta_pit, &sts[1]->old_corr_fx ); + set16_fx( sts[1]->old_wsp_fx, 0, L_WSP_MEM ); + set16_fx( sts[1]->old_wsp2_fx, 0, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + set16_fx( sts[1]->mem_decim2_fx, 0, 3 ); + Copy( sts[0]->pitch, sts[1]->pitch, 3 ); + + sts[1]->Nb_ACELP_frames = 0; + move16(); + + /* populate PCh memories into the SCh */ + IF( sts[0]->hLPDmem != NULL ) + { + Copy( sts[0]->hLPDmem->old_exc, sts[1]->hLPDmem->old_exc, L_EXC_MEM ); + } + Copy( sts[0]->lsf_old_fx, sts[1]->lsf_old_fx, M ); + Copy( sts[0]->lsp_old_fx, sts[1]->lsp_old_fx, M ); + Copy( sts[0]->lsf_old1_fx, sts[1]->lsf_old1_fx, M ); + Copy( sts[0]->lsp_old1_fx, sts[1]->lsp_old1_fx, M ); + + sts[1]->GSC_noisy_speech = 0; + move16(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + /* cross-fade overlap region of DFT Stereo downmix and original stereo channels */ + tmp_fx = div_s( 64, shl( sts[0]->encoderLookahead_FB, Q6 ) ); + FOR( i = 0; i < sts[0]->encoderLookahead_FB; i++ ) + { + sts[1]->input32_fx[-sts[0]->encoderLookahead_FB + i] = L_shr( Mpy_32_16_1( L_add( Mpy_32_16_1( sts[0]->input32_fx[-sts[0]->encoderLookahead_FB + i], sts[0]->encoderLookahead_FB - i ), Mpy_32_16_1( sts[1]->input32_fx[-sts[0]->encoderLookahead_FB + i], i ) ), tmp_fx ), 13 ); + move32(); + sts[0]->input32_fx[-sts[0]->encoderLookahead_FB + i] = L_shr( Mpy_32_16_1( L_add( Mpy_32_16_1( sts[0]->input32_fx[-sts[0]->encoderLookahead_FB + i], sts[0]->encoderLookahead_FB - i ), Mpy_32_16_1( sts[1]->input32_fx[-2 * sts[0]->encoderLookahead_FB + i], i ) ), tmp_fx ), 13 ); + move32(); + } + /* restore continuous signal in right channel (part of old_output was used to store original left channel) */ + Copy32( sts[0]->input32_fx - sts[0]->hTcxEnc->L_frameTCX, sts[1]->input32_fx - sts[0]->hTcxEnc->L_frameTCX, sts[0]->hTcxEnc->L_frameTCX - sts[0]->encoderLookahead_FB ); + + sts[1]->last_core = sts[0]->last_core; + move16(); + sts[1]->last_coder_type = sts[0]->last_coder_type; + move16(); + sts[1]->last_bwidth = sts[0]->last_bwidth; + move16(); + } + } + ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) ) + { + set16_fx( sts[0]->hLPDmem->old_exc, 0, L_EXC_MEM ); + set16_fx( sts[1]->hLPDmem->old_exc, 0, L_EXC_MEM ); + } + test(); + + /* TD/DFT -> MDCT stereo switching (there is no TCX in the TD stereo secondary channel, or DFT stereo) */ + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && NE_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) ) + { + sts[1]->hTcxCfg->last_aldo = sts[0]->hTcxCfg->last_aldo; + move16(); + sts[1]->hTcxCfg->tcx_curr_overlap_mode = sts[0]->hTcxCfg->tcx_curr_overlap_mode; + move16(); + } + + return; +} +#else /*-------------------------------------------------------------------* * Function stereo_switching_enc() * @@ -855,3 +1672,4 @@ void stereo_switching_enc( return; } +#endif diff --git a/lib_enc/ivas_stereo_td_analysis.c b/lib_enc/ivas_stereo_td_analysis.c index 299f5e837c201808fd33f357f026becf95ecf524..c745013c2a1af347c6af52d3ac2fbf837f1851d8 100644 --- a/lib_enc/ivas_stereo_td_analysis.c +++ b/lib_enc/ivas_stereo_td_analysis.c @@ -62,6 +62,11 @@ #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 */ +#ifdef IVAS_FLOAT_FIXED +#define RMS_MIN_Q16 98304000 /* 1500 in Q16 */ /* Minimum energy for ratio index*/ +#define RMS_MIN2_Q16 65536000 /* 1000 in Q16 */ /* Minimum energy for LR encoding*/ +#define CORR_THRES_Q15 31130 /* Maximal open loop correlation */ +#endif #ifndef IVAS_FLOAT_FIXED #define DT_ENER_THR 200 /* Energy variation threshold */ #endif @@ -106,17 +111,28 @@ #define B_ADAP 0.16f #endif -#define PC_LIMIT 64 -#define RATIO_PG_HR 0.94f -#define RATIO_PG 0.92f -#define PG2ND 3.0f -#define EUCLDST 0.04f -#define RATIO_PG2 0.86f -#define PG2ND2 3.0f -#define EUCLDST2 0.08f - -#define RMS_THR 100 -#define RATIO_PG_LRTD 0.96f +#define PC_LIMIT 64 +#define RATIO_PG_HR 0.94f +#define RATIO_PG_HR_FX 2018634629 // 0.94f in Q31 +#define RATIO_PG 0.92f +#define RATIO_PG_FX 1975684956 // 0.92f in Q31 +#define PG2ND 3.0f +#define PG2ND_FX 6291456 // 3.0f in Q21 +#define EUCLDST 0.04f +#define EUCLDST_FX 85899346 // 0.04f in Q31 +#define RATIO_PG2 0.86f +#define RATIO_PG2_FX 1846835937 // 0.86f in Q31 +#define PG2ND2 3.0f +#define PG2ND2_FX 6291456 // 3.0f in Q21 +#define EUCLDST2 0.08f +#define EUCLDST2_FX 171798692 // 0.08f in Q31 + +#define RMS_THR 100 +#ifdef IVAS_FLOAT_FIXED +#define RMS_THR_Q16 ( 6553600 ) +#endif +#define RATIO_PG_LRTD 0.96f +#define RATIO_PG_LRTD_FX 2061584302 // 0.96f in Q31 #define IVAS_BRATE_OMASA_STEREO_SW_THR 15000 @@ -170,11 +186,611 @@ static float Comp_diff_lt_corr( CPE_ENC_HANDLE hCPE, const int16_t IsSideMono, c #endif -/*-------------------------------------------------------------------* - * Function stereo_tdm_ener_analysis() - * - *-------------------------------------------------------------------*/ +/*-------------------------------------------------------------------* + * Function stereo_tdm_ener_analysis() + * + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word16 stereo_tdm_ener_analysis_fx( + const Word16 ivas_format, /* i : IVAS format */ + CPE_ENC_HANDLE hCPE, /* i : CPE structure */ + const Word16 input_frame, /* i : Number of samples */ + Word16 *tdm_SM_or_LRTD_Pri, /* o : channel combination scheme flag in TD stereo OR LRTD primary channel */ + Word16 *tdm_ratio_idx_SM /* o : TDM ratio index for SM mode */ +) +{ + Word32 diff_lt_corr_fx /*Q24*/; + Word32 ratio_L_fx, dist_fx; + Word16 i, side_can_change; + Word16 idx, tdm_SM_flag_loc; + Word16 tmp_SM_flag; + Word16 desired_idx; + Word32 rms_thd_fx; // Q16 + Word16 tdm_NOOP_flag_loc, tdm_NOOP_flag; + STEREO_TD_ENC_DATA_HANDLE hStereoTD; + Encoder_State **sts; + Word32 d_lt_corr_raw_fx; + Word16 q_d_lt_corr_raw; + Word32 inst_ratio_L_fx; // Q24 + Word16 tdm_LRTD_pri_side; + 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; + + hStereoTD = hCPE->hStereoTD; + sts = hCPE->hCoreCoder; + + desired_idx = 0; + move16(); + inst_ratio_L_fx = 0; + move32(); + diff_lt_corr_fx = 0; + move32(); + /*----------------------------------------------------------------* + * Compute L and R energy and Long term RMS of each channel + *----------------------------------------------------------------*/ + + 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 ); + + /*----------------------------------------------------------------* + * Compute the 1st order energy difference difference + * Compute the gain of L&R channel compared to mono + * - estimate the long term evolution of the L to Mono gain + * - estimate the long term evolution of the R to Mono gain + * - estimate the long term difference between the long term + * - evolution of the L and R to Mono gain + *----------------------------------------------------------------*/ + + tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag; + move16(); + + 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 ); + + hStereoTD->tdm_SM_reset_flag = 0; + move16(); + + /*----------------------------------------------------------------* + * Check if the signal has Near Out Of Phase characteristics + * and trigger side/mono configuration if needed + *----------------------------------------------------------------*/ + + 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 ); + + /*----------------------------------------------------------------* + * Adjust stereo downmixing adaptation rate factor + * in function of the signal energy. If signal energy is low, + * adaptation rate factor is lower. This prevent stereo image + * move on speech offset + *----------------------------------------------------------------*/ + 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 ); + + IF( GT_16( q_d_lt_corr_raw, 31 ) ) + { + d_lt_corr_raw_fx = L_shr( d_lt_corr_raw_fx, sub( q_d_lt_corr_raw, Q31 ) ); + q_d_lt_corr_raw = Q31; + move16(); + } + + /*----------------------------------------------------------------* + * UNCLR classifier (detection of uncorrelated L and R channels) + * Xtalk classifier (detection of cross-talk L and R channels) + *----------------------------------------------------------------*/ + + unclr_classifier_td_fx( hCPE ); + xtalk_classifier_td_fx( hCPE ); + + /* switch to LRTD on cross-talk segments where two speakers are weakly correlated */ + hStereoTD->prev_fr_LRTD_TD_dec = hCPE->hStereoClassif->lrtd_mode; + move16(); + + /*----------------------------------------------------------------* + * When the energies of channels are low enough, compute the ratio + * of L and R needed to create new mono/side signals + *----------------------------------------------------------------*/ + + IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) ) + { + test(); + test(); + if ( ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) || EQ_16( hCPE->hStereoTD->prev_fr_LRTD_TD_dec, 1 ) ) && ( LE_32( L_add( L_sub( hCPE->element_brate, 50 * FRAMES_PER_SEC ), L_add( hCPE->brate_surplus, hCPE->brate_surplus ) ), IVAS_BRATE_OMASA_STEREO_SW_THR ) ) ) + { + hStereoTD->prev_fr_LRTD_TD_dec = 0; + move16(); + } + } + + rms_thd_fx = RMS_MIN_Q16; + move32(); + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + rms_thd_fx = L_shr( rms_thd_fx, 2 ); /*Q16*/ /*rms_thd_fx *= 0.25f*/ + test(); + test(); + IF( LE_32( hStereoTD->tdm_lt_rms_L_fx, 4915200 /* 75 in Q16*/ ) || LE_32( hStereoTD->tdm_lt_rms_R_fx, 75 /* 75 in Q16*/ ) /*|| sts[0]->last_coder_type == TRANSITION */ ) + { + rms_thd_fx = L_shr( rms_thd_fx, 5 ); /* Q16*/ /*rms_thd_fx *= 0.03125f*/ + } + ELSE IF( GE_16( sts[0]->hVAD->hangover_cnt, 8 ) && GE_16( sts[1]->hVAD->hangover_cnt, 8 ) ) + { + rms_thd_fx = imult3216( rms_thd_fx, 5 /*1/0.2f*/ ); /*Q16*/ /*rms_thd_fx /= 0.2f*/ + } + + /* Overwrite the LR decision flag in case the signals is already considered as S/M or when the signal is very similar between left and right channel */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16( tdm_SM_flag_loc, 1 ) ) + { + hStereoTD->prev_fr_LRTD_TD_dec = 0; + move16(); + } + ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && GT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 10 ) && + ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( LT_32( hCPE->hStereoClassif->xtalk_score_fx, -1717986918 /* -0.8f in Q31*/ ) || LT_32( hCPE->hStereoClassif->xtalk_wscore_fx, -279172874 /*-0.13f in Q31*/ ) ) ) || + ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 10737418 /* 0.005f in Q31 */ ) ) ) ) + { + /* This forces the LRTD to switch to TD when inactive content happens on both channel */ + hStereoTD->prev_fr_LRTD_TD_dec = 0; + move16(); + } + ELSE IF( hStereoTD->tdm_LRTD_flag == 0 && + ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( hCPE->hStereoClassif->xtalk_score_fx <= 0 || LE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748364 /*0.1f in Q31 */ ) ) ) || + ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && ( sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS ) && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 53687091 /*0.025f in Q31 */ ) ) + /* (sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && hCPE->hStereoClassif->xtalk_wscore <= 0.0f)*/ ) ) + { + /* This forces the LRTD to switch to TD when inactive content happens on both channel */ + hStereoTD->prev_fr_LRTD_TD_dec = 0; + move16(); + } + } + + side_can_change = 0; + move16(); + + /* update LRTD->DFT stereo hangover counters */ + IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) ) + { + hStereoTD->tdm_last_LRTD_frame_cnt = 0; + move16(); + } + ELSE + { + hStereoTD->tdm_last_LRTD_frame_cnt = add( hStereoTD->tdm_last_LRTD_frame_cnt, 1 ); + move16(); + hStereoTD->tdm_last_LRTD_frame_cnt = s_min( hStereoTD->tdm_last_LRTD_frame_cnt, 100 ); + move16(); + } + + if ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) + { + side_can_change = 1; + move16(); + } + + test(); + IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) && side_can_change == 0 ) + { + test(); + test(); + test(); + test(); + IF( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || + ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) || + ( sts[0]->hVAD->hangover_cnt != 0 && LT_16( sts[1]->hNoiseEst->Etot_last_fx, 3072 /*12 in Q8*/ ) ) || + ( sts[1]->hVAD->hangover_cnt != 0 && LT_16( sts[0]->hNoiseEst->Etot_last_fx, 3072 /*12 in Q8*/ ) ) || + ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ( ( ( LT_32( rms_L_fx, RMS_THR_Q16 ) && LT_32( rms_R_fx, RMS_THR_Q16 ) && LT_32( L_abs( L_sub( rms_R_fx, rms_L_fx ) ), RMS_THR_Q16 / 2 ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) || + ( LT_16( abs_s( sub( sts[0]->old_corr_fx, sts[1]->old_corr_fx ) ), 4915 /*0.15f in Q15*/ ) && GT_16( sts[0]->old_corr_fx, 22937 /*0.7f in Q15*/ ) && LT_16( sts[0]->old_corr_fx, 27853 /*0.85f in Q15*/ ) && LT_32( L_abs( L_sub( rms_L_fx, rms_R_fx ) ), rms_thd_fx ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) ) /* Both channels are low energy, clean background switching is allowed */ + ) + { + side_can_change = 1; + move16(); + } + } + } + ELSE IF( side_can_change == 0 ) /*if( hStereoTD->prev_fr_LRTD_TD_dec == 0 )*/ + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( LT_16( sts[0]->old_corr_fx, CORR_THRES_Q15 ) && LT_16( sts[1]->old_corr_fx, CORR_THRES_Q15 ) ) || ( LE_32( hStereoTD->tdm_lt_rms_L_fx, RMS_MIN2_Q16 ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, RMS_MIN2_Q16 ) ) ) && + ( ( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) ) || + ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( sts[0]->tdm_LRTD_flag == 0 || ( EQ_16( sts[0]->tdm_LRTD_flag, 1 ) && ( ( LT_32( rms_L_fx, L_shl( rms_thd_fx, 1 ) ) && LT_32( rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) ) ) ) ) /* Even if the UNCLR is set to 1, the content should be encoded with TD, lower swichting requierment */ + ) ) + { + side_can_change = 1; + move16(); + } + } + + test(); + test(); + if ( GE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 107374182 /*0.05f in Q31*/ ) && hStereoTD->prev_fr_LRTD_TD_dec == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + side_can_change = 0; + move16(); + } + test(); + test(); + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) || EQ_16( hStereoTD->flag_skip_DMX, 1 ) ) + { + desired_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + ratio_L_fx = ONE_IN_Q31; /*Q31*/ + move32(); + hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + hStereoTD->tdm_ratio_transition_mov_flag = 0; + move16(); + hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + hStereoTD->tdm_ratio_transition_cnt = 0; + move16(); + idx = TDM_NQ; /* Reserved quantizer index for special case */ + move16(); + } + ELSE IF( side_can_change || LE_16( sts[1]->ini_frame, 1 ) ) + { + ratio_L_fx = L_max( diff_lt_corr_fx, -RATIO_MAX_FX_Q24 ); // Q24 + ratio_L_fx = L_min( ratio_L_fx, RATIO_MAX_FX_Q24 ); // Q24 + ratio_L_fx = Madd_32_32( ONE_IN_Q24, 1432371593 /*0.667f in Q31*/, ratio_L_fx ); // Q24 + + test(); + test(); + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 4 ) ) ) + { + ratio_L_fx = hCPE->hStereoTD->tdm_last_ratio_fx; // Q31 /* note: the last_ratio is set in before in stereo_set_tdm() */ + move32(); + } + ELSE + { + /*ratio_L = ( 1.0f - cosf( EVS_PI * ratio_L / 2.0f ) ) / 2.0f;*/ + ratio_L_fx = L_deposit_h( sub( ONE_IN_Q14, getCosWord16( extract_l( Mpy_32_32( 1647099 /* EVS_PI/2 in Q20 */, ratio_L_fx ) ) ) ) ); // Q31 (Q14 + Q1(division by 2.0f) + Q16) + } + + test(); + test(); + test(); + IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) || ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( hCPE->hStereoClassif->prev_lrtd_mode == 0 || GT_16( abs_s( sub( hCPE->hStereoTCA->indx_ica_gD, 20 ) ), 2 ) ) ) ) + { + IF( GE_32( ratio_L_fx, 1138166333 /*0.53f in Q31*/ ) ) /* small hysteresis is used to prevent undesired switching during inactive segment */ + { + desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1; + move16(); + } + ELSE IF( LT_32( ratio_L_fx, 1009317315 /*0.47f in Q31*/ ) ) + { + desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1; + move16(); + } + ELSE IF( GT_32( L_sub( rms_L_fx, rms_R_fx ), 655360 /*10 in Q16*/ ) ) + { + desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1; + move16(); + } + ELSE + { + desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1; + move16(); + } + + test(); + test(); + IF( NE_16( desired_idx, hStereoTD->tdm_prev_desired_idx ) && EQ_16( hStereoTD->tdm_last_LRTD_frame_cnt, 1 ) && LE_16( sts[0]->last_coder_type, UNVOICED ) ) /* TD transtionning to FD, we don't want an inversion of channels on the first transition frame */ + { + desired_idx = hStereoTD->tdm_prev_desired_idx; + move16(); + } + ELSE + { + hStereoTD->tdm_prev_desired_idx = desired_idx; + move16(); + } + idx = desired_idx; + move16(); + } + ELSE + { + test(); + test(); + if ( GE_32( hCPE->element_brate, IVAS_48k ) && sts[0]->hVAD->hangover_cnt != 0 && LT_32( L_max( hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx ), 33554432 /* 512.0f */ ) ) + { + ratio_L_fx = check_bounds_l( ratio_L_fx, 644245094 /*0.3f in Q31*/, 1503238554 /*0.7f in Q31*/ ); + } + + test(); + test(); + test(); + test(); + IF( ( GT_32( hCPE->hStereoTCA->instTargetGain_fx, 644245094 /*1.2f in Q29*/ ) || GT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && LT_32( ratio_L_fx, 858993459 /*0.4f*/ ) ) + { + ratio_L_fx = 858993459; /*0.4f in Q31*/ + move32(); + } + ELSE IF( ( LT_32( hCPE->hStereoTCA->instTargetGain_fx, 429496730 /*0.8f*/ ) || LT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && GT_32( ratio_L_fx, 1288490189 /*0.6f in Q31*/ ) ) + { + ratio_L_fx = 1288490189; /* 0.6f in Q31 */ + move32(); + } + + dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[0] ) ); // Q31 + + desired_idx = 0; + move16(); + FOR( i = 1; i < TDM_NQ; i++ ) + { + IF( LE_32( L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ), dist_fx ) ) + { + dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ); // Q31 + desired_idx = i; + move16(); + } + } + + idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx, &hStereoTD->tdm_ratio_transition_mov_flag, hStereoTD->tdm_last_ratio_idx, &hStereoTD->tdm_prev_desired_idx, &hStereoTD->tdm_ratio_transition_cnt, tdm_SM_flag_loc, desired_idx ); + + /* Change the switching level in case of dual mono (in case the scenario still accept left right switching */ + /* This logic is needed in case the content is exactly the same in the 2 channel and it is expected to get back to LRTD, to prevent the secondary channel to be completely empty */ + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + IF( LE_16( idx, LRTD_STEREO_MID_IS_PRIM ) ) + { + idx = s_min( idx, LRTD_STEREO_MID_IS_PRIM - 1 ); + } + ELSE + { + idx = s_max( idx, LRTD_STEREO_MID_IS_PRIM + 1 ); + } + + hStereoTD->tdm_prev_desired_idx = idx; + move16(); + } + /* 0 and 30 are reserved to signal L-R only coding */ + } + } + ELSE + { + idx = hStereoTD->tdm_last_ratio_idx; + move16(); + } + + hStereoTD->tdm_inst_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM; + move16(); + tdm_LRTD_pri_side = -1; + move16(); + IF( LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 5 ) ) + { + desired_idx = 15; + move16(); + } + ELSE + { + desired_idx = 0; + move16(); + dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[0], 7 ) ) ); // Q24 + + FOR( i = 1; i < TDM_NQ; i++ ) + { + IF( LE_32( L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ), dist_fx ) ) + { + dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ); // Q24 + desired_idx = i; + move16(); + } + } + } + + IF( LT_16( sub( sts[1]->lp_speech_fx, sts[1]->lp_noise_fx ), 12800 /*50.0f*/ ) ) /* likely presence of noisy content */ + { + /* pointing in the right direction, inverse it else do nothing */ + test(); + test(); + test(); + test(); + IF( ( GT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) || ( LT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && LT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) ) + { + Word16 idx_offet; + idx_offet = 5; + move16(); + if ( GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) /* slightly Favor the 2nd channel */ + { + idx_offet = negate( idx_offet ); + } + desired_idx = add( desired_idx, idx_offet ); + desired_idx = check_bounds_s_fx( desired_idx, 0, 30 ); + } + } + + test(); + IF( sts[1]->clas != UNVOICED_CLAS || sts[0]->clas != UNVOICED_CLAS ) + { + desired_idx = check_bounds_s_fx( desired_idx, 5, 25 ); + } + + hStereoTD->tdm_inst_ratio_idx = desired_idx; + move16(); + IF( /*hCPE->last_element_mode == IVAS_CPE_MDCT ||*/ EQ_16( hStereoTD->flag_skip_DMX, 1 ) ) + { + /*force tdm_inst_ratio_idx to the reserved index */ + hStereoTD->tdm_inst_ratio_idx = idx; + move16(); + tdm_LRTD_pri_side = 1; /* left channel */ + move16(); + } + ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + idx = limit_idx_NoDwnmix_fx( idx, side_can_change, d_lt_corr_raw_fx, q_d_lt_corr_raw ); + + hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); + tdm_LRTD_pri_side = 0; /* right channel */ + move16(); + IF( idx != LRTD_STEREO_RIGHT_IS_PRIM ) + { + tdm_LRTD_pri_side = 1; /* left channel */ + move16(); + hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_RIGHT_IS_PRIM; + move16(); + } + } + ELSE + { + test(); + test(); + idx = limit_idx_Dwnmix_fx( idx, ( hCPE->hStereoClassif->unclr_decision || ( EQ_16( sts[0]->flag_noisy_speech_snr, 1 ) && GT_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748365 /*0.1f*/ ) ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt ); + } + + IF( GT_16( abs_s( sub( hStereoTD->tdm_last_ratio_idx, idx ) ), LRTD_STEREO_MID_IS_PRIM ) ) + { + hStereoTD->tdm_last_LRTD_PriCh_cnt = 0; + move16(); + } + ELSE + { + hStereoTD->tdm_last_LRTD_PriCh_cnt = add( hStereoTD->tdm_last_LRTD_PriCh_cnt, 1 ); + move16(); + } + ratio_L_fx = tdm_ratio_tabl_fx[idx]; // Q31 + move32(); + + test(); + IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) && hStereoTD->tdm_LRTD_flag == 0 ) + { + idx = shr( add( hStereoTD->tdm_last_ratio_idx, add( LRTD_STEREO_MID_IS_PRIM, 1 ) ), 1 ); + ratio_L_fx = tdm_ratio_tabl_fx[idx]; // Q31 + move32(); + } + + test(); + test(); + test(); + IF( ( EQ_16( hStereoTD->tdm_ratio_transition_mov_flag, 1 ) && GE_16( hStereoTD->tdm_ratio_transition_cnt, 31 ) ) || ( ( EQ_16( hStereoTD->tdm_last_SM_flag, tdm_SM_flag_loc ) ) && ( EQ_16( idx, hStereoTD->tdm_prev_stable_idx ) ) ) ) + { + hStereoTD->tdm_ratio_transition_cnt = 0; + move16(); + hStereoTD->tdm_ratio_transition_mov_flag = 0; + move16(); + } + + test(); + if ( hStereoTD->tdm_ratio_transition_mov_flag == 0 || tdm_SM_flag_loc == 0 ) + { + hStereoTD->tdm_prev_stable_idx = idx; + move16(); + } + + /* NOOP ratio calculation */ + IF( tdm_SM_flag_loc ) + { + IF( hStereoTD->tdm_SM_reset_flag ) + { + hStereoTD->tdm_lt_corr_RM_SM_fx = 167772 /*0.01f Q24*/; + move32(); + hStereoTD->tdm_lt_corr_LM_SM_fx = 167772 /*0.01f Q24*/; + move32(); + hStereoTD->tdm_last_ratio_SM_fx = hStereoTD->tdm_last_ratio_fx; + move32(); + hStereoTD->tdm_last_ratio_idx_SM = hStereoTD->tdm_last_ratio_idx; + move16(); + hStereoTD->tdm_lt_rms_L_SM_fx = 2621440; // 40.0f Q16 + move32(); + hStereoTD->tdm_lt_rms_R_SM_fx = 2621440; // 40.0f Q16 + move32(); + hStereoTD->tdm_last_diff_lt_corr_SM_fx = 0; + move32(); + hStereoTD->q_tdm_last_diff_lt_corr_SM = 0; + move16(); + hStereoTD->tdm_last_ener_lt_R_SM_fx = 0; + move32(); + hStereoTD->tdm_last_ener_lt_L_SM_fx = 0; + move32(); + + hStereoTD->tdm_noop_mov_flag = 0; + move16(); + hStereoTD->tdm_noop_cnt = 0; + move16(); + hStereoTD->tdm_last_SM_flag_noop = 0; + move16(); + hStereoTD->tdm_prev_stable_idx_SM = 0; + move16(); + hStereoTD->tdm_prev_desired_idx_SM = 0; + move16(); + hStereoTD->tdm_LT_es_em_SM_fx = 209715; // 0.1f Q21; + move32(); + hStereoTD->tdm_hyst_cnt_SM = 0; + move16(); + } + + *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM_fx( hCPE, sts, input_frame, &tdm_NOOP_flag ); + move16(); + } + ELSE + { + *tdm_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM; + move16(); + tdm_NOOP_flag = 1; + move16(); + } + + sts[0]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag; + move16(); + sts[1]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag; + move16(); + + /* set channel combination scheme flag */ + *tdm_SM_or_LRTD_Pri = tdm_SM_flag_loc; + move16(); + if ( EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) ) + { + *tdm_SM_or_LRTD_Pri = tdm_LRTD_pri_side; + move16(); + } + + hCPE->hStereoClassif->ratio_L_fx = ratio_L_fx; + move32(); + return idx; +} +#else int16_t stereo_tdm_ener_analysis( const int16_t ivas_format, /* i : IVAS format */ CPE_ENC_HANDLE hCPE, /* i : CPE structure */ @@ -184,93 +800,33 @@ 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 @@ -283,39 +839,8 @@ 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; @@ -324,17 +849,7 @@ 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 @@ -343,29 +858,8 @@ 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) @@ -559,11 +1053,7 @@ int16_t stereo_tdm_ener_analysis( } } -#ifdef IVAS_FLOAT_FIXED - idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx, &hStereoTD->tdm_ratio_transition_mov_flag, hStereoTD->tdm_last_ratio_idx, &hStereoTD->tdm_prev_desired_idx, &hStereoTD->tdm_ratio_transition_cnt, tdm_SM_flag_loc, desired_idx ); -#else idx = stereo_smooth_LR_transition( &hStereoTD->tdm_prev_stable_idx, &hStereoTD->tdm_ratio_transition_mov_flag, hStereoTD->tdm_last_ratio_idx, &hStereoTD->tdm_prev_desired_idx, &hStereoTD->tdm_ratio_transition_cnt, tdm_SM_flag_loc, desired_idx ); -#endif /* Change the switching level in case of dual mono (in case the scenario still accept left right switching */ /* This logic is needed in case the content is exactly the same in the 2 channel and it is expected to get back to LRTD, to prevent the secondary channel to be completely empty */ @@ -639,13 +1129,7 @@ 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 ) @@ -656,11 +1140,7 @@ int16_t stereo_tdm_ener_analysis( } else { -#ifdef IVAS_FLOAT_FIXED - idx = limit_idx_Dwnmix_fx( idx, ( hCPE->hStereoClassif->unclr_decision || ( sts[0]->flag_noisy_speech_snr == 1 && hCPE->hStereoClassif->xtalk_wscore > 0.1f ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt ); -#else idx = limit_idx_Dwnmix( idx, ( hCPE->hStereoClassif->unclr_decision || ( sts[0]->flag_noisy_speech_snr == 1 && hCPE->hStereoClassif->xtalk_wscore > 0.1f ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt ); -#endif } if ( abs( hStereoTD->tdm_last_ratio_idx - idx ) > LRTD_STEREO_MID_IS_PRIM ) @@ -704,12 +1184,6 @@ int16_t stereo_tdm_ener_analysis( hStereoTD->tdm_last_diff_lt_corr_SM = 0; hStereoTD->tdm_last_ener_lt_R_SM = 0; hStereoTD->tdm_last_ener_lt_L_SM = 0; -#ifdef IVAS_FLOAT_FIXED - hStereoTD->tdm_lt_corr_RM_SM_fx = 167772 /*0.01f Q24*/; - hStereoTD->tdm_lt_corr_LM_SM_fx = 167772 /*0.01f Q24*/; - hStereoTD->tdm_last_ener_lt_R_SM_fx = 0; - hStereoTD->tdm_last_ener_lt_L_SM_fx = 0; -#endif hStereoTD->tdm_noop_mov_flag = 0; hStereoTD->tdm_noop_cnt = 0; @@ -720,49 +1194,7 @@ int16_t stereo_tdm_ener_analysis( hStereoTD->tdm_hyst_cnt_SM = 0; } -#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 ); - - 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 - *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM_fx( hCPE, sts, input_frame, &tdm_NOOP_flag ); -#else *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM( hCPE, sts, input_frame, &tdm_NOOP_flag ); -#endif - -#ifdef IVAS_FLOAT_FIXED - 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 ); - 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 ); - - hStereoTD->tdm_lt_corr_LM_SM = fixedToFloat_32( hStereoTD->tdm_lt_corr_LM_SM_fx, Q24 ); - hStereoTD->tdm_lt_corr_RM_SM = fixedToFloat_32( hStereoTD->tdm_lt_corr_RM_SM_fx, Q24 ); - hStereoTD->tdm_last_diff_lt_corr_SM = fixedToFloat_32( hStereoTD->tdm_last_diff_lt_corr_SM_fx, hStereoTD->q_tdm_last_diff_lt_corr_SM ); -#endif } else { @@ -785,7 +1217,7 @@ int16_t stereo_tdm_ener_analysis( return ( idx ); } - +#endif #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* @@ -1046,7 +1478,7 @@ static Word16 Get_dt_lt_ener_fx( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = BASOP_Util_Add_Mant32Exp( *corr_LM, sub( Q31, *q_corr_LM ), L_negate( *corr_RM ), sub( Q31, *q_corr_RM ), &exp_diff ); move32(); - hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = L_shl( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM], sub( Q21, sub( Q31, exp_diff ) ) ); + hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = L_shl( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM], sub( Q15, sub( Q31, exp_diff ) ) ); // Q15 move32(); IF( sts[0]->hVAD->hangover_cnt != 0 ) @@ -1060,7 +1492,7 @@ static Word16 Get_dt_lt_ener_fx( move32(); } - hCPE->hStereoClassif->xtalk_fv_fx[E_tdm_LT_es_em] = *tdm_LT_es_em; // Q21 + hCPE->hStereoClassif->xtalk_fv_fx[E_tdm_LT_es_em] = L_shr( *tdm_LT_es_em, 6 ); // Q15 move32(); tmp_SM_flag = 0; @@ -2381,7 +2813,129 @@ static int16_t stereo_tdm_ener_analysis_SM( * * Perform the comparison of the 2 sets of LP coefficients *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +/*! r: replication decision; 1 = Use old LP */ +Word16 tdm_lp_comparison_fx( + STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + Encoder_State *st, /* i/o: Encoder structure */ + Word32 *speech_buff, /* i : Current speech frame Q_speech */ + const Word16 *A_PCh_fx, /* i : primary channel LP coefficients Q12*/ + const Word16 *A_SCh_fx, /* i : secondary channel LP coeff. Q12*/ + const Word16 m, /* i : filter length */ + const Word32 *isp_PCh_fx, /* i : primary channel LSPs Q31 */ + const Word32 *isp_SCh_fx, /* i : secondary channel LSPs Q31 */ + const Word16 L_frame, /* i : frame length */ + const Word32 element_brate_wo_meta, /* i : element bitrate without metadata*/ + Word16 Q_speech ) +{ + Word32 ener_sig_fx, pred_gain_reuse_PCh_fx, log10_fx, predgain_SCh_fx; + Word16 LP_mode; + Word32 dist_fx, ftmp_fx; + Word16 i; + Word32 res_fx[L_FRAME16k]; + Word16 gb1 = find_guarded_bits_fx( M ); + + Word32 *speech_fx = &speech_buff[M]; + residu_ivas_fx( A_SCh_fx, Q12, m, speech_fx, res_fx, L_frame ); + + /* Find prediction gain for current LP filter */ + // residu( A_SCh, m, speech, res, L_frame ); + + Word16 gb = find_guarded_bits_fx( L_frame ); + scale_sig32( speech_buff, L_FRAME + M, gb1 ); + Word16 exp = sub( 31, Q_speech ); + Word32 sum2_value = sum2_32_exp_fx( speech_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb + sum2_value = L_add( sum2_value, L_shl( 328, sub( sub( 31, exp ), 15 ) ) ); + Word32 temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); + ener_sig_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25 + // ener_sig = log10f( sum2_f( speech, L_frame ) + 0.01f ); + exp = sub( 31, sub( Q_speech, gb1 ) ); + sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb + sum2_value = L_add( sum2_value, L_shl( 328, sub( sub( 31, exp ), 15 ) ) ); + temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); + log10_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25 + predgain_SCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 ); // Q27+Q25-31 = Q21 + // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) ); + // predgain_SCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) ); + + /* Find prediction gain when resuing the Primary Channel LP filter */ + // residu( A_PCh, m, speech, res, L_frame ); + scale_sig32( speech_buff, L_FRAME + M, negate( gb1 ) ); + residu_ivas_fx( A_PCh_fx, Q12, m, speech_fx, res_fx, L_frame ); + exp = sub( 31, sub( Q_speech, gb1 ) ); + sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb + sum2_value = L_add( sum2_value, L_shl( 328, sub( sub( 31, exp ), 15 ) ) ); + temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); + log10_fx = Mpy_32_32( temp32_log, 646456623 ); // Q25 + + pred_gain_reuse_PCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 ); // Q27+Q25-31 = Q21 + // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) ); + + /* Find Euclidian distance between the 2 filters */ + dist_fx = 0; + move16(); + gb = find_guarded_bits_fx( M ); + FOR( i = 0; i < m; i++ ) + { + // ftmp = isp_SCh[i] - isp_PCh[i]; + ftmp_fx = L_sub( isp_SCh_fx[i], isp_PCh_fx[i] ); + // dist += ftmp * ftmp; + dist_fx = L_add( dist_fx, L_shr( Mpy_32_32( ftmp_fx, ftmp_fx ), gb ) ); // Q31-gb + } + // ener_sig *= 10.0f; + ener_sig_fx = Mpy_32_32( ener_sig_fx, 1342177280 ); // Q27+Q25-31 = Q21 + + /* Verification of the filters similartiies and prediction gain obtained for each channel */ + /* Threshold are more relax if alpha is close to 0.5 (Valid if ICA is used ) */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) ) /* Prediction gain are close & Euclidian dist is small */ + || ( LT_32( predgain_SCh_fx, PG2ND_FX ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) ) /* Prediction gain if the secondary channel is low & Euclidian dist is not too large */ + || ( GE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM - 2 ) ) && LE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM + 2 ) ) && /* ratio between 0.4 and 0.6 */ + ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG2_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) || LT_32( predgain_SCh_fx, PG2ND2_FX ) ) ) /* Prediction gain are not far & Euclidian dist is not too large or Prediction gain if the secondary channel is low */ + || LE_32( ener_sig_fx, 62914560 ) // 30.0f in Q21 + /* secondary channel has low energy */ + ) + { + LP_mode = 1; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + + if ( ( GE_32( element_brate_wo_meta, IVAS_48k ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) ) ) || + ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && LT_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, add( gb, 1 ) ) ) ) ) || + ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && GE_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_LRTD_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb + 2 ) ) ) ) || st->tc_cnt > 0 ) + { + LP_mode = 0; + move16(); + } + } + ELSE + { + /* Prediction or and filters are too different -> quantize the difference*/ + LP_mode = 0; + move16(); + } + return LP_mode; +} +#else /*! r: replication decision; 1 = Use old LP */ int16_t tdm_lp_comparison( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ @@ -2402,7 +2956,6 @@ int16_t tdm_lp_comparison( int16_t LP_mode; float dist, ftmp; int16_t i; - /* Find prediction gain for current LP filter */ residu( A_SCh, m, speech, res, L_frame ); ener_sig = log10f( sum2_f( speech, L_frame ) + 0.01f ); @@ -2447,8 +3000,8 @@ int16_t tdm_lp_comparison( return LP_mode; } - - +#endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * tdm_ol_pitch_comparison() * @@ -2528,7 +3081,108 @@ void tdm_ol_pitch_comparison( return; } +#else +/*-------------------------------------------------------------------* + * tdm_ol_pitch_comparison() + * + * Perform the comparison of the 2 sets of OL pitch + *-------------------------------------------------------------------*/ + +/*! r: replication decision; 1 = Use old LP */ +void tdm_ol_pitch_comparison_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values, Q6 */ + Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15 */ +) +{ + Word16 tmp_diff; + Word16 diff_thr = 6; + Encoder_State *st0, *st1; + move16(); + + st0 = hCPE->hCoreCoder[0]; /* Encoder structure - primary channel */ + st1 = hCPE->hCoreCoder[1]; /* Encoder structure - secondary channel */ + + if ( GT_32( hCPE->element_brate, IVAS_13k2 ) ) + { + diff_thr = 3; + move16(); + } + + test(); + if ( GE_32( hCPE->element_brate, IVAS_48k ) || EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) ) + { + diff_thr = 1; + move16(); + } + + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( st0->sp_aud_decision1 == 0 && st0->sp_aud_decision2 == 0 ) && /* Pitch is not recycled in case of music coding*/ + ( LE_32( hCPE->element_brate, IVAS_16k4 ) || ( LE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( st0->coder_type, VOICED ) && EQ_16( st1->coder_type, VOICED ) ) ) ) || + LT_32( hCPE->element_brate, IVAS_13k2 ) ) + { + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + Word16 voicmin[4]; + + minimum_fx( st0->voicing_fx, 3, voicmin ); + minimum_fx( st1->voicing_fx, 3, voicmin + 1 ); + minimum_fx( voicing_fr[0], 4, voicmin + 2 ); + minimum_fx( voicing_fr[1], 4, voicmin + 3 ); + tmp_diff = 10; + move16(); + + test(); + test(); + test(); + IF( GE_16( voicmin[0], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[1], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[2], 27853 /* 0.85f in Q15 */ ) && GE_16( voicmin[3], 27853 /* 0.85f in Q15 */ ) ) + { + tmp_diff = add( abs_s( sub( st0->pitch[0], st1->pitch[0] ) ), add( abs_s( sub( st0->pitch[1], st1->pitch[1] ) ), abs_s( sub( st0->pitch[2], st1->pitch[2] ) ) ) ); + } + } + ELSE + { + tmp_diff = abs_s( sub( add( st0->pitch[0], add( st0->pitch[1], st0->pitch[2] ) ), add( st1->pitch[0], add( st1->pitch[1], st1->pitch[2] ) ) ) ); + } + + IF( LE_16( tmp_diff, diff_thr ) ) + { + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 1; + move16(); + + /* 1/4 pitch precision update*/ + Copy( st0->pitch, st1->pitch, 3 ); + Copy( st0->voicing_fx, st1->voicing_fx, 3 ); + + /* Update some parameters accordingly */ + st1->old_corr_fx = st0->old_corr_fx; + st1->old_thres_fx = st0->old_thres_fx; + st1->delta_pit = st0->delta_pit; + move16(); + move16(); + move16(); + + /* Updates for adaptive lag window memory */ + st1->old_pitch_la = st0->old_pitch_la; + move16(); + /* 1/4 pitch precision update*/ + Copy( pitch_fr[0], pitch_fr[1], NB_SUBFR ); + Copy( voicing_fr[0], voicing_fr[1], NB_SUBFR ); + } + } + + return; +} +#endif #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index 6a5866ef52c3f0487d69b72c1759ca1b37d28994..346c78d638c22cee5f9a8cb182888078362bc3a8 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -42,6 +42,12 @@ #ifdef DEBUGGING #include "debug.h" #endif +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "ivas_prot_fx.h" +#include "prot_fx.h" +#include "ivas_rom_com_fx.h" +#endif /*-------------------------------------------------------------------* @@ -49,7 +55,7 @@ * * Initialize TD stereo encoder *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void stereo_td_init_enc( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ const int16_t last_element_mode /* i : last element mode */ @@ -132,85 +138,149 @@ void stereo_td_init_enc( return; } - +#endif void stereo_td_init_enc_fx( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */ const Word16 last_element_mode /* i : last element mode */ ) { - hStereoTD->tdm_lt_corr_RM_fx = 21474836; // Q31 - hStereoTD->tdm_lt_corr_LM_fx = 21474836; + hStereoTD->tdm_lt_corr_RM_fx = 167772; // Q24 + move32(); + hStereoTD->tdm_lt_corr_LM_fx = 167772; // Q24 + move32(); hStereoTD->tdm_last_ratio_fx = 1073741824; // Q31 + move32(); hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM; - hStereoTD->tdm_lt_rms_L_fx = 671088640; // Q24 - hStereoTD->tdm_lt_rms_R_fx = 671088640; // Q24 + move16(); + hStereoTD->tdm_lt_rms_L_fx = 2621440; // Q16 + move32(); + hStereoTD->tdm_lt_rms_R_fx = 2621440; // Q16 + move32(); hStereoTD->tdm_last_diff_lt_corr_fx = 0; + move32(); hStereoTD->q_tdm_last_diff_lt_corr = Q31; + move16(); hStereoTD->tdm_last_ener_lt_R_fx = 0; + move32(); hStereoTD->tdm_last_ener_lt_L_fx = 0; + move32(); hStereoTD->tdm_ratio_transition_mov_flag = 0; + move16(); hStereoTD->tdm_ratio_transition_cnt = 0; + move16(); hStereoTD->tdm_noop_mov_flag = 0; + move16(); hStereoTD->tdm_noop_cnt = 0; + move16(); hStereoTD->tdm_last_SM_flag = 0; + move16(); hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_FD2LRTD_SW_cnt = 0; - hStereoTD->tdm_LT_es_em_fx = 214748364; // Q31 + move16(); + hStereoTD->tdm_LT_es_em_fx = 209715; // Q21 + move32(); hStereoTD->tdm_hyst_cnt = 0; + move16(); /* NOOP parameters */ - hStereoTD->tdm_lt_corr_RM_SM_fx = 21474836; // Q31 - hStereoTD->tdm_lt_corr_LM_SM_fx = 21474836; // Q31 + hStereoTD->tdm_lt_corr_RM_SM_fx = 167772 /*0.01f Q24*/; + move32(); + hStereoTD->tdm_lt_corr_LM_SM_fx = 167772 /*0.01f Q24*/; hStereoTD->tdm_last_ratio_SM_fx = 1073741824; // Q31 + move32(); hStereoTD->tdm_last_ratio_idx_SM = 0; - hStereoTD->tdm_lt_rms_L_SM_fx = 671088640; // Q24 - hStereoTD->tdm_lt_rms_R_SM_fx = 671088640; // Q24 + move16(); + hStereoTD->q_tdm_last_diff_lt_corr_SM = Q31; + move16(); + hStereoTD->tdm_lt_rms_L_SM_fx = 2621440; // Q16 + move32(); + hStereoTD->tdm_lt_rms_R_SM_fx = 2621440; // Q16 + move32(); hStereoTD->tdm_last_diff_lt_corr_SM_fx = 0; + move32(); hStereoTD->q_tdm_last_diff_lt_corr_SM = Q31; + move16(); hStereoTD->tdm_last_ener_lt_R_SM_fx = 0; + move32(); hStereoTD->tdm_last_ener_lt_L_SM_fx = 0; + move32(); hStereoTD->tdm_noop_mov_flag = 0; + move16(); hStereoTD->tdm_NOOP_cnt = 0; + move16(); hStereoTD->tdm_last_SM_flag_noop = 0; + move16(); hStereoTD->tdm_last_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_prev_stable_idx_SM = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_prev_desired_idx_SM = LRTD_STEREO_MID_IS_PRIM; - hStereoTD->tdm_LT_es_em_SM_fx = 214748364; // Q31 + move16(); + hStereoTD->tdm_LT_es_em_SM_fx = 209715; // Q21 + move32(); hStereoTD->tdm_hyst_cnt_SM = 0; + move16(); hStereoTD->tdm_noop_cnt = 0; + move16(); hStereoTD->tdm_SM_flag = 0; + move16(); hStereoTD->tdm_SM_last_clas[0] = VOICED_CLAS; + move16(); hStereoTD->tdm_SM_last_clas[1] = VOICED_CLAS; + move16(); hStereoTD->tdm_SM_last2_clas[0] = VOICED_CLAS; + move16(); hStereoTD->tdm_SM_last2_clas[1] = VOICED_CLAS; + move16(); hStereoTD->tdm_SM_modi_flag = 0; + move16(); hStereoTD->tdm_SM_reset_flag = 0; + move16(); hStereoTD->prev_fr_LRTD_TD_dec = 0; + move16(); hStereoTD->tdm_LRTD_flag = 0; + move16(); hStereoTD->tdm_inst_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM; + move16(); hStereoTD->tdm_last_inst_ratio_idx = LRTD_STEREO_MID_IS_PRIM; + move16(); hStereoTD->tdm_last_LRTD_frame_cnt = 0; + move16(); hStereoTD->tdm_vad_hangover_cnt = 0; + move16(); hStereoTD->tdm_ini_frame_cnt = 0; + move16(); hStereoTD->tdm_last_LRTD_PriCh_cnt = 0; + move16(); hStereoTD->flag_skip_DMX = 0; + move16(); IF( EQ_16( last_element_mode, IVAS_CPE_MDCT ) ) { hStereoTD->flag_skip_DMX = 1; + move16(); hStereoTD->prev_fr_LRTD_TD_dec = 1; + move16(); hStereoTD->tdm_last_ratio_fx = MAX_32; // Q31 + move32(); hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_LEFT_IS_PRIM; + move16(); } hStereoTD->tdm_hBstr_tmp.ind_list = hStereoTD->tdm_ind_list_tmp; hStereoTD->tdm_hBstr_tmp.ivas_ind_list_zero = (Indice **) ( &hStereoTD->tdm_hBstr_tmp.ind_list ); hStereoTD->max_ind_tdm_tmp = MAX_IND_TDM_TMP; + move32(); hStereoTD->tdm_hBstr_tmp.ivas_max_num_indices = &hStereoTD->max_ind_tdm_tmp; hStereoTD->tdm_hBstr_tmp.st_ivas = NULL; reset_indices_enc( &hStereoTD->tdm_hBstr_tmp, MAX_IND_TDM_TMP ); @@ -218,6 +288,184 @@ void stereo_td_init_enc_fx( return; } +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * stereo_set_tdm() + * + * Set TD stereo encoder parameters + *-------------------------------------------------------------------*/ + +ivas_error stereo_set_tdm_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 input_frame, /* i : input frame length per channel */ + Word16 input_q ) +{ + Encoder_State **sts; + sts = hCPE->hCoreCoder; + ivas_error error; + + error = IVAS_ERR_OK; + + /* initialize TD stereo parameters */ + IF( hCPE->hStereoTD != NULL ) + { + hCPE->hStereoTD->tdm_lp_reuse_flag = 0; + move16(); + hCPE->hStereoTD->tdm_low_rate_mode = 0; + move16(); + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0; + move16(); + + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + /* initialize this flag when uncorrelated L&R channels have been detected in the previous frame */ + test(); + test(); + IF( EQ_16( hCPE->hStereoTD->prev_fr_LRTD_TD_dec, 1 ) || NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || LT_16( hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt, 5 ) ) + { + hCPE->hStereoTD->tdm_LRTD_flag = 1; + move16(); + } + ELSE + { + hCPE->hStereoTD->tdm_LRTD_flag = 0; + move16(); + } + } + ELSE + { + hCPE->hStereoTD->tdm_LRTD_flag = hCPE->hStereoTD->prev_fr_LRTD_TD_dec; + move16(); + } + +#ifdef DEBUG_MODE_INFO + dbgwrite( &hCPE->hStereoTD->tdm_LRTD_flag, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); +#endif + + + /* normal TD / LRTD switching */ + IF( EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 0 ) ) + { + Encoder_State *st; + st = hCPE->hCoreCoder[1]; + + /* deallocate CLDFB ana for secondary channel */ + IF( st->cldfbAnaEnc != NULL ) + { + deleteCldfb_ivas( &st->cldfbAnaEnc ); + } + + /* deallocate BWEs for secondary channel */ + IF( st->hBWE_TD != NULL ) + { + IF( st->hBWE_TD != NULL ) + { + free( st->hBWE_TD ); + st->hBWE_TD = NULL; + } + + deleteCldfb_ivas( &st->cldfbSynTd ); + + IF( st->hBWE_FD != NULL ) + { + free( st->hBWE_FD ); + st->hBWE_FD = NULL; + } + } + + /* allocate ICBWE structure */ + IF( hCPE->hStereoICBWE == NULL ) + { + IF( ( hCPE->hStereoICBWE = (STEREO_ICBWE_ENC_HANDLE) malloc( sizeof( STEREO_ICBWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE \n" ) ); + } +#ifdef IVAS_FLOAT_FIXED + stereo_icBWE_init_enc_fx( hCPE->hStereoICBWE ); +#endif + stereo_icBWE_init_enc( hCPE->hStereoICBWE ); + } + } + ELSE /* tdm_LRTD_flag == 1 */ + { + Encoder_State *st; + st = hCPE->hCoreCoder[1]; + + /* deallocate ICBWE structure */ + IF( hCPE->hStereoICBWE != NULL ) + { + free( hCPE->hStereoICBWE ); + hCPE->hStereoICBWE = NULL; + } + + /* allocate CLDFB ana for secondary channel */ + IF( st->cldfbAnaEnc == NULL ) + { + IF( NE_32( ( error = openCldfb_ivas_enc( &st->cldfbAnaEnc, CLDFB_ANALYSIS, st->input_Fs, CLDFB_PROTOTYPE_1_25MS ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* allocate BWEs for secondary channel */ + IF( st->hBWE_TD == NULL ) + { + IF( ( st->hBWE_TD = (TD_BWE_ENC_HANDLE) malloc( sizeof( TD_BWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n" ) ); + } + IF( NE_32( ( error = openCldfb_ivas_enc( &st->cldfbSynTd, CLDFB_SYNTHESIS, 16000, CLDFB_PROTOTYPE_1_25MS ) ), IVAS_ERR_OK ) ) + { + return error; + } + + InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif + ResetSHBbuffer_Enc( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + ResetSHBbuffer_Enc_fx( st ); +#endif + + IF( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); + } + +#ifdef IVAS_FLOAT_FIXED + fd_bwe_enc_init_fx( st->hBWE_FD ); +#endif + fd_bwe_enc_init( st->hBWE_FD ); + } + } + + IF( hCPE->hStereoClassif->lrtd_mode == 0 ) + { + hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = 0; + move16(); + } + hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = s_min( 100, hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt + 1 ); + move16(); + stereo_tdm_prep_dwnmx_fx( hCPE, sts[1]->input32_fx, input_frame, input_q ); + } + ELSE + { +#ifdef DEBUG_MODE_INFO + { + int16_t tmp = -2; + dbgwrite( &tmp, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + } +#endif + hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; + move16(); + hCPE->hCoreCoder[1]->tdm_LRTD_flag = 0; + move16(); + } + + return error; +} +#else /*-------------------------------------------------------------------* * stereo_set_tdm() * @@ -347,6 +595,9 @@ ivas_error stereo_set_tdm( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) @@ -354,39 +605,385 @@ ivas_error stereo_set_tdm( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n" ) ); } - fd_bwe_enc_init( st->hBWE_FD ); - } + fd_bwe_enc_init( st->hBWE_FD ); + } + } + + if ( hCPE->hStereoClassif->lrtd_mode == 0 ) + { + hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = 0; + } + hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = min( 100, hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt + 1 ); + stereo_tdm_prep_dwnmx( hCPE, sts[1]->input, input_frame ); + } + else + { +#ifdef DEBUG_MODE_INFO + { + int16_t tmp = -2; + dbgwrite( &tmp, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + } +#endif + hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; + hCPE->hCoreCoder[1]->tdm_LRTD_flag = 0; + } + + return error; +} + +#endif +/*-------------------------------------------------------------------* + * tdm_configure_enc() + * + * Configure TD stereo encoder + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void tdm_configure_enc_fx( + const Word16 ivas_format, /* i : IVAS format */ + const Word16 ism_mode, /* i : ISM mode in combined format */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 Etot_last_fx[CPE_CHANNELS], /* i/o: Energy of last frame Q8*/ + const Word16 tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const Word16 tdm_ratio_idx, /* i : ratio index */ + const Word16 tdm_ratio_idx_SM, /* i : ratio index in SM mode */ + const Word16 attack_flag, /* i : Primary channel attack flag */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +) +{ + Word16 tdm_ratio_bit_alloc_idx, mod_ct; + STEREO_TD_ENC_DATA_HANDLE hStereoTD; + Encoder_State **sts; + Word16 loc_coder_tyape_raw0; + hStereoTD = hCPE->hStereoTD; + sts = hCPE->hCoreCoder; + loc_coder_tyape_raw0 = sts[0]->coder_type_raw; + move16(); + + /*----------------------------------------------------------------* + * Overwrite certain decisions depending on the input + *----------------------------------------------------------------*/ + + hStereoTD->tdm_use_IAWB_Ave_lpc = 0; /* Flag initialisation */ + move16(); + sts[0]->hSpMusClas->tdm_lt_Etot_fx = add( mult( 3277 /*0.1f in Q15*/, Etot_last_fx[0] ), mult( 29491 /* 0.9f*/, sts[0]->hSpMusClas->tdm_lt_Etot_fx ) ); + move16(); + sts[1]->hSpMusClas->tdm_lt_Etot_fx = add( mult( 3277 /*0.1f in Q15*/, Etot_last_fx[1] ), mult( 29491 /* 0.9f*/, sts[1]->hSpMusClas->tdm_lt_Etot_fx ) ); + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( hCPE->hStereoClassif->lrtd_mode == 0 && ( ( sts[1]->hSpMusClas->tdm_lt_Etot_fx < 0 && hCPE->hCoreCoder[1]->vad_flag == 0 ) /* very clean signal */ + || ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) ) ) + { + sts[1]->coder_type = INACTIVE; + move16(); + + test(); + if ( hStereoTD->tdm_lp_reuse_flag == 0 && hCPE->hCoreCoder[0]->vad_flag != 0 ) + { + hStereoTD->tdm_use_IAWB_Ave_lpc = 1; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + } + ELSE IF( ( ( hCPE->hCoreCoder[1]->vad_flag == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 && LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) && ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) /* && NO_DTX */ ) /* boths channels are inactive but not DTX used*/ + { + sts[1]->coder_type = INACTIVE; + move16(); + IF( GT_16( tdm_ratio_idx, 1 ) && LT_16( tdm_ratio_idx, 29 ) ) + { + if ( hStereoTD->tdm_lp_reuse_flag == 0 && hCPE->hCoreCoder[0]->vad_flag != 0 ) + { + hStereoTD->tdm_use_IAWB_Ave_lpc = 1; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + } + } + ELSE IF( !( sts[1]->sp_aud_decision0 ) && sts[1]->tc_cnt <= 0 && ( EQ_16( sts[1]->coder_type_raw, UNVOICED ) || ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && hStereoTD->tdm_lp_reuse_flag == 0 && ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) ) ) ) + { + sts[1]->coder_type = UNVOICED; + move16(); + if ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + hStereoTD->tdm_lp_reuse_flag = 0; + move16(); + } + } + ELSE IF( ( LT_16( sts[1]->coder_type, AUDIO ) && NE_16( sts[1]->coder_type, UNVOICED ) ) || /* TC and VC are not supported in secondary channel */ + ( ( EQ_16( sts[1]->coder_type, AUDIO ) && LE_32( hCPE->element_brate, IVAS_24k4 ) ) || ( EQ_16( sts[0]->sp_aud_decision1, 1 ) && GE_32( hCPE->element_brate, IVAS_16k4 ) ) || ( EQ_16( sts[1]->sp_aud_decision0, 1 ) && GE_32( hCPE->element_brate, IVAS_13k2 ) ) ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + ELSE IF( EQ_16( sts[1]->coder_type, GENERIC ) && EQ_16( sts[1]->coder_type_raw, UNVOICED ) ) + { + hStereoTD->tdm_lp_reuse_flag = 0; + move16(); + } + + test(); + IF( GE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + if ( EQ_16( sts[1]->coder_type, UNVOICED ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + + IF( EQ_16( sts[0]->coder_type, UNVOICED ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + loc_coder_tyape_raw0 = GENERIC; + move16(); + } + } + test(); + test(); + IF( GE_32( hCPE->element_brate, IVAS_24k4 ) && hCPE->hStereoClassif->lrtd_mode == 0 && EQ_16( sts[0]->coder_type, UNVOICED ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + loc_coder_tyape_raw0 = GENERIC; + move16(); + } + + if ( NE_16( sts[1]->coder_type, GENERIC ) ) + { + hStereoTD->tdm_Pitch_reuse_flag = 0; + move16(); + } + + IF( attack_flag != 0 ) + { + if ( sts[1]->coder_type != INACTIVE ) + { + hStereoTD->tdm_lp_reuse_flag = 0; /* Do not allow the LP filter reusing on TC or attack in the primary channel */ + move16(); + } + } + test(); + IF( tdm_SM_or_LRTD_Pri && hStereoTD->tdm_LRTD_flag == 0 ) + { + tdm_ratio_bit_alloc_idx = tdm_ratio_idx_SM; + move16(); + } + ELSE + { + tdm_ratio_bit_alloc_idx = tdm_ratio_idx; + move16(); + } + test(); + test(); + test(); + test(); + if ( ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && GE_16( sts[1]->coder_type, UNVOICED ) && GT_16( abs_s( sub( hStereoTD->tdm_last_ratio_idx, tdm_ratio_bit_alloc_idx ) ), 15 ) ) /* channel inversion in lrtd */ + || ( LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 4 ) && LT_16( hStereoTD->tdm_last_LRTD_frame_cnt, 4 ) ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + + IF( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 12000 ) ) + { + if ( EQ_16( sts[1]->coder_type, UNVOICED ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + + if ( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 11000 ) ) + { + sts[1]->coder_type = INACTIVE; + move16(); + } + } + + IF( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 14700 ) ) + { + if ( EQ_16( sts[0]->coder_type, TRANSITION ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + } + } + + mod_ct = AUDIO; + move16(); + IF( LT_32( hCPE->element_brate, IVAS_24k4 ) ) + { + mod_ct = sts[0]->coder_type; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + /* Only sure TRANSITION coding modes are important for bit allocation, otherwise mod_ct is set to AUDIO only to easy debugging if needed */ + IF( ( ( GE_16( sts[0]->last_L_frame, L_FRAME16k ) && EQ_16( sts[0]->flag_ACELP16k, 0 ) ) || ( EQ_16( sts[0]->last_L_frame, L_FRAME ) && EQ_16( sts[0]->flag_ACELP16k, 1 ) ) ) && NE_32( sts[0]->last_core_brate, FRAME_NO_DATA ) && NE_32( sts[0]->last_core_brate, SID_2k40 ) && NE_32( sts[0]->coder_type_raw, VOICED ) /*in case of CNG, this code is not reached sts[0]->core_brate != FRAME_NO_DATA && sts[0]->core_brate != SID_2k40 &&*/ ) + { + mod_ct = TRANSITION; + move16(); + } + ELSE IF( EQ_16( sts[0]->sp_aud_decision1, 1 ) || EQ_16( sts[0]->sp_aud_decision2, 1 ) || NE_16( mod_ct, TRANSITION ) ) + { + mod_ct = AUDIO; + move16(); + } + } + + /* Correction of tdm_inst_ratio_idx in case of TC in the seecondary channel */ + test(); + test(); + IF( hStereoTD->flag_skip_DMX == 0 && EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && GT_16( sts[1]->tc_cnt, 1 ) /*&& abs(hStereoTD->tdm_inst_ratio_idx-LRTD_STEREO_MID_IS_PRIM) > 5*/ ) + { + IF( tdm_SM_or_LRTD_Pri == 0 ) /* Primary is right */ + { + hStereoTD->tdm_inst_ratio_idx = add( hStereoTD->tdm_inst_ratio_idx, LRTD_STEREO_QUARTER_RANGE ); + move16(); + } + ELSE IF( EQ_16( tdm_SM_or_LRTD_Pri, 1 ) ) /* Primary is left */ + { + hStereoTD->tdm_inst_ratio_idx = sub( hStereoTD->tdm_inst_ratio_idx, LRTD_STEREO_QUARTER_RANGE ); + move16(); } + hStereoTD->tdm_inst_ratio_idx = check_bounds_s_fx( hStereoTD->tdm_inst_ratio_idx, 8, 22 ); + move16(); + } - if ( hCPE->hStereoClassif->lrtd_mode == 0 ) + /*----------------------------------------------------------------* + * bitbudget distribution between channels (taking into account also metadata bitbudget) + *----------------------------------------------------------------*/ + + tdm_bit_alloc( ivas_format, ism_mode, L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), + hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), + &( hStereoTD->tdm_low_rate_mode ), sts[1]->coder_type, tdm_ratio_bit_alloc_idx, hStereoTD->tdm_Pitch_reuse_flag, + sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, hStereoTD->tdm_inst_ratio_idx ); + test(); + if ( sts[0]->GSC_IVAS_mode > 0 && LE_32( sts[0]->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) ) + { + sts[0]->GSC_IVAS_mode = 0; + move16(); + } + test(); + test(); + if ( sts[1]->GSC_IVAS_mode > 0 && ( LE_32( sts[1]->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) || EQ_16( hStereoTD->tdm_low_rate_mode, 1 ) ) ) + { + sts[1]->GSC_IVAS_mode = 0; + move16(); + } + test(); + IF( EQ_16( sts[0]->coder_type, GENERIC ) && EQ_16( loc_coder_tyape_raw0, UNVOICED ) ) + { + if ( LT_32( sts[0]->total_brate, MAX_UNVOICED_BRATE ) ) { - hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = 0; + sts[0]->coder_type = UNVOICED; + move16(); } - hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt = min( 100, hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt + 1 ); - stereo_tdm_prep_dwnmx( hCPE, sts[1]->input, input_frame ); } - else + + /*----------------------------------------------------------------* + * Bitstream writing + *----------------------------------------------------------------*/ + + /* transmit the ratio index */ + test(); + IF( tdm_SM_or_LRTD_Pri && hStereoTD->tdm_LRTD_flag == 0 ) { -#ifdef DEBUG_MODE_INFO + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, tdm_ratio_idx_SM, TDM_RATIO_BITS ); + } + ELSE + { + IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) { - int16_t tmp = -2; - dbgwrite( &tmp, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, hStereoTD->tdm_inst_ratio_idx, TDM_RATIO_BITS ); + } + ELSE + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, tdm_ratio_idx, TDM_RATIO_BITS ); } -#endif - hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; - hCPE->hCoreCoder[1]->tdm_LRTD_flag = 0; } - return error; -} + /* LPC reuse flag */ + test(); + test(); + IF( sts[1]->coder_type == INACTIVE && LT_16( tdm_ratio_idx, 29 ) && GT_16( tdm_ratio_idx, 1 ) ) + { + /* normal TD, tdm_lp_reuse_flag always on, tdm_use_IAWB_Ave_lpc varies tdm_ratio_idx<29 && tdm_ratio_idx> 1*/ + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LPC_REUSE, hStereoTD->tdm_use_IAWB_Ave_lpc, TDM_LP_REUSE_BITS ); + } + ELSE + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LPC_REUSE, hStereoTD->tdm_lp_reuse_flag, TDM_LP_REUSE_BITS ); + } + /* LRTD flag */ + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LRTD_FLAG, hStereoTD->tdm_LRTD_flag, TDM_LR_CONTENT_BITS ); -/*-------------------------------------------------------------------* - * tdm_configure_enc() - * - * Configure TD stereo encoder - *-------------------------------------------------------------------*/ + /* Stereo ICA parameters */ + IF( hStereoTD->tdm_LRTD_flag == 0 ) + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_REFCHAN, hCPE->hStereoTCA->refChanIndx, STEREO_BITS_TCA_CHAN ); + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_CORRSTATS, hCPE->hStereoTCA->indx_ica_NCShift, STEREO_BITS_TCA_CORRSTATS ); + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_GD, hCPE->hStereoTCA->indx_ica_gD, STEREO_BITS_TCA_GD ); + } + + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + hStereoTD->tdm_last_ratio_idx = tdm_ratio_idx; + move16(); + hStereoTD->tdm_last_ratio_idx_SM = tdm_ratio_idx_SM; + move16(); + hStereoTD->tdm_last_SM_flag = tdm_SM_or_LRTD_Pri; + move16(); + + if ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + hStereoTD->tdm_last_SM_flag = 0; + move16(); + } + hStereoTD->tdm_last_inst_ratio_idx = hStereoTD->tdm_inst_ratio_idx; + move16(); + + return; +} +#else void tdm_configure_enc( const int16_t ivas_format, /* i : IVAS format */ const int16_t ism_mode, /* i : ISM mode in combined format */ @@ -643,7 +1240,7 @@ void tdm_configure_enc( return; } - +#endif /*-------------------------------------------------------------------* * signaling_enc_secondary() @@ -762,7 +1359,7 @@ ivas_error signaling_enc_secondary( * * downmix Left+Right to Primary+Secondary channel *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void tdm_downmix_plain( float FR_Y[], /* o : primary channel */ float LR_X[], /* o : secondary channel */ @@ -784,13 +1381,40 @@ static void tdm_downmix_plain( return; } +#endif + +#ifdef IVAS_FLOAT_FIXED +static void tdm_downmix_plain_ivas_fx( + Word16 FR_Y_fx[], /*Qx*/ + Word16 LR_X_fx[], /*Qx*/ + const Word16 Left_in_fx[], /*Qx*/ + const Word16 Right_in_fx[], /*Qx*/ + const Word32 ratio_L_fx, /* Q31 */ + const Word32 One_m_Ratio_fx, /* Q31 */ + const Word16 start_index, /* i : start index */ + const Word16 end_index /* i : end index */ +) +{ + Word16 i; + + FOR( i = start_index; i < end_index; i++ ) + { + FR_Y_fx[i] = add( mult( Right_in_fx[i], extract_h( One_m_Ratio_fx ) ), mult( Left_in_fx[i], extract_h( ratio_L_fx ) ) ); + LR_X_fx[i] = sub( mult( Left_in_fx[i], extract_h( One_m_Ratio_fx ) ), mult( Right_in_fx[i], extract_h( ratio_L_fx ) ) ); + move16(); + move16(); + } + + return; +} +#endif /*-------------------------------------------------------------------* * Function tdm_downmix_fade() * * downmix Left+Right to Primary+Secondary channel with fade in/out *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void tdm_downmix_fade( float FR_Y[], /* o : primary channel */ float LR_X[], /* o : secondary channel */ @@ -822,13 +1446,56 @@ static void tdm_downmix_fade( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +static void tdm_downmix_fade_ivas_fx( + Word16 FR_Y_fx[], /* o : primary channel Qx */ + Word16 LR_X_fx[], /* o : secondary channel Qx */ + const Word16 Left_in_fx[], /* i : Left channel Qx */ + const Word16 Right_in_fx[], /* i : Right channel Qx */ + const Word32 ratio_L_fx, /* i : mixing ratio Q31 */ + const Word32 One_m_Ratio_fx, /* i : 1 - mixing ratio Q31 */ + const Word32 OldRatio_L_fx, /* i : old mixing ratio Q31 */ + const Word32 One_m_OldRatio_fx, /* i : 1 - old mixing ratio Q31 */ + const Word16 start_index, /* i : start index */ + const Word16 end_index /* i : end index */ +) +{ + Word16 i; + Word16 step_fx, fade_in_fx, fade_out_fx, scale; + + step_fx = BASOP_Util_Divide1616_Scale( 1, sub( end_index, start_index ), &scale ); + step_fx = shl( step_fx, scale ); // Q15 + fade_out_fx = 32767; + fade_in_fx = 0; + move16(); + move16(); + + FOR( i = start_index; i < end_index; i++ ) + { + FR_Y_fx[i] = add( mult( add( mult( Right_in_fx[i], extract_l( One_m_OldRatio_fx ) ), mult( Left_in_fx[i], extract_l( OldRatio_L_fx ) ) ), fade_out_fx ), mult( add( mult( Right_in_fx[i], extract_l( One_m_Ratio_fx ) ), mult( Left_in_fx[i], extract_l( ratio_L_fx ) ) ), fade_in_fx ) ); // Qx + LR_X_fx[i] = add( mult( sub( mult( Left_in_fx[i], extract_l( One_m_OldRatio_fx ) ), mult( Right_in_fx[i], extract_l( OldRatio_L_fx ) ) ), fade_out_fx ), + mult( sub( mult( Left_in_fx[i], extract_l( One_m_Ratio_fx ) ), mult( Right_in_fx[i], extract_l( ratio_L_fx ) ) ), + fade_in_fx ) ); // Qx + move16(); + move16(); + + + fade_in_fx = add( fade_in_fx, step_fx ); + fade_out_fx = sub( fade_out_fx, step_fx ); + } + + return; +} +#endif + /*-------------------------------------------------------------------* * Function stereo_tdm_downmix() * * Compute the TD stereo downmix signal based on the ratio index *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void stereo_tdm_downmix( STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i : TD stereo IVAS encoder structure */ float *Left_in, /* i/o: Left channel -> Primary channel */ @@ -937,7 +1604,189 @@ void stereo_tdm_downmix( return; } +#endif +#ifdef IVAS_FLOAT_FIXED +void stereo_tdm_downmix_ivas_fx( + STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i : TD stereo IVAS encoder structure */ + Word16 *Left_in_fx, /* Qx */ + Word16 *Right_in_fx, /* Qx */ + const Word16 input_frame, /* i : Number of samples */ + const Word16 tdm_ratio_idx, /* i : TDM ratio index */ + const Word16 tdm_SM_flag, /* i : channel combination scheme flag */ + const Word16 tdm_ratio_idx_SM /* i : TDM ratio index for SM mode */ +) +{ + Word16 FR_Y_fx[L_FRAME48k], LR_X_fx[L_FRAME48k]; + Word16 i, tdm_n_OVA; + Word16 stereo_tdm_coder_type; + + tdm_n_OVA = NS2SA_FX2( L_mult0( input_frame, FRAMES_PER_SEC ), TDM_L_NOVA_NS ); + move16(); + + IF( hStereoTD->flag_skip_DMX ) + { + stereo_tdm_coder_type = 10; /* no DMX */ + move16(); + + Copy( Left_in_fx, FR_Y_fx, input_frame ); + Copy( Right_in_fx, LR_X_fx, input_frame ); + } + ELSE IF( EQ_16( tdm_SM_flag, 1 ) ) + { + IF( hStereoTD->tdm_last_SM_flag == 0 ) + { + stereo_tdm_coder_type = 0; /* mode 1 : Switching from YX scheme to SM scheme*/ + move16(); + } + ELSE + { + stereo_tdm_coder_type = 1; /* mode 2 : SM scheme*/ + move16(); + } + } + ELSE + { + IF( EQ_16( hStereoTD->tdm_last_SM_flag, 1 ) ) + { + stereo_tdm_coder_type = 2; /* mode 3 : Switching from SM scheme to YX scheme*/ + move16(); + } + ELSE + { + stereo_tdm_coder_type = 3; /* mode 4 : YX scheme*/ + move16(); + } + } + + SWITCH( stereo_tdm_coder_type ) + { + case ( 0 ): + { + /* Switching from YX scheme to SM scheme */ + tdm_downmix_fade_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx_SM], L_sub( tdm_ratio_tabl_fx[tdm_ratio_idx_SM], 2147483647 ), hStereoTD->tdm_last_ratio_fx, L_sub( 2147483647, hStereoTD->tdm_last_ratio_fx ), 0, tdm_n_OVA ); // 1.0 in Q31 -> 2147483647 + + /* Create new mixture of using the ratio computed above and formular for SM scheme */ + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx_SM], L_sub( tdm_ratio_tabl_fx[tdm_ratio_idx_SM], 2147483647 ), tdm_n_OVA, input_frame ); // 1.0 in Q31 -> 2147483647 + } + BREAK; + case ( 1 ): + { + /* Create new mixture of using the ratio computed above and formular for SM scheme */ + IF( EQ_32( tdm_ratio_tabl_fx[tdm_ratio_idx_SM], hStereoTD->tdm_last_ratio_SM_fx ) ) + { + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx_SM], L_sub( (Word32) tdm_ratio_tabl_fx[tdm_ratio_idx_SM], 2147483647 ), 0, input_frame ); // 1.0 in Q31 -> 2147483647 + } + ELSE + { + tdm_downmix_fade_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx_SM], L_sub( tdm_ratio_tabl_fx[tdm_ratio_idx_SM], 2147483647 ), hStereoTD->tdm_last_ratio_SM_fx, L_sub( hStereoTD->tdm_last_ratio_SM_fx, 2147483647 ), 0, tdm_n_OVA ); // 1.0 in Q31 -> 2147483647 + + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx_SM], L_sub( tdm_ratio_tabl_fx[tdm_ratio_idx_SM], 2147483647 ), tdm_n_OVA, input_frame ); // 1.0 in Q31 -> 2147483647 + } + } + BREAK; + case ( 2 ): + { + /* Switching from SM scheme to YX scheme */ + tdm_downmix_fade_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx], L_sub( 2147483647, tdm_ratio_tabl_fx[tdm_ratio_idx] ), hStereoTD->tdm_last_ratio_SM_fx, L_sub( hStereoTD->tdm_last_ratio_SM_fx, 2147483647 ), 0, tdm_n_OVA ); // 1.0 in Q31 -> 2147483647 + + /* Create new mixture of using the ratio computed above and formular for YX scheme */ + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx], L_sub( 2147483647, tdm_ratio_tabl_fx[tdm_ratio_idx] ), tdm_n_OVA, input_frame ); // 1.0 in Q31 -> 2147483647 + } + BREAK; + case ( 3 ): + { + /* Create new mixture of using the ratio computed above and formular for YX scheme */ + IF( EQ_32( tdm_ratio_tabl_fx[tdm_ratio_idx], + hStereoTD->tdm_last_ratio_fx ) ) + { + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx], L_sub( 2147483647, tdm_ratio_tabl_fx[tdm_ratio_idx] ), 0, input_frame ); // 1.0 in Q31 -> 2147483647 + } + ELSE + { + tdm_downmix_fade_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx], L_sub( 2147483647, tdm_ratio_tabl_fx[tdm_ratio_idx] ), hStereoTD->tdm_last_ratio_fx, L_sub( 2147483647, hStereoTD->tdm_last_ratio_fx ), 0, tdm_n_OVA ); // 1.0 in Q31 -> 2147483647 + + tdm_downmix_plain_ivas_fx( FR_Y_fx, LR_X_fx, Left_in_fx, Right_in_fx, tdm_ratio_tabl_fx[tdm_ratio_idx], L_sub( 2147483647, tdm_ratio_tabl_fx[tdm_ratio_idx] ), tdm_n_OVA, input_frame ); // 1.0 in Q31 -> 2147483647 + } + } + BREAK; + default: + BREAK; + } + + FOR( i = 0; i < input_frame; i++ ) + { + Left_in_fx[i] = FR_Y_fx[i]; // Qx + Right_in_fx[i] = LR_X_fx[i]; // Qx + move16(); + move16(); + } + + hStereoTD->tdm_last_ratio_fx = tdm_ratio_tabl_fx[tdm_ratio_idx]; // Q31 + hStereoTD->tdm_last_ratio_SM_fx = tdm_ratio_tabl_fx[tdm_ratio_idx_SM]; // Q31 + move32(); + move32(); + + return; +} +#endif + +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * Function stereo_tdm_prep_dwnmx() + * + * Reactivate downmixing after bitrate switching from MDCT to lower rate + *-------------------------------------------------------------------*/ + +void stereo_tdm_prep_dwnmx_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word32 *input1, /* i : right channel input */ + const Word16 input_frame, /* i : frame lenght */ + const Word16 input_q /* i : frame lenght */ +) +{ +#define USER_ENER + Word32 mener; + int16_t i, sw_pos, enr_len; + Encoder_State **sts; + Word16 mener_e; + sts = hCPE->hCoreCoder; + + i = idiv1616( input_frame, L_FRAME16k ); + + sw_pos = i_mult( 22, i ); + enr_len = i_mult( 6, i ); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + IF( EQ_16( hCPE->hStereoTD->flag_skip_DMX, 1 ) ) /* hStereoTD is defined only if element mode == TD */ + { + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) + { + Word16 tmp_e; + mener_e = sub( 31, input_q ); + mener = L_add( sum2_32_fx( input1 + sub( input_frame, sw_pos ), enr_len, &mener_e ), EPSILON_FX ); + mener = BASOP_Util_Divide3232_Scale( mener, (Word32) enr_len, &tmp_e ); + mener_e = add( mener_e, sub( tmp_e, 15 ) ); + mener = Sqrt32( mener, &mener_e ); + test(); + test(); + IF( LT_32( mener, L_shl( 10, sub( 31, mener_e ) ) ) && ( sts[1]->vad_flag == 0 || EQ_16( sts[1]->coder_type_raw, UNVOICED ) ) ) + { + hCPE->hStereoTD->flag_skip_DMX = 0; /* Can start using the TD downmix whenever the right channel is sufficiently low energy to limit switching artefacts */ + move16(); + } + } + ELSE IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) || EQ_32( hCPE->last_element_brate, IVAS_13k2 ) ) /* Just security check, should not happened */ + { + hCPE->hStereoTD->flag_skip_DMX = 0; + move16(); + } + test(); + } + } + return; +} +#else /*-------------------------------------------------------------------* * Function stereo_tdm_prep_dwnmx() * @@ -982,3 +1831,4 @@ void stereo_tdm_prep_dwnmx( return; } +#endif diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 21250b5e433cedeaa27acc966d76e81012714970..384ad20835c2db22ec02179df88cbd4d09fdcb34 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -45,6 +45,7 @@ #include "prot_fx.h" #include "prot_fx_enc.h" #include "rom_com_fx.h" +#include "ivas_prot_fx.h" #endif /*-------------------------------------------------------------------* @@ -225,35 +226,19 @@ void stereo_tcx_init_enc( * Stereo TCX encoder *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void stereo_tcx_core_enc( - Encoder_State *st, /* i/o: encoder state structure */ - const float new_samples_12k8[], /* i : buffer of input signal @12.8 kHz */ - const float new_samples_16k[], /* i : buffer of input signal @16 kHz */ - const float Aw[], /* i : weighted A(z) unquant. for subframes*/ - float lsp_new[], /* i : LSPs at the end of the frame */ - float lsp_mid[], /* i : LSPs in the middle of the frame */ - float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ - const int16_t last_element_mode, /* i : last element mode */ - const int16_t vad_hover_flag /* i : VAD hangover flag */ + Encoder_State *st, /* i/o: encoder state structure */ + const float new_samples_12k8[], /* i : buffer of input signal @12.8 kHz */ + const float new_samples_16k[], /* i : buffer of input signal @16 kHz */ + const Word16 Aw_fx[], /* i : weighted A(z) unquant. for subframes, Q12 */ + float lsp_new[], /* i : LSPs at the end of the frame, Q15 */ + float lsp_mid[], /* i : LSPs in the middle of the frame, Q15 */ + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : pitch for each subframe, Q6 */ + const Word16 last_element_mode, /* i : last element mode, Q0 */ + const Word16 vad_hover_flag /* i : VAD hangover flag, Q0 */ ) { -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word32 pitch_buf_fx[NB_SUBFR16k]; /* 15Q16 */ - - // Convert gamma to fixed point. - if ( (Word16) ( st->gamma_flt * 100 ) == 92 ) - { - st->gamma = GAMMA1; - st->inv_gamma = GAMMA1_INV; - } - else if ( (Word16) ( st->gamma_flt * 100 ) == 94 ) - { - st->gamma = GAMMA16k; - st->inv_gamma = GAMMA16k_INV; - } -#endif - -#ifdef IVAS_FLOAT_FIXED TCX_ENC_HANDLE hTcxEnc; Word16 i, n; Word16 tmp1, tmp2; @@ -278,28 +263,25 @@ void stereo_tcx_core_enc( Word16 bits_param_lpc[10], no_param_lpc; /*LPC*/ - float lsf_q[M], lsp_q[M], lsf[M]; - Word16 lsp_q_fx[M], lsf_fx[M]; - float lspmid_q[M]; + Word16 lsp_fx[M]; + Word16 lsp_q_fx[M], lsf_q_fx[M], lsf_fx[M]; Word16 lspmid_q_fx[M]; - float A_q[M + 1]; Word16 A_q_fx[M + 1]; - float gainlpc[2][FDNS_NPTS]; - float lsp_tcx_q[M], lsf_tcx_q[M]; + Word16 gainlpc_fx[2][FDNS_NPTS]; + Word16 gainlpc_e[2][FDNS_NPTS]; Word16 lsp_tcx_q_fx[M], lsf_tcx_q_fx[M]; - int16_t tcx_lpc_cdk; + Word16 tcx_lpc_cdk; Word16 A_q_ind[M + 1]; /*for LPC-based AC*/ Word16 lspq_ind[M]; /*for LPC-based AC*/ -#ifdef MSAN_FIX - set_zero( lspmid_q, M ); -#endif /*TCX-LTP*/ Word16 T_op[3]; /*HM*/ Word16 indexBuffer[2 * ( ( N_MAX / 2 ) + 1 )]; + Word16 s; + CONTEXT_HM_CONFIG hm_cfg[2]; /* bitstream */ @@ -312,6 +294,9 @@ void stereo_tcx_core_enc( assert( st->mdct_sw == MODE1 && "MDCT switching should be in TCX MODE 1\n" ); assert( st->rf_mode == 0 && "Channel aware not supported! " ); + set16_fx( gainlpc_e[0], 0, FDNS_NPTS ); + set16_fx( gainlpc_e[1], 0, FDNS_NPTS ); + no_param_lpc = 0; move16(); n_subframes = 1; @@ -319,6 +304,11 @@ void stereo_tcx_core_enc( hTcxEnc = st->hTcxEnc; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_new, Q_exc, q_comm_Bin; + Word16 lsp_new_fx[M], lsp_mid_fx[M]; +#endif + /*--------------------------------------------------------------* * Configuration of TCX *---------------------------------------------------------------*/ @@ -331,6 +321,7 @@ void stereo_tcx_core_enc( /* Subtract the bits of common header */ st->bits_frame_core = extract_l( L_sub( Mpy_32_32( st->total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ), hBstr->nb_bits_tot ) ); + move16(); /*Get Bits of TCX header*/ nbits_header = 3; /* Coder types (2) + last_core for bfi (1) */ @@ -343,6 +334,7 @@ void stereo_tcx_core_enc( } /* bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + test(); IF( EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP ) || EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, MIN_OVERLAP ) ) { nbits_header = add( nbits_header, 2 ); @@ -376,14 +368,13 @@ void stereo_tcx_core_enc( /* convert pitch values to core sampling-rate */ IF( NE_16( st->L_frame, L_FRAME ) ) { - Word16 s; + // T_op[i] = (int16_t)(T_op[i] * (float)st->L_frame / (float)L_FRAME + 0.5f); Word16 fac = BASOP_Util_Divide1616_Scale( st->L_frame, L_FRAME, &s ); // exp: s Word32 mul = L_mult0( T_op[i], fac ); // exp: 15 + s + 1 = 16 + s Word32 half = L_shr( ONE_IN_Q14 /*0.5 in Q15*/, s ); // exp: 16 + s Word32 sum = L_add( mul, half ); // exp: 16 + s T_op[i] = extract_l( L_shr( sum, sub( 15, s ) ) ); // exp: 31 (Q0) move16(); - // T_op[i] = (int16_t)(T_op[i] * (float)st->L_frame / (float)L_FRAME + 0.5f); } } @@ -468,177 +459,87 @@ void stereo_tcx_core_enc( { bitsAvailable = sub( bitsAvailable, st->hIGFEnc->infoTotalBitsWritten ); } -#else - TCX_ENC_HANDLE hTcxEnc; - int16_t i, n; - - /*size and windowing*/ - const float *p_new_samples; - int16_t n_subframes; - int16_t last_core_orig; - - /*Bits*/ - int16_t nbits_start, total_nbbits, nbits_header; - int16_t target_bits[2], bitsAvailable; - int16_t nbits_lpc[2]; - int16_t tnsSize[2]; /* number of tns parameters put into prm */ - int16_t tnsBits[2]; /* number of tns bits in the frame */ - int16_t ltpBits; - - /*Parameters*/ - int16_t param_lpc[NPRM_LPC_NEW]; - int16_t param_core[2 * NPRM_DIV]; - int16_t bits_param_lpc[10], no_param_lpc; - - /*LPC*/ - float lsf_q[M], lsp_q[M], lsp[M], lsf[M]; - float lspmid_q[M]; - float A_q[M + 1]; - float gainlpc[2][FDNS_NPTS]; - float lsp_tcx_q[M], lsf_tcx_q[M]; - int16_t tcx_lpc_cdk; - Word16 A_q_ind[M + 1]; /*for LPC-based AC*/ - Word16 lspq_ind[M]; /*for LPC-based AC*/ - - /*TCX-LTP*/ - int16_t T_op[3]; - - /*HM*/ - int16_t indexBuffer[2 * ( ( N_MAX / 2 ) + 1 )]; - - CONTEXT_HM_CONFIG hm_cfg[2]; - - /* bitstream */ - BSTR_ENC_HANDLE hBstr = st->hBstr; - - - push_wmops( "stereo_tcx_core_enc" ); - /*Sanity check*/ - assert( st->mdct_sw == MODE1 && "MDCT switching should be in TCX MODE 1\n" ); - assert( st->rf_mode == 0 && "Channel aware not supported! " ); - - no_param_lpc = 0; - n_subframes = 1; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); - hTcxEnc = st->hTcxEnc; + q_comm_Bin = s_min( Q_factor_arrL( st->Bin_E_old, 128 ), Q_factor_arrL( st->Bin_E, 256 ) ); + Q_new = q_comm_Bin - ( QSCALE - 2 ); + const Word16 Q_ener = Q_new + Q_SCALE - 2; // Q_new + Q_SCALE -2 - /*--------------------------------------------------------------* - * Configuration of TCX - *---------------------------------------------------------------*/ + st->stab_fac_fx = float_to_fix16( st->stab_fac, Q15 ); + floatToFixed_arrL( st->Bin_E_old, st->Bin_E_old_fx, q_comm_Bin, 128 ); + floatToFixed_arrL( st->Bin_E, st->Bin_E_fx, q_comm_Bin, 256 ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + for ( int j = 0; j < M; j++ ) + { + st->lsf_old_fx[j] = (Word16) ( st->lsf_old[j] * 2.56f ); + st->lsf_adaptive_mean_fx[j] = (Word16) ( st->lsf_adaptive_mean[j] * 2.56f ); + st->mem_MA_fx[j] = (Word16) ( st->mem_MA[j] * 2.56f ); + st->mem_AR_fx[j] = (Word16) ( st->mem_AR[j] * 2.56f ); + } - stereo_tcx_init_enc( st ); + st->gamma = float_to_fix16( st->gamma_flt, Q15 ); + floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); - /*--------------------------------------------------------------* - * Initialization - *---------------------------------------------------------------*/ + st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); + st->hTcxEnc->spectrum_e[1] = st->hTcxEnc->spectrum_e[0]; - /* Subtract the bits of common header */ - st->bits_frame_core = (int16_t) ( st->total_brate / FRAMES_PER_SEC ) - hBstr->nb_bits_tot; + hTcxEnc->tcxltp_gain = float_to_fix16( hTcxEnc->tcxltp_gain_flt, Q15 ); - /*Get Bits of TCX header*/ - nbits_header = 3; /* Coder types (2) + last_core for bfi (1) */ + Word16 L_frame = st->L_frame; + Word16 L_frameTCX = hTcxEnc->L_frameTCX; + Word16 L_spec = st->hTcxCfg->tcx_coded_lines; + Word16 tcx_offset = st->hTcxCfg->tcx_offset; - if ( st->tcxonly ) + IF( EQ_16( st->core, TCX_10_CORE ) ) { - /* TCX20/10 flag */ - nbits_header++; + L_frame = shr( L_frame, 1 ); + L_frameTCX = shr( L_frameTCX, 1 ); + L_spec = shr( L_spec, 1 ); } - - /* bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ - nbits_header += ( st->hTcxCfg->tcx_curr_overlap_mode == HALF_OVERLAP || st->hTcxCfg->tcx_curr_overlap_mode == MIN_OVERLAP ) ? 2 : 1; - - hm_cfg[0].indexBuffer = &indexBuffer[0]; - hm_cfg[1].indexBuffer = &indexBuffer[N_MAX / 2 + 1]; - - set_s( tnsSize, 0, 2 ); - set_s( tnsBits, 0, 2 ); - set_s( nbits_lpc, 0, 2 ); - ltpBits = 0; - - for ( i = 0; i < 3; i++ ) + ELSE IF( st->last_core == ACELP_CORE ) { - T_op[i] = st->pitch[i]; - - /* check minimum pitch for quantization */ - if ( T_op[i] < PIT_MIN_SHORTER ) - { - T_op[i] *= 2; - } + L_frame = add( L_frame, tcx_offset ); + L_frameTCX = add( L_frameTCX, st->hTcxCfg->tcx_offsetFB ); + L_spec = add( L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) ); - /* convert pitch values to core sampling-rate */ - if ( st->L_frame != L_FRAME ) + IF( st->hTcxCfg->lfacNext < 0 ) { - T_op[i] = (int16_t) ( T_op[i] * (float) st->L_frame / (float) L_FRAME + 0.5f ); + L_frame = sub( L_frame, st->hTcxCfg->lfacNext ); + L_frameTCX = sub( L_frameTCX, st->hTcxCfg->lfacNextFB ); } } - if ( st->L_frame == L_FRAME ) - { - p_new_samples = new_samples_12k8; - } - else - { - p_new_samples = new_samples_16k; - } - - /*--------------------------------------------------------------* - * TCX20/TCX10 switching decision - *---------------------------------------------------------------*/ + Q_new = 0; - if ( hTcxEnc->tcxMode == TCX_10 ) - { - st->core = TCX_10_CORE; - n_subframes = 2; - nbits_header += ( st->hTcxCfg->tcx_last_overlap_mode == HALF_OVERLAP || st->hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) ? 2 : 1; - } - else if ( hTcxEnc->tcxMode == TCX_20 ) + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); + floatToFixed_arr( st->lsp_old16k, st->lsp_old16k_fx, Q15, M ); + Word16 exp_exc; + f2me_buf_16( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, &exp_exc, L_EXC_MEM ); + Q_exc = 15 - exp_exc; + st->hLPDmem->e_old_exc = exp_exc; + if ( st->hTdCngEnc != NULL ) { - st->core = TCX_20_CORE; - n_subframes = 1; + floatToFixed_arr( st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_exc2_buf, Q_exc, HO_HIST_SIZE * L_FFT ); } - - nbits_start = hBstr->nb_bits_tot; - - /*--------------------------------------------------------------------------------* - * Write TCX signaling - *--------------------------------------------------------------------------------*/ - - /* TCX20/TCX10 and coder type */ - writeTCXMode( st, hBstr, 0, /* MCT_flag */ &nbits_start ); - - /* write last_core for error concealment */ - push_next_indice( hBstr, ( st->last_core != ACELP_CORE || st->core == TCX_10_CORE ), 1 ); - - /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ - writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); - if ( st->core == TCX_10_CORE ) + if ( st->hDtxEnc != NULL ) { - writeTCXWindowing( hBstr, st->hTcxCfg->tcx_last_overlap_mode ); + floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); } - assert( nbits_header == ( hBstr->nb_bits_tot - nbits_start ) ); - - /*--------------------------------------------------------------* - * Core Signal Analysis: MDCT, TNS, LPC analysis - *---------------------------------------------------------------*/ - - core_signal_analysis_high_bitrate( p_new_samples, T_op, lsp_new, lsp_mid, st, NULL, tnsSize, tnsBits, param_core, <pBits, NULL, st->L_frame, hTcxEnc->L_frameTCX, last_element_mode, vad_hover_flag ); - - bitsAvailable = st->bits_frame_core - nbits_header; - if ( st->igf ) + floatToFixed_arr( st->synth_flt, st->synth, Q_new, st->L_frame ); + floatToFixed_arr( st->hLPDmem->syn_flt, st->hLPDmem->syn, Q_new, M + 1 ); + if ( st->tcxonly == 0 ) { - bitsAvailable -= st->hIGFEnc->infoTotalBitsWritten; + st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); } - - /*--------------------------------------------------------------* - * Envelope Quantization and FDNS - *---------------------------------------------------------------*/ -#endif +#endif // IVAS_FLOAT_FIXED_CONVERSIONS IF( !st->enableTcxLpc ) { -#ifdef IVAS_FLOAT_FIXED IF( st->envWeighted ) { /* Unweight the envelope */ @@ -646,46 +547,24 @@ void stereo_tcx_core_enc( st->envWeighted = 0; move16(); } -#else - if ( st->envWeighted ) - { - /* Unweight the envelope */ - E_LPC_lsp_unweight_float( st->lsp_old, st->lsp_old, st->lsf_old, 1.0f / st->gamma_flt ); - st->envWeighted = 0; - } -#endif - lpc_quantization( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, AUDIO, 0, /*No acelp->no need to compute any mid-LPC*/ - param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc ); + lpc_quantization_ivas_fx( st, lsp_new_fx, lsp_mid_fx, lsp_q_fx, lsf_q_fx, lspmid_q_fx, AUDIO, 0, /*No acelp->no need to compute any mid-LPC*/ + param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc, Q_ener ); /*--------------------------------------------------------------* * Rate switching *--------------------------------------------------------------*/ - if ( st->rate_switching_reset ) + IF( st->rate_switching_reset ) { - mvr2r( lsp_q, st->lsp_old, M ); - mvr2r( lsf_q, st->lsf_old, M ); + Copy( lsp_q_fx, st->lsp_old_fx, M ); + Copy( lsf_q_fx, st->lsf_old_fx, M ); } } last_core_orig = st->last_core; move16(); -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Float to fix - Word16 lsp_new_fx[M], lsp_fx[M]; - st->gamma = float_to_fix16( st->gamma_flt, Q15 ); - floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); - floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); - floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); - if ( !st->enableTcxLpc ) - { - floatToFixed_arr( lsp_q, lsp_q_fx, Q15, M ); - floatToFixed_arr( lspmid_q, lspmid_q_fx, Q15, M ); - } -#endif FOR( n = 0; n < n_subframes; n++ ) { /* Get the envelope */ @@ -693,7 +572,6 @@ void stereo_tcx_core_enc( { tcx_lpc_cdk = tcxlpc_get_cdk( st->hTcxCfg->coder_type ); - /* NOTE: High MLD observed for the below function. */ /* Get the envelope corresponding to the current frame */ E_LPC_int_lpc_tcx( st->lspold_enc_fx, lsp_new_fx, A_q_fx ); @@ -705,23 +583,8 @@ void stereo_tcx_core_enc( E_LPC_lsp_lsf_conversion( lsp_fx, lsf_fx, M ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( int j = 0; j < M; j++ ) - { - lsf[j] = (float) lsf_fx[j] / 2.56f; - } -#endif - /* Quantize */ - /* TODO: integrate this. */ - Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( int j = 0; j < M; j++ ) - { - lsf_tcx_q_fx[j] = (Word16) ( lsf_tcx_q[j] * 2.56f ); - } -#endif + Q_lsf_tcxlpc_fx( lsf_fx, lsf_tcx_q_fx, lspq_ind, param_lpc, M, st->narrowBand, tcx_lpc_cdk, st->mem_MA_fx, st->hTcxCfg->coder_type, st->Bin_E_fx, Q_ener ); /* Account for consumed bits */ nbits_lpc[0] = TCXLPC_NUMBITS; @@ -732,7 +595,6 @@ void stereo_tcx_core_enc( move16(); } - /* NOTE: High MLD observed for the below function. */ /* Convert quantized lsf to lsp and A */ E_LPC_lsf_lsp_conversion( lsf_tcx_q_fx, lsp_tcx_q_fx, M ); E_LPC_f_lsp_a_conversion( lsp_tcx_q_fx, A_q_fx, M ); @@ -757,87 +619,22 @@ void stereo_tcx_core_enc( bitsAvailable = sub( bitsAvailable, nbits_lpc[n] ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( A_q_fx, A_q, Q14 - norm_s( A_q_fx[0] ), M + 1 ); -#endif - /* Shape spectrum */ - /* TODO: integrate this. */ - ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); + ShapeSpectrum_ivas_fx( st->hTcxCfg, A_q_fx, gainlpc_fx[n], gainlpc_e[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum_fx[n], &hTcxEnc->spectrum_e[n], hTcxEnc->fUseTns[n], st, NULL ); st->last_core = st->core; move16(); } -#else - for ( n = 0; n < n_subframes; n++ ) - { - /* Get the envelope */ - if ( st->enableTcxLpc ) - { - tcx_lpc_cdk = tcxlpc_get_cdk_float( st->hTcxCfg->coder_type ); - - /* Get the envelope corresponding to the current frame */ - E_LPC_int_lpc_tcx_float( st->lspold_enc, lsp_new, A_q ); - /* Weight the envelope */ - weight_a( A_q, A_q, st->gamma_flt, M ); + st->last_core = last_core_orig; + move16(); - /* Convert to lsp and lsf */ - float lsp[M]; - a2lsp_stab( A_q, lsp, lsp_new ); - lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + /*--------------------------------------------------------------------------------* + * Write LPC parameters + *--------------------------------------------------------------------------------*/ + writeLPCparam_fx( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); - /* Quantize */ - Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); - - /* Account for consumed bits */ - nbits_lpc[0] = TCXLPC_NUMBITS; - if ( param_lpc[0] ) - { - nbits_lpc[0] += TCXLPC_IND_NUMBITS; - } - - /* Convert quantized lsf to lsp and A */ - lsf2lsp( lsf_tcx_q, lsp_tcx_q, M, INT_FS_12k8 ); - lsp2a_stab( lsp_tcx_q, A_q, M ); - } - else if ( !st->tcxonly ) - { - E_LPC_int_lpc_tcx_float( st->lsp_old, lsp_q, A_q ); - } - else if ( n + 2 == n_subframes ) /* First TCX10/5 subframe */ - { - lsp2a_stab( lspmid_q, A_q, M ); - } - else - { - lsp2a_stab( lsp_q, A_q, M ); - } - - if ( hTcxEnc->tcx_lpc_shaped_ari ) - { - basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); - } - - bitsAvailable -= nbits_lpc[n]; - - /* Shape spectrum */ - ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); - - st->last_core = st->core; - } -#endif - -#ifdef IVAS_FLOAT_FIXED - st->last_core = last_core_orig; - move16(); - - /*--------------------------------------------------------------------------------* - * Write LPC parameters - *--------------------------------------------------------------------------------*/ - writeLPCparam_fx( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); - - assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); + assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); /*--------------------------------------------------------------* * Run TCX10/20 Core @@ -871,134 +668,75 @@ void stereo_tcx_core_enc( } tmp2 = imult1616( n, NPRM_DIV ); - QuantizeSpectrum_ivas_fx( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); + QuantizeSpectrum_ivas_fx( st, A_q_fx, A_q_ind, gainlpc_fx[n], gainlpc_e[n], st->synth + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); } /* Update tcx overlap mode */ st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; move16(); - // Fix to float - hTcxEnc->measuredBwRatio_flt = fix16_to_float( hTcxEnc->measuredBwRatio, Q14 ); -#else - st->last_core = last_core_orig; - - /*--------------------------------------------------------------------------------* - * Write LPC parameters - *--------------------------------------------------------------------------------*/ - - writeLPCparam( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); - - assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); - - /*--------------------------------------------------------------* - * Run TCX10/20 Core - *---------------------------------------------------------------*/ - - hTcxEnc->measuredBwRatio_flt = 1.f; - - for ( n = 0; n < n_subframes; n++ ) + s = sub( getScaleFactor16( st->synth, st->L_frame ), 2 ); + s = s_min( s, getScaleFactor16( st->hLPDmem->syn, M ) ); + IF( st->tcxonly == 0 ) { - target_bits[n] = ( bitsAvailable + ( n_subframes - 1 ) - n ) / n_subframes - tnsBits[n]; - - if ( st->enablePlcWaveadjust && ( n == n_subframes - 1 ) ) - { - target_bits[n] -= 1; - } - if ( n == 0 ) - { - target_bits[n] -= ltpBits; - } - - /* Run TCX20/10 encoder */ - QuantizeSpectrum( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + n * st->L_frame / n_subframes, target_bits[n], tnsSize[n], param_core + n * NPRM_DIV, n, &hm_cfg[n], vad_hover_flag ); + s = s_min( s, norm_s( st->wspeech_enc[st->L_frame - 1] ) ); + st->wspeech_enc[st->L_frame - 1] = shl( st->wspeech_enc[st->L_frame - 1], s ); } + Scale_sig( st->synth, st->L_frame, s ); + Scale_sig( st->hLPDmem->syn, M + 1, s ); + Q_new = add( Q_new, s ); + move16(); + move16(); - /* Update tcx overlap mode */ - st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; -#endif - - coder_tcx_post( st, A_q, Aw ); - -#ifdef IVAS_FLOAT_FIXED - IF( st->enableTcxLpc ) + /* Scaling old_exc buffer to Q_new */ + IF( NE_16( Q_new, Q_exc ) ) { -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 lsf_q_fx[M]; -#endif - E_LPC_lsp_unweight( lsp_tcx_q_fx, lsp_q_fx, lsf_q_fx, st->inv_gamma, M ); /* Update lsf_q for encoderSideLossSimulation() */ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Fixed to float - for ( int j = 0; j < M; j++ ) - { - lsp_q[j] = fix16_to_float( lsp_q_fx[j], Q15 ); - lsf_q[j] = (float) lsf_q_fx[j] / 2.56f; - } -#endif + Scale_sig( st->hLPDmem->old_exc, L_EXC_MEM, sub( Q_new, Q_exc ) ); } -#else - if ( st->enableTcxLpc ) + + coder_tcx_post_ivas_fx( st, st->hLPDmem, st->hTcxCfg, st->synth, A_q_fx, Aw_fx, st->wspeech_enc, Q_new ); + + /* Upscaling old_exc buffer */ + s = getScaleFactor16( st->hLPDmem->old_exc, L_EXC_MEM ) - 1; + Scale_sig( st->hLPDmem->old_exc, L_EXC_MEM, s ); + IF( st->hTdCngEnc != NULL ) { - E_LPC_lsp_unweight_float( lsp_tcx_q, lsp_q, lsf_q, 1.0f / st->gamma_flt ); /* Update lsf_q for encoderSideLossSimulation() */ + Scale_sig( st->hTdCngEnc->cng_exc2_buf, HO_HIST_SIZE * L_FFT, sub( add( shl( Q_new, 1 ), s ), Q_exc ) ); } -#endif + Q_exc = add( shl( Q_new, 1 ), s ); // 2 * Q_new + s -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - if ( st->enableTcxLpc ) + IF( st->enableTcxLpc ) { - fixedToFloat_arr( lsp_tcx_q_fx, lsp_tcx_q, Q15, M ); + E_LPC_lsp_unweight( lsp_tcx_q_fx, lsp_q_fx, lsf_q_fx, st->inv_gamma, M ); /* Update lsf_q for encoderSideLossSimulation() */ } -#endif /* Update lsp/lsf memory */ - if ( st->enableTcxLpc && st->core != ACELP_CORE ) + test(); + IF( st->enableTcxLpc && st->core != ACELP_CORE ) { /* Update lsf / lsp memory */ - mvr2r( lsf_tcx_q, st->lsf_old, M ); - mvr2r( lsp_tcx_q, st->lsp_old, M ); + Copy( lsf_tcx_q_fx, st->lsf_old_fx, M ); + Copy( lsp_tcx_q_fx, st->lsp_old_fx, M ); st->envWeighted = 1; + move16(); /* Update ACELP quantizer state */ - lsf_update_memory_float( st->narrowBand, st->lsf_old, st->mem_MA, st->mem_MA ); + lsf_update_memory( st->narrowBand, st->lsf_old_fx, st->mem_MA_fx, st->mem_MA_fx, M ); st->pstreaklen = 0; - st->streaklimit = 1.0f; - /* check resonance for pitch clipping algorithm */ - gp_clip_test_lsf( st->element_mode, st->core_brate, st->lsf_old, st->clip_var, 0 ); - mvr2r( st->lsf_old, st->mem_AR, M ); - } - else - { - mvr2r( lsf_q, st->lsf_old, M ); - mvr2r( lsp_q, st->lsp_old, M ); - } - + st->streaklimit_fx = 32767; // 1.0 in Q15 + move16(); + move16(); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Float to fixed - Word16 Q_exc, exp_exc; - f2me_buf_16( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, &exp_exc, L_EXC_MEM ); - Q_exc = 15 - exp_exc; - floatToFixed_arr( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, Q_exc, L_EXC_MEM ); - floatToFixed_arr( st->lsp_old16k, st->lsp_old16k_fx, Q15, M ); - IF( st->hTdCngEnc != NULL ) - { - floatToFixed_arrL( st->hTdCngEnc->ho_ener_circ, st->hTdCngEnc->ho_ener_circ_fx, Q6, HO_HIST_SIZE ); - floatToFixed_arr( st->hTdCngEnc->ho_lsp_circ, st->hTdCngEnc->ho_lsp_circ_fx, Q15, HO_HIST_SIZE * M ); - floatToFixed_arrL( st->hTdCngEnc->ho_env_circ, st->hTdCngEnc->ho_env_circ_fx, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); - floatToFixed_arr( st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_exc2_buf, Q_exc, HO_HIST_SIZE * L_FFT ); - st->hTdCngEnc->lp_ener_fx = float_to_fix( st->hTdCngEnc->lp_ener, Q6 ); + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_ivas_fx( st->element_mode, st->core_brate, st->lsf_old_fx, st->clip_var_fx, 0 ); + Copy( st->lsf_old_fx, st->mem_AR_fx, M ); } - IF( st->hDtxEnc != NULL ) + ELSE { - floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); + Copy( lsf_q_fx, st->lsf_old_fx, M ); + Copy( lsp_q_fx, st->lsp_old_fx, M ); } - floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); - st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif - -#ifdef IVAS_FLOAT_FIXED test(); test(); IF( st->Opt_DTX_ON && !st->tcxonly && st->hTdCngEnc != NULL ) @@ -1076,117 +814,455 @@ void stereo_tcx_core_enc( IF( NE_16( param_core[1 + NOISE_FILL_RANGES], 0 ) ) { Word32 tcxltp_pitch_tmp = L_add( L_deposit_h( hTcxEnc->tcxltp_pitch_int ), L_shl( L_deposit_l( div_s( hTcxEnc->tcxltp_pitch_fr, st->pit_res_max ) ), 1 ) ); /* 15Q16 */ - set32_fx( pitch_buf_fx, tcxltp_pitch_tmp, NB_SUBFR16k ); + tcxltp_pitch_tmp = L_shr( tcxltp_pitch_tmp, 10 ); // Q6 + set16_fx( pitch_buf_fx, extract_l( tcxltp_pitch_tmp ), NB_SUBFR16k ); } ELSE { - set32_fx( pitch_buf_fx, L_SUBFR * ONE_IN_Q16, NB_SUBFR16k ); - } -#else - if ( st->Opt_DTX_ON && !st->tcxonly && st->hTdCngEnc != NULL ) - { - /* update CNG parameters in active frames */ - if ( st->bwidth == NB && st->enableTcxLpc && st->core != ACELP_CORE ) - { - float buf[L_LP], res[L_FRAME], A[M + 1], r[M + 1], tmp, lsptmp[M]; - - assert( st->L_frame == L_FRAME ); - - mvr2r( st->synth_flt + L_FRAME - L_LP, buf, L_LP ); - tmp = st->synth_flt[L_FRAME - L_LP - 1]; - preemph( buf, st->preemph_fac_flt, L_LP, &tmp ); - autocorr( buf, r, M, L_LP, LP_assym_window, 0, 0, 0 ); - lag_wind_flt( r, M, INT_FS_12k8, LAGW_WEAK ); - lev_dur( A, r, M, NULL ); - a2lsp_stab( A, lsptmp, lsp_new ); - residu( A, M, buf + L_LP - L_FRAME, res, L_FRAME ); - - cng_params_upd( lsptmp, res, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ, ENC, st->hTdCngEnc->ho_env_circ, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); - } - else - { - cng_params_upd( lsp_new, st->hLPDmem->old_exc_flt + L_EXC_MEM - st->L_frame, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ, ENC, st->hTdCngEnc->ho_env_circ, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); - } - - if ( st->L_frame == L_FRAME ) - { - /* store LSPs@16k, potentially to be used in CNG@16k */ - mvr2r( st->lsp_old16k, &( st->hTdCngEnc->ho_lsp_circ2[( st->hTdCngEnc->ho_circ_ptr ) * M] ), M ); - } - - /* Set 16k LSP flag for CNG buffer */ - st->hTdCngEnc->ho_16k_lsp[st->hTdCngEnc->ho_circ_ptr] = ( st->L_frame == L_FRAME ? 0 : 1 ); - - /* efficient DTX hangover control */ - if ( st->hTdCngEnc->burst_ho_cnt > 1 ) - { - dtx_hangover_control( st, lsp_new ); - } - } - - /*--------------------------------------------------------------------------------* - * Encode TCX20/10 parameters - *--------------------------------------------------------------------------------*/ - - writeTCXparam( st, hBstr, hm_cfg, param_core, nbits_header, nbits_start, nbits_lpc[0] + nbits_lpc[1], NULL, NULL, NULL, -1 ); - - total_nbbits = hBstr->nb_bits_tot - nbits_start; - - if ( param_core[1 + NOISE_FILL_RANGES] != 0 ) - { - set_f( pitch_buf, hTcxEnc->tcxltp_pitch_int + (float) hTcxEnc->tcxltp_pitch_fr / (float) st->pit_res_max, NB_SUBFR16k ); - } - else - { - set_f( pitch_buf, L_SUBFR, NB_SUBFR16k ); + set16_fx( pitch_buf_fx, L_SUBFR * ONE_IN_Q6, NB_SUBFR16k ); } -#endif #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Fixed to float - for ( int j = 0; j < NB_SUBFR16k; j++ ) - { - pitch_buf[j] = fix_to_float( pitch_buf_fx[j], Q16 ); - } IF( st->hTdCngEnc != NULL ) { - fixedToFloat_arrL( st->hTdCngEnc->ho_ener_circ_fx, st->hTdCngEnc->ho_ener_circ, Q6, HO_HIST_SIZE ); - fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ_fx, st->hTdCngEnc->ho_lsp_circ, Q15, HO_HIST_SIZE * M ); - fixedToFloat_arrL( st->hTdCngEnc->ho_env_circ_fx, st->hTdCngEnc->ho_env_circ, Q6, HO_HIST_SIZE * NUM_ENV_CNG ); fixedToFloat_arr( st->hTdCngEnc->cng_exc2_buf, st->hTdCngEnc->cng_exc2_buf_flt, Q_exc, HO_HIST_SIZE * L_FFT ); - fixedToFloat_arr( st->hTdCngEnc->ho_lsp_circ2_fx, st->hTdCngEnc->ho_lsp_circ2, M, Q15 ); } + + fixedToFloat_arr( st->synth, st->synth_flt, Q_new, st->L_frame ); + fixedToFloat_arr( st->hLPDmem->mem_syn_r, st->hLPDmem->mem_syn_r_flt, Q_new + ( Q_new - 1 ), L_SYN_MEM ); + fixedToFloat_arr( st->hLPDmem->mem_syn, st->hLPDmem->mem_syn_flt, Q_new + ( Q_new - 1 ), M ); + fixedToFloat_arr( st->hLPDmem->mem_syn2, st->hLPDmem->mem_syn2_flt, Q_new + ( Q_new - 1 ), M ); + fixedToFloat_arr( st->hLPDmem->syn, st->hLPDmem->syn_flt, Q_new, M + 1 ); + fixedToFloat_arr( st->hLPDmem->old_exc, st->hLPDmem->old_exc_flt, Q_exc, L_EXC_MEM ); + st->hLPDmem->mem_w0_flt = fixedToFloat_16( st->hLPDmem->mem_w0, Q_new ); + + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, q_comm_Bin, 128 ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, q_comm_Bin, 256 ); + + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); #endif pop_wmops(); return; } +#else +void stereo_tcx_core_enc( + Encoder_State *st, /* i/o: encoder state structure */ + const float new_samples_12k8[], /* i : buffer of input signal @12.8 kHz */ + const float new_samples_16k[], /* i : buffer of input signal @16 kHz */ + const float Aw[], /* i : weighted A(z) unquant. for subframes*/ + float lsp_new[], /* i : LSPs at the end of the frame */ + float lsp_mid[], /* i : LSPs in the middle of the frame */ + float pitch_buf[NB_SUBFR16k], /* o : floating pitch for each subframe */ + const int16_t last_element_mode, /* i : last element mode */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +) +{ + TCX_ENC_HANDLE hTcxEnc; + int16_t i, n; + /*size and windowing*/ + const float *p_new_samples; + int16_t n_subframes; + int16_t last_core_orig; -/*-------------------------------------------------------------------* - * ivas_acelp_tcx20_switching() - * - * Open-loop ACELP/TCX20 core decision - *-------------------------------------------------------------------*/ + /*Bits*/ + int16_t nbits_start, total_nbbits, nbits_header; + int16_t target_bits[2], bitsAvailable; + int16_t nbits_lpc[2]; + int16_t tnsSize[2]; /* number of tns parameters put into prm */ + int16_t tnsBits[2]; /* number of tns bits in the frame */ + int16_t ltpBits; -/*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ -int16_t ivas_acelp_tcx20_switching( - Encoder_State *st, /* i/o: encoder state structure */ - const float *inp, /* i : new input signal */ - const float *wsp, /* i : input weighted signal */ - const float non_staX, /* i : unbound non-stationarity for sp/mu clas.*/ - const float *pitch_fr, /* i : fraction pitch values */ - const float *voicing_fr, /* i : fractional voicing values */ - const float currFlatness, /* i : flatness */ - const float lsp_mid[M], /* i : LSPs at the middle of the frame */ - const float stab_fac, /* i : LP filter stability */ - float *res_cod_SNR_M, - const int16_t flag_16k_smc /* i : flag to compute parameters with 16kHz core */ -) -{ - TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; - int16_t i, j; - float A_q_tcx[NB_SUBFR16k * ( M + 1 )]; + /*Parameters*/ + int16_t param_lpc[NPRM_LPC_NEW]; + int16_t param_core[2 * NPRM_DIV]; + int16_t bits_param_lpc[10], no_param_lpc; + + /*LPC*/ + float lsf_q[M], lsp_q[M], lsp[M], lsf[M]; + float lspmid_q[M]; + float A_q[M + 1]; + float gainlpc[2][FDNS_NPTS]; + float lsp_tcx_q[M], lsf_tcx_q[M]; + int16_t tcx_lpc_cdk; + Word16 A_q_ind[M + 1]; /*for LPC-based AC*/ + Word16 lspq_ind[M]; /*for LPC-based AC*/ + + /*TCX-LTP*/ + int16_t T_op[3]; + + /*HM*/ + int16_t indexBuffer[2 * ( ( N_MAX / 2 ) + 1 )]; + + CONTEXT_HM_CONFIG hm_cfg[2]; + + /* bitstream */ + BSTR_ENC_HANDLE hBstr = st->hBstr; + + + push_wmops( "stereo_tcx_core_enc" ); + + /*Sanity check*/ + assert( st->mdct_sw == MODE1 && "MDCT switching should be in TCX MODE 1\n" ); + assert( st->rf_mode == 0 && "Channel aware not supported! " ); + + no_param_lpc = 0; + n_subframes = 1; + + hTcxEnc = st->hTcxEnc; + + /*--------------------------------------------------------------* + * Configuration of TCX + *---------------------------------------------------------------*/ + + stereo_tcx_init_enc( st ); + + /*--------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + /* Subtract the bits of common header */ + st->bits_frame_core = (int16_t) ( st->total_brate / FRAMES_PER_SEC ) - hBstr->nb_bits_tot; + + /*Get Bits of TCX header*/ + nbits_header = 3; /* Coder types (2) + last_core for bfi (1) */ + + if ( st->tcxonly ) + { + /* TCX20/10 flag */ + nbits_header++; + } + + /* bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + nbits_header += ( st->hTcxCfg->tcx_curr_overlap_mode == HALF_OVERLAP || st->hTcxCfg->tcx_curr_overlap_mode == MIN_OVERLAP ) ? 2 : 1; + + hm_cfg[0].indexBuffer = &indexBuffer[0]; + hm_cfg[1].indexBuffer = &indexBuffer[N_MAX / 2 + 1]; + + set_s( tnsSize, 0, 2 ); + set_s( tnsBits, 0, 2 ); + set_s( nbits_lpc, 0, 2 ); + ltpBits = 0; + + for ( i = 0; i < 3; i++ ) + { + T_op[i] = st->pitch[i]; + + /* check minimum pitch for quantization */ + if ( T_op[i] < PIT_MIN_SHORTER ) + { + T_op[i] *= 2; + } + + /* convert pitch values to core sampling-rate */ + if ( st->L_frame != L_FRAME ) + { + T_op[i] = (int16_t) ( T_op[i] * (float) st->L_frame / (float) L_FRAME + 0.5f ); + } + } + + if ( st->L_frame == L_FRAME ) + { + p_new_samples = new_samples_12k8; + } + else + { + p_new_samples = new_samples_16k; + } + + /*--------------------------------------------------------------* + * TCX20/TCX10 switching decision + *---------------------------------------------------------------*/ + + if ( hTcxEnc->tcxMode == TCX_10 ) + { + st->core = TCX_10_CORE; + n_subframes = 2; + nbits_header += ( st->hTcxCfg->tcx_last_overlap_mode == HALF_OVERLAP || st->hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) ? 2 : 1; + } + else if ( hTcxEnc->tcxMode == TCX_20 ) + { + st->core = TCX_20_CORE; + n_subframes = 1; + } + + nbits_start = hBstr->nb_bits_tot; + + /*--------------------------------------------------------------------------------* + * Write TCX signaling + *--------------------------------------------------------------------------------*/ + + /* TCX20/TCX10 and coder type */ + writeTCXMode( st, hBstr, 0, /* MCT_flag */ &nbits_start ); + + /* write last_core for error concealment */ + push_next_indice( hBstr, ( st->last_core != ACELP_CORE || st->core == TCX_10_CORE ), 1 ); + + /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + writeTCXWindowing( hBstr, st->hTcxCfg->tcx_curr_overlap_mode ); + if ( st->core == TCX_10_CORE ) + { + writeTCXWindowing( hBstr, st->hTcxCfg->tcx_last_overlap_mode ); + } + + assert( nbits_header == ( hBstr->nb_bits_tot - nbits_start ) ); + + /*--------------------------------------------------------------* + * Core Signal Analysis: MDCT, TNS, LPC analysis + *---------------------------------------------------------------*/ + + core_signal_analysis_high_bitrate( p_new_samples, T_op, lsp_new, lsp_mid, st, NULL, tnsSize, tnsBits, param_core, <pBits, NULL, st->L_frame, hTcxEnc->L_frameTCX, last_element_mode, vad_hover_flag ); + + bitsAvailable = st->bits_frame_core - nbits_header; + if ( st->igf ) + { + bitsAvailable -= st->hIGFEnc->infoTotalBitsWritten; + } + + /*--------------------------------------------------------------* + * Envelope Quantization and FDNS + *---------------------------------------------------------------*/ + + if ( !st->enableTcxLpc ) + { + if ( st->envWeighted ) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight_float( st->lsp_old, st->lsp_old, st->lsf_old, 1.0f / st->gamma_flt ); + st->envWeighted = 0; + } + + lpc_quantization( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, AUDIO, 0, /*No acelp->no need to compute any mid-LPC*/ + param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc ); + + /*--------------------------------------------------------------* + * Rate switching + *--------------------------------------------------------------*/ + + if ( st->rate_switching_reset ) + { + mvr2r( lsp_q, st->lsp_old, M ); + mvr2r( lsf_q, st->lsf_old, M ); + } + } + + last_core_orig = st->last_core; + + for ( n = 0; n < n_subframes; n++ ) + { + /* Get the envelope */ + if ( st->enableTcxLpc ) + { + tcx_lpc_cdk = tcxlpc_get_cdk_float( st->hTcxCfg->coder_type ); + + /* Get the envelope corresponding to the current frame */ + E_LPC_int_lpc_tcx_float( st->lspold_enc, lsp_new, A_q ); + + /* Weight the envelope */ + weight_a( A_q, A_q, st->gamma_flt, M ); + + /* Convert to lsp and lsf */ + float lsp[M]; + a2lsp_stab( A_q, lsp, lsp_new ); + lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + + /* Quantize */ + Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); + + /* Account for consumed bits */ + nbits_lpc[0] = TCXLPC_NUMBITS; + if ( param_lpc[0] ) + { + nbits_lpc[0] += TCXLPC_IND_NUMBITS; + } + + /* Convert quantized lsf to lsp and A */ + lsf2lsp( lsf_tcx_q, lsp_tcx_q, M, INT_FS_12k8 ); + lsp2a_stab( lsp_tcx_q, A_q, M ); + } + else if ( !st->tcxonly ) + { + E_LPC_int_lpc_tcx_float( st->lsp_old, lsp_q, A_q ); + } + else if ( n + 2 == n_subframes ) /* First TCX10/5 subframe */ + { + lsp2a_stab( lspmid_q, A_q, M ); + } + else + { + lsp2a_stab( lsp_q, A_q, M ); + } + + if ( hTcxEnc->tcx_lpc_shaped_ari ) + { + basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); + } + + bitsAvailable -= nbits_lpc[n]; + + /* Shape spectrum */ + ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); + + st->last_core = st->core; + } + + st->last_core = last_core_orig; + + /*--------------------------------------------------------------------------------* + * Write LPC parameters + *--------------------------------------------------------------------------------*/ + + writeLPCparam( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); + + assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); + + /*--------------------------------------------------------------* + * Run TCX10/20 Core + *---------------------------------------------------------------*/ + + hTcxEnc->measuredBwRatio_flt = 1.f; + + for ( n = 0; n < n_subframes; n++ ) + { + target_bits[n] = ( bitsAvailable + ( n_subframes - 1 ) - n ) / n_subframes - tnsBits[n]; + + if ( st->enablePlcWaveadjust && ( n == n_subframes - 1 ) ) + { + target_bits[n] -= 1; + } + if ( n == 0 ) + { + target_bits[n] -= ltpBits; + } + + /* Run TCX20/10 encoder */ + QuantizeSpectrum( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + n * st->L_frame / n_subframes, target_bits[n], tnsSize[n], param_core + n * NPRM_DIV, n, &hm_cfg[n], vad_hover_flag ); + } + + /* Update tcx overlap mode */ + st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; + + coder_tcx_post( st, A_q, Aw ); + + if ( st->enableTcxLpc ) + { + E_LPC_lsp_unweight_float( lsp_tcx_q, lsp_q, lsf_q, 1.0f / st->gamma_flt ); /* Update lsf_q for encoderSideLossSimulation() */ + } + + /* Update lsp/lsf memory */ + if ( st->enableTcxLpc && st->core != ACELP_CORE ) + { + /* Update lsf / lsp memory */ + mvr2r( lsf_tcx_q, st->lsf_old, M ); + mvr2r( lsp_tcx_q, st->lsp_old, M ); + st->envWeighted = 1; + + /* Update ACELP quantizer state */ + lsf_update_memory_float( st->narrowBand, st->lsf_old, st->mem_MA, st->mem_MA ); + st->pstreaklen = 0; + st->streaklimit = 1.0f; + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf( st->element_mode, st->core_brate, st->lsf_old, st->clip_var, 0 ); + mvr2r( st->lsf_old, st->mem_AR, M ); + } + else + { + mvr2r( lsf_q, st->lsf_old, M ); + mvr2r( lsp_q, st->lsp_old, M ); + } + + if ( st->Opt_DTX_ON && !st->tcxonly && st->hTdCngEnc != NULL ) + { + /* update CNG parameters in active frames */ + if ( st->bwidth == NB && st->enableTcxLpc && st->core != ACELP_CORE ) + { + float buf[L_LP], res[L_FRAME], A[M + 1], r[M + 1], tmp, lsptmp[M]; + + assert( st->L_frame == L_FRAME ); + + mvr2r( st->synth_flt + L_FRAME - L_LP, buf, L_LP ); + tmp = st->synth_flt[L_FRAME - L_LP - 1]; + preemph( buf, st->preemph_fac_flt, L_LP, &tmp ); + autocorr( buf, r, M, L_LP, LP_assym_window, 0, 0, 0 ); + lag_wind_flt( r, M, INT_FS_12k8, LAGW_WEAK ); + lev_dur( A, r, M, NULL ); + a2lsp_stab( A, lsptmp, lsp_new ); + residu( A, M, buf + L_LP - L_FRAME, res, L_FRAME ); + + cng_params_upd( lsptmp, res, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ, ENC, st->hTdCngEnc->ho_env_circ, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); + } + else + { + cng_params_upd( lsp_new, st->hLPDmem->old_exc_flt + L_EXC_MEM - st->L_frame, st->L_frame, &st->hTdCngEnc->ho_circ_ptr, st->hTdCngEnc->ho_ener_circ, &st->hTdCngEnc->ho_circ_size, st->hTdCngEnc->ho_lsp_circ, ENC, st->hTdCngEnc->ho_env_circ, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hDtxEnc->last_active_brate, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); + } + + if ( st->L_frame == L_FRAME ) + { + /* store LSPs@16k, potentially to be used in CNG@16k */ + mvr2r( st->lsp_old16k, &( st->hTdCngEnc->ho_lsp_circ2[( st->hTdCngEnc->ho_circ_ptr ) * M] ), M ); + } + + /* Set 16k LSP flag for CNG buffer */ + st->hTdCngEnc->ho_16k_lsp[st->hTdCngEnc->ho_circ_ptr] = ( st->L_frame == L_FRAME ? 0 : 1 ); + + /* efficient DTX hangover control */ + if ( st->hTdCngEnc->burst_ho_cnt > 1 ) + { + dtx_hangover_control( st, lsp_new ); + } + } + + /*--------------------------------------------------------------------------------* + * Encode TCX20/10 parameters + *--------------------------------------------------------------------------------*/ + + writeTCXparam( st, hBstr, hm_cfg, param_core, nbits_header, nbits_start, nbits_lpc[0] + nbits_lpc[1], NULL, NULL, NULL, -1 ); + + total_nbbits = hBstr->nb_bits_tot - nbits_start; + + if ( param_core[1 + NOISE_FILL_RANGES] != 0 ) + { + set_f( pitch_buf, hTcxEnc->tcxltp_pitch_int + (float) hTcxEnc->tcxltp_pitch_fr / (float) st->pit_res_max, NB_SUBFR16k ); + } + else + { + set_f( pitch_buf, L_SUBFR, NB_SUBFR16k ); + } + + pop_wmops(); + return; +} +#endif + + +/*-------------------------------------------------------------------* + * ivas_acelp_tcx20_switching() + * + * Open-loop ACELP/TCX20 core decision + *-------------------------------------------------------------------*/ + +/*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ +#ifndef IVAS_FLOAT_FIXED +int16_t ivas_acelp_tcx20_switching( + Encoder_State *st, /* i/o: encoder state structure */ + const float *inp, /* i : new input signal */ + const float *wsp, /* i : input weighted signal */ + const float non_staX, /* i : unbound non-stationarity for sp/mu clas.*/ + const float *pitch_fr, /* i : fraction pitch values */ + const float *voicing_fr, /* i : fractional voicing values */ + const float currFlatness, /* i : flatness */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + const float stab_fac, /* i : LP filter stability */ + float *res_cod_SNR_M, + const int16_t flag_16k_smc /* i : flag to compute parameters with 16kHz core */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + int16_t i, j; + float A_q_tcx[NB_SUBFR16k * ( M + 1 )]; float dsnr, snr_tcx, snr_acelp; int16_t iter; float xn_buf[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; @@ -1208,276 +1284,852 @@ int16_t ivas_acelp_tcx20_switching( float y[N_MAX]; /* Initialization */ - L_frame = flag_16k_smc ? st->L_frame : L_FRAME; + L_frame = flag_16k_smc ? st->L_frame : L_FRAME; + L_frame_tmp = L_frame; + + x = hTcxEnc->spectrum_long; + + /* Check minimum pitch for quantization */ + for ( i = 0; i < 4; i++ ) + { + pitch_fr_local[i] = pitch_fr[i]; + voicing_fr_local[i] = voicing_fr[i]; + } + + lsp2a_stab( lsp_mid, A_q_tcx, M ); + + /*--------------------------------------------------------------* + * Estimate TCX SNR + *---------------------------------------------------------------*/ + + target = 850.f; + if ( flag_16k_smc ) + { + tcx_offset = st->hTcxCfg->tcx_offset; + + if ( st->last_core == ACELP_CORE ) + { + L_frame += tcx_offset; + + if ( st->hTcxCfg->lfacNext < 0 ) + { + L_frame -= st->hTcxCfg->lfacNext; + tcx_offset = st->hTcxCfg->lfacNext; + } + else + { + tcx_offset = 0; + } + } + + overlap = st->hTcxCfg->tcx_mdct_window_delay; + mvr2r( st->hTcxCfg->tcx_mdct_window_flt, window, L_LOOK_16k ); + } + else + { + overlap = L_LOOK_12k8; + tcx_offset = ( overlap >> 1 ); + mdct_window_sine_flt( window, INT_FS_12k8, overlap, FULL_OVERLAP, st->element_mode ); + + if ( st->last_core == ACELP_CORE ) + { + L_frame += L_frame / 4; + tcx_offset -= L_frame / 4; + } + } + mvr2r( inp - ( overlap >> 1 ) + tcx_offset, xn_buf, L_frame + overlap ); + + if ( st->last_core == ACELP_CORE ) + { + if ( ( tcx_offset < 0 && flag_16k_smc ) || !flag_16k_smc ) + { + set_f( xn_buf, 0.0f, overlap >> 1 ); + } + } + else + { + for ( i = 0; i < overlap; i++ ) + { + xn_buf[i] *= window[i]; + } + } + + for ( i = 0; i < overlap; i++ ) + { + xn_buf[L_frame + i] *= window[overlap - 1 - i]; + } + + TCX_MDCT_flt( xn_buf, x, overlap, L_frame - overlap, overlap, st->element_mode ); + + for ( i = 0; i < L_frame; i++ ) + { + x[i] *= (float) L_frame * inv_sqrt( 2 * NORM_MDCT_FACTOR ); + y[i] = x[i]; + } + + weight_a( A_q_tcx, Ap, GAMMA1_FLT, M ); + + lpc2mdct_flt( Ap, M, gainlpc, FDNS_NPTS, 0 ); + + mdct_preShaping( x, L_frame, gainlpc ); + + for ( i = 0; i < L_frame; i += 4 ) + { + ener = 0.01f + x[i] * x[i] + x[i + 1] * x[i + 1] + x[i + 2] * x[i + 2] + x[i + 3] * x[i + 3]; + en[i / 4] = 9.0f + 10.0f * log10f( ener ); + } + + fac = 128.0f; + offset = fac; + + for ( iter = 0; iter < 10; iter++ ) + { + fac *= 0.5f; + offset -= fac; + ener = 0.0f; + + for ( i = 0; i < L_frame / 4; i++ ) + { + tmp = en[i] - offset; + + if ( tmp > 3.0f ) + { + ener += tmp; + } + + if ( ener > target ) + { + offset += fac; + break; + } + } + } + + if ( offset <= 32.f ) + { + offset = -128.f; + } + + sqGain = powf( 10.0f, offset / 20.0f ); + ener = sqGain * sqGain / 12.f * sqrtf( 2.f ) / (float) L_frame; + + if ( !flag_16k_smc ) + { + const int16_t *bands; + const int16_t bands_20[8] = { 0, 5, 9, 19, 34, 51, 81, 111 }; + const int16_t bands_25[8] = { 0, 4, 7, 15, 28, 40, 65, 89 }; + float nrg_s, nrg_n; + + /*Approximate SNR of TCX*/ + set_f( x, sqrtf( ener ), L_frame ); + mdct_noiseShaping_flt( x, L_frame, gainlpc, FDNS_NPTS ); + + if ( st->last_core != ACELP_CORE ) + { + /*25Hz resolution*/ + bands = bands_25; + } + else + { + /*20Hz resolution*/ + bands = bands_20; + } + + for ( iter = 0; iter < 7; iter++ ) + { + nrg_s = 1e-6f; + nrg_n = 1e-6f; + for ( i = bands[iter]; i < bands[iter + 1]; i++ ) + { + nrg_s += y[i] * y[i]; + nrg_n += x[i] * x[i]; + } + res_cod_SNR_M[iter] = nrg_s / nrg_n; + } + } + + snr_tcx = 0.0f; + pt_ener_sfr = ener_sfr; + + L_loop = flag_16k_smc ? L_frame_tmp : L_frame; + + for ( i = 0; i < L_loop; i += L_SUBFR ) + { + *pt_ener_sfr = sum2_f( wsp + i, L_SUBFR ) + 1e-6f; + snr_tcx += log10f( *pt_ener_sfr / ( ener * L_SUBFR ) ); + pt_ener_sfr++; + } + snr_tcx *= ( (float) ( 10 * L_SUBFR ) ) / (float) L_loop; + + + /*--------------------------------------------------------------* + * Estimate ACELP SNR + *---------------------------------------------------------------*/ + + if ( flag_16k_smc ) + { + scale = 0.092f; + } + else + { + scale = 0.059f; + } + + snr_acelp = 0.0f; + fac = flag_16k_smc ? (float) st->sr_core / (float) INT_FS_12k8 : 1.0f; + L_loop = flag_16k_smc ? L_frame_tmp : L_FRAME; + + pt_ener_sfr = ener_sfr; + for ( i = 0; i < L_loop; i += L_SUBFR ) + { + T0 = (int16_t) ( ( fac * pitch_fr_local[(int16_t) ( (float) ( i / L_SUBFR ) / fac + 0.5f )] ) + 0.5f ); + gain = get_gain_flt( wsp + i, wsp + i - T0, L_SUBFR, NULL ); + noise = 1e-6f; + for ( j = 0; j < L_SUBFR; j++ ) + { + tmp = wsp[i + j] - gain * wsp[i + j - T0]; + noise += tmp * tmp; + } + + noise *= scale; + snr_acelp += log10f( *pt_ener_sfr / noise ); + pt_ener_sfr++; + } + + snr_acelp *= ( (float) ( 10 * L_SUBFR ) ) / (float) L_loop; + + + /*--------------------------------------------------------------* + * Switching Decision + *---------------------------------------------------------------*/ + + dsnr = 0.0f; + /* hysteresis for very small SNR differences between ACELP and TCX */ + + /* try to use TCX instead of ACELP on temporally stationary frames */ + if ( ( snr_acelp > snr_tcx ) && ( snr_acelp < snr_tcx + 2.0f ) && + ( st->prevTempFlatness + currFlatness < 3.25f || stab_fac == 1.0f || + ( !flag_16k_smc && st->sp_aud_decision0 > 0 && st->prevTempFlatness + currFlatness < 20.f ) ) && + ( st->Nb_ACELP_frames <= 6 ) ) + { + dsnr = -2.0f; + } + + /* try to use ACELP instead of TCX on transient and "buzzy" frames */ + if ( ( snr_acelp < snr_tcx ) && + ( snr_acelp > snr_tcx - 2.0f ) && + ( st->prevTempFlatness + currFlatness > 3.25f ) && + ( st->Nb_ACELP_frames >= 6 ) ) + { + dsnr = 2.0f; + } + if ( ( !flag_16k_smc ) && ( offset < 74.0f ) && ( non_staX > 5.0f ) && ( snr_acelp >= snr_tcx - 4 ) && st->Nb_ACELP_frames >= 1 && ( ( ( st->hSpMusClas->lps > st->hSpMusClas->lpm ) && mean( voicing_fr_local, 4 ) >= 0.3f ) || ( st->Nb_ACELP_frames >= 6 && ( st->hSpMusClas->lps > st->hSpMusClas->lpm - 1.5f ) ) ) && ( st->sp_aud_decision0 == 0 ) && st->vad_flag ) + { + /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/ + dsnr = 4.0f; + } + + if ( st->flag_noisy_speech_snr ) + { + + if ( st->vad_flag || st->Opt_DTX_ON ) + { + dsnr += 2.f; + } + else + { + dsnr -= 2.f; + } + } + + /* Select ACELP or TCX */ + if ( ( snr_acelp + dsnr > snr_tcx ) && ( st->sp_aud_decision0 == 0 || st->prevTempFlatness + currFlatness > 3.25f ) ) + { + smc_dec_ol = 0; + } + else + { + smc_dec_ol = 2; + } + + + st->prevTempFlatness = currFlatness; + + return smc_dec_ol; +} +#else +Word16 ivas_acelp_tcx20_switching_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *inp_fx, + Word16 q_inp, + Word16 *wsp, /*q_inp i : input weighted signal */ + Word16 non_staX, /*Q8 i : unbound non-stationarity for sp/mu clas*/ + Word16 *pitch_fr, /*Q6 i : fraction pitch values */ + Word16 *voicing_fr, /*Q15 i : fractional voicing values */ + Word16 currFlatness, /*Q7 i : flatness */ + Word16 lsp_mid[M], /*Q15 i : LSPs at the middle of the frame */ + Word16 stab_fac, /* i : LP filter stability */ + Word32 *res_cod_SNR_M, + Word16 *res_cod_SNR_M_e, + Word16 *tcx_mdct_window_fx, + const Word16 flag_16k_smc /* i : flag to compute parameters with 16kHz core */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 i, j; + Word32 dsnr; + Word32 snr_acelp; + Word16 i2, T0; + Word16 pitch_fr_local[4], voicing_fr_local[4]; + Word16 smc_dec_ol; + Word16 L_frame, L_frame_tmp, L_loop; + Word16 overlap; + Word16 tcx_offset; + Word16 tmp16, s, L_frame_4, iter; + Word32 *x_fx, tmp32, ener, fac, offset; + Word16 e_x, ener_e, scale_A, Q_A_q_tcx; + Word16 gainlpc_fx[FDNS_NPTS]; + Word16 gainlpc_e[FDNS_NPTS]; + Word16 gainlpc_noinv[FDNS_NPTS]; + Word16 gainlpc_noinv_e[FDNS_NPTS]; + Word16 Ap_fx[M + 1]; + Word16 A_q_tcx_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 window_fx[L_LOOK_16k]; + PWord16 window_p_fx[L_LOOK_16k]; + Word16 xn_buf_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + Word16 tcx_mdct_window_fx_local[L_LOOK_16k], scale; + Word32 en[N_MAX / 4]; + Word32 offset_tcx, target; + Word32 y_fx[N_MAX]; + Word32 tcx_snr; + Flag Overflow; + Word32 gain, noise; + Word32 *pt_ener_sfr, ener_sfr[NB_SUBFR16k]; + + /* Initialization */ + IF( flag_16k_smc ) + { + L_frame = st->L_frame; + move16(); + } + ELSE + { + L_frame = L_FRAME; + move16(); + } + L_frame_tmp = L_frame; + move16(); + Copy( tcx_mdct_window_fx, tcx_mdct_window_fx_local, L_LOOK_16k ); + x_fx = hTcxEnc->spectrum_long_fx; + move32(); + e_x = 31 - 15; + move16(); - x = hTcxEnc->spectrum_long; /* Check minimum pitch for quantization */ - for ( i = 0; i < 4; i++ ) + FOR( i = 0; i < 4; i++ ) { pitch_fr_local[i] = pitch_fr[i]; + move16(); voicing_fr_local[i] = voicing_fr[i]; + move16(); } - lsp2a_stab( lsp_mid, A_q_tcx, M ); + basop_E_LPC_f_lsp_a_conversion( lsp_mid, A_q_tcx_fx, M ); + Q_A_q_tcx = sub( 14, norm_s( A_q_tcx_fx[0] ) ); + scale_A = sub( Q12, Q_A_q_tcx ); + Copy_Scale_sig( A_q_tcx_fx, A_q_tcx_fx, M + 1, scale_A ); /*--------------------------------------------------------------* * Estimate TCX SNR *---------------------------------------------------------------*/ - target = 850.f; - if ( flag_16k_smc ) + target = L_add( 0x11A5D28, 0 ); /* 0x11A5D28 -> 850.f * log2(10)/10 (Q16) */ + IF( flag_16k_smc ) { tcx_offset = st->hTcxCfg->tcx_offset; + move16(); - if ( st->last_core == ACELP_CORE ) + IF( st->last_core == ACELP_CORE ) { - L_frame += tcx_offset; + L_frame = add( L_frame, tcx_offset ); - if ( st->hTcxCfg->lfacNext < 0 ) + IF( st->hTcxCfg->lfacNext < 0 ) { - L_frame -= st->hTcxCfg->lfacNext; + L_frame = sub( L_frame, st->hTcxCfg->lfacNext ); tcx_offset = st->hTcxCfg->lfacNext; + move16(); } - else + ELSE { tcx_offset = 0; + move16(); } } overlap = st->hTcxCfg->tcx_mdct_window_delay; - mvr2r( st->hTcxCfg->tcx_mdct_window_flt, window, L_LOOK_16k ); + move16(); + Copy( tcx_mdct_window_fx_local, window_fx, L_LOOK_16k ); // Q15 } - else + ELSE { overlap = L_LOOK_12k8; - tcx_offset = ( overlap >> 1 ); - mdct_window_sine_flt( window, INT_FS_12k8, overlap, FULL_OVERLAP, st->element_mode ); + move16(); + tcx_offset = shr( overlap, 1 ); + move16(); + FOR( i = 0; i < shr( overlap, 1 ); i++ ) + { + st->hTcxCfg->tcx_mdct_window[i].v.re = tcx_mdct_window_fx_local[overlap - 1 - i]; + st->hTcxCfg->tcx_mdct_window[i].v.im = tcx_mdct_window_fx_local[i]; + move16(); + move16(); + } + mdct_window_sine_IVAS_updated( window_p_fx, INT_FS_12k8, overlap, FULL_OVERLAP, st->element_mode ); + FOR( i = 0; i < shr( overlap, 1 ); i++ ) + { + window_fx[overlap - 1 - i] = window_p_fx[i].v.re; + window_fx[i] = window_p_fx[i].v.im; + move16(); + move16(); + } - if ( st->last_core == ACELP_CORE ) + IF( st->last_core == ACELP_CORE ) { - L_frame += L_frame / 4; - tcx_offset -= L_frame / 4; + L_frame = add( L_frame, shr( L_frame, 2 ) ); + tcx_offset = sub( tcx_offset, shr( L_frame, 2 ) ); } } - mvr2r( inp - ( overlap >> 1 ) + tcx_offset, xn_buf, L_frame + overlap ); - if ( st->last_core == ACELP_CORE ) + Copy( inp_fx + sub( tcx_offset, shr( overlap, 1 ) ), xn_buf_fx, add( L_frame, overlap ) ); + + L_frame_4 = shr( L_frame, 2 ); + IF( st->last_core == ACELP_CORE ) { - if ( ( tcx_offset < 0 && flag_16k_smc ) || !flag_16k_smc ) + test(); + test(); + IF( ( ( tcx_offset < 0 ) && flag_16k_smc ) || !flag_16k_smc ) { - set_f( xn_buf, 0.0f, overlap >> 1 ); + set16_zero_fx( xn_buf_fx, shr( overlap, 1 ) ); } } - else + ELSE { - for ( i = 0; i < overlap; i++ ) + FOR( i = 0; i < overlap; i++ ) { - xn_buf[i] *= window[i]; + xn_buf_fx[i] = mult( xn_buf_fx[i], window_fx[i] ); + move16(); } } - for ( i = 0; i < overlap; i++ ) + FOR( i = 0; i < overlap; i++ ) { - xn_buf[L_frame + i] *= window[overlap - 1 - i]; + xn_buf_fx[L_frame + i] = mult( xn_buf_fx[L_frame + i], window_fx[overlap - 1 - i] ); + move16(); } + e_x = 16; + move16(); + TCX_MDCT( xn_buf_fx, x_fx, &e_x, overlap, sub( L_frame, overlap ), overlap, st->element_mode ); + scale_A = getScaleFactor32( x_fx, L_frame ); + Copy_Scale_sig32( x_fx, x_fx, L_frame, scale_A ); + e_x = sub( e_x, scale_A ); - TCX_MDCT_flt( xn_buf, x, overlap, L_frame - overlap, overlap, st->element_mode ); - - for ( i = 0; i < L_frame; i++ ) + tmp16 = mult_r( shl( L_frame, 5 ), 29309 /*16*0.0559017 Q15*/ ); /* L_frame / sqrt(2*NORM_MDCT_FACTOR); Q9 */ + FOR( i = 0; i < L_frame; i++ ) { - x[i] *= (float) L_frame * inv_sqrt( 2 * NORM_MDCT_FACTOR ); - y[i] = x[i]; + x_fx[i] = Mpy_32_16_1( x_fx[i], tmp16 ); + y_fx[i] = x_fx[i]; + move32(); + move32(); } + e_x = add( e_x, 6 ); - weight_a( A_q_tcx, Ap, GAMMA1_FLT, M ); - - lpc2mdct_flt( Ap, M, gainlpc, FDNS_NPTS, 0 ); + basop_weight_a( A_q_tcx_fx, Ap_fx, 30147 /*0.92 in Q15*/ ); + basop_lpc2mdct( Ap_fx, M, gainlpc_fx, gainlpc_e, gainlpc_noinv, gainlpc_noinv_e ); - mdct_preShaping( x, L_frame, gainlpc ); + mdct_shaping( x_fx, L_frame, gainlpc_fx, gainlpc_e ); - for ( i = 0; i < L_frame; i += 4 ) + FOR( i = 0; i < L_frame_4; i++ ) { - ener = 0.01f + x[i] * x[i] + x[i + 1] * x[i + 1] + x[i + 2] * x[i + 2] + x[i + 3] * x[i + 3]; - en[i / 4] = 9.0f + 10.0f * log10f( ener ); + /* normalization */ + s = 31; + move16(); + + tmp16 = norm_l( x_fx[0] ); + if ( x_fx[0] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x_fx[1] ); + if ( x_fx[1] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x_fx[2] ); + if ( x_fx[2] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x_fx[3] ); + if ( x_fx[3] != 0 ) + s = s_min( s, tmp16 ); + + s = sub( s, 2 ); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l( 1 ); + + tmp16 = extract_h( L_shl( x_fx[0], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x_fx[1], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x_fx[2], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x_fx[3], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + s = shl( sub( e_x, s ), 1 ); + + tmp32 = L_add( BASOP_Util_Log2( ener ), L_shl( L_deposit_l( s ), 25 ) ); /* log2, 6Q25 */ + tmp32 = L_shr( tmp32, 9 ); /* 15Q16 */ + en[i] = L_add( tmp32, 0x2FD5F ); /* 0x2FD5F -> 9.f * log2(10)/10 (15Q16) */ + move32(); + + x_fx += 4; } - fac = 128.0f; - offset = fac; + fac = L_add( 0x2A854B, 0 ); /* 0x2A854B -> 128.f * log2(10)/10 (15Q16) */ + offset = L_add( fac, 0 ); - for ( iter = 0; iter < 10; iter++ ) + FOR( iter = 0; iter < 10; iter++ ) { - fac *= 0.5f; - offset -= fac; - ener = 0.0f; + fac = L_shr( fac, 1 ); + offset = L_sub( offset, fac ); + ener = L_deposit_l( 0 ); - for ( i = 0; i < L_frame / 4; i++ ) + FOR( i = 0; i < L_frame_4; i += 4 ) { - tmp = en[i] - offset; + tmp32 = L_sub( en[i], offset ); - if ( tmp > 3.0f ) + if ( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 3.f * log2(10)/10 */ { - ener += tmp; + ener = L_add( ener, tmp32 ); } - if ( ener > target ) + tmp32 = L_sub( en[i + 1], offset ); + + if ( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 3.f * log2(10)/10 */ { - offset += fac; - break; + ener = L_add( ener, tmp32 ); + } + + tmp32 = L_sub( en[i + 2], offset ); + + if ( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add( ener, tmp32 ); + } + + tmp32 = L_sub( en[i + 3], offset ); + + if ( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add( ener, tmp32 ); + } + + IF( GT_32( ener, target ) ) + { + offset = L_add( offset, fac ); + BREAK; } } } - if ( offset <= 32.f ) + if ( LE_32( offset, 0xAA153 ) ) /* 0xAA153 -> 32.f * log2(10)/10 */ { - offset = -128.f; + offset = L_add( 0xFFD57AB5, 0 ); /* 0xFFD57AB5 -> -128.f * log2(10)/10; */ } + offset_tcx = offset; + move32(); - sqGain = powf( 10.0f, offset / 20.0f ); - ener = sqGain * sqGain / 12.f * sqrtf( 2.f ) / (float) L_frame; + s = add( extract_h( offset ), 1 ); + offset = L_sub( L_and( offset, 0xFFFF ), 0x10000 ); + ener = BASOP_Util_InvLog2( L_shl( offset, 9 ) ); - if ( !flag_16k_smc ) - { - const int16_t *bands; - const int16_t bands_20[8] = { 0, 5, 9, 19, 34, 51, 81, 111 }; - const int16_t bands_25[8] = { 0, 4, 7, 15, 28, 40, 65, 89 }; - float nrg_s, nrg_n; + ener = Mpy_32_16_1( Mpy_32_16_1( ener, 0x78AE ), getInvFrameLen( L_frame ) ); /* 0x78AE -> sqrt(2)/12 (Q18) */ + ener_e = sub( s, 9 ); + IF( !flag_16k_smc ) + { + const Word16 *bands; + const Word16 bands_20[8] = { 0, 5, 9, 19, 34, 51, 81, 111 }; + const Word16 bands_25[8] = { 0, 4, 7, 15, 28, 40, 65, 89 }; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + Word32 nrg_s, nrg_n; + Word16 temp_e, e_num, e_den, temp_ene_e; + temp_ene_e = ener_e; + tmp32 = Sqrt32( ener, &temp_ene_e ); /*Approximate SNR of TCX*/ - set_f( x, sqrtf( ener ), L_frame ); - mdct_noiseShaping_flt( x, L_frame, gainlpc, FDNS_NPTS ); + set32_fx( x_fx, tmp32, L_frame ); /* ener_e */ + mdct_noiseShaping_ivas_fx( x_fx, &temp_ene_e, L_frame, gainlpc_noinv, gainlpc_noinv_e ); - if ( st->last_core != ACELP_CORE ) + IF( st->last_core != ACELP_CORE ) { /*25Hz resolution*/ bands = bands_25; } - else + ELSE { /*20Hz resolution*/ bands = bands_20; } - for ( iter = 0; iter < 7; iter++ ) + FOR( iter = 0; iter < 7; iter++ ) { - nrg_s = 1e-6f; - nrg_n = 1e-6f; - for ( i = bands[iter]; i < bands[iter + 1]; i++ ) + nrg_s = L_deposit_l( 1 ); + nrg_n = L_deposit_l( 1 ); + e_num = 0; + move16(); + e_den = 0; + move16(); + + FOR( i = bands[iter]; i < bands[iter + 1]; i++ ) { - nrg_s += y[i] * y[i]; - nrg_n += x[i] * x[i]; + nrg_s = BASOP_Util_Add_Mant32Exp( nrg_s, e_num, Mpy_32_32( y_fx[i], y_fx[i] ), shl( e_x, 1 ), &e_num ); + nrg_n = BASOP_Util_Add_Mant32Exp( nrg_n, e_den, Mpy_32_32( x_fx[i], x_fx[i] ), shl( temp_ene_e, 1 ), &e_den ); } - res_cod_SNR_M[iter] = nrg_s / nrg_n; + res_cod_SNR_M[iter] = BASOP_Util_Divide3232_Scale_cadence( nrg_s, nrg_n, &temp_e ); + move32(); + res_cod_SNR_M_e[iter] = add( temp_e, sub( e_num, e_den ) ); + move16(); } } - snr_tcx = 0.0f; pt_ener_sfr = ener_sfr; + tcx_snr = L_deposit_l( 0 ); - L_loop = flag_16k_smc ? L_frame_tmp : L_frame; - - for ( i = 0; i < L_loop; i += L_SUBFR ) + L_loop = L_frame; + move16(); + if ( flag_16k_smc ) { - *pt_ener_sfr = sum2_f( wsp + i, L_SUBFR ) + 1e-6f; - snr_tcx += log10f( *pt_ener_sfr / ( ener * L_SUBFR ) ); - pt_ener_sfr++; + L_loop = L_frame_tmp; + move16(); } - snr_tcx *= ( (float) ( 10 * L_SUBFR ) ) / (float) L_loop; + Word16 temp32_e = 0; + move16(); + Word32 temp_energy = L_add( BASOP_Util_Log2( ener ), L_shl( L_deposit_l( ener_e ), 25 ) ); + temp_energy = L_add( temp_energy, 201326592 /* 6 in Q25*/ ); + temp_energy = L_shr( temp_energy, 9 ); /*temp_energy is log(( ener * L_SUBFR ))*/ + FOR( i = 0; i < L_loop; i += L_SUBFR ) + { + tmp32 = L_deposit_l( 0 ); + FOR( j = 0; j < L_SUBFR; j++ ) + { + tmp32 = BASOP_Util_Add_Mant32Exp( tmp32, temp32_e, L_mult0( wsp[i + j], wsp[i + j] ), sub( 31, add( q_inp, q_inp ) ), &temp32_e ); + } + IF( tmp32 == 0 ) + { + *pt_ener_sfr = -668739840; /* 0xFFEC1185 -> log2(1e-6) in 6Q25 */ + move32(); + tmp32 = 0xFFEC1185; /* 0xFFEC1185 -> log2(1e-6) in 15Q16 */ + move32(); + } + ELSE + { + tmp32 = L_add( BASOP_Util_Log2( tmp32 ), L_shl( L_deposit_l( temp32_e ), 25 ) ); + *pt_ener_sfr = tmp32; + move32(); + tmp32 = L_shr( tmp32, 9 ); /* 15Q16 */ + } + tcx_snr = L_sub( L_add( tcx_snr, tmp32 ), temp_energy ); /*15Q16*/ + pt_ener_sfr++; + } + tmp16 = BASOP_Util_Divide1616_Scale( L_SUBFR, L_loop, &temp32_e ); + tmp16 = shl( tmp16, temp32_e ); + tcx_snr = Mpy_32_16_1( tcx_snr, tmp16 ); + tcx_snr = L_shl( Mpy_32_16_1( tcx_snr, 0x6054 /* 0x6054 -> 10/log2(10) (2Q13) */ ), 2 ); /* Q16*/ /*--------------------------------------------------------------* * Estimate ACELP SNR *---------------------------------------------------------------*/ - if ( flag_16k_smc ) + pt_ener_sfr = ener_sfr; + IF( flag_16k_smc ) { - scale = 0.092f; + scale = 3014; // Q15 + move16(); } - else + ELSE { - scale = 0.059f; + scale = 1933; // Q15 + move16(); } - snr_acelp = 0.0f; - fac = flag_16k_smc ? (float) st->sr_core / (float) INT_FS_12k8 : 1.0f; - L_loop = flag_16k_smc ? L_frame_tmp : L_FRAME; - - pt_ener_sfr = ener_sfr; - for ( i = 0; i < L_loop; i += L_SUBFR ) + tmp32 = L_deposit_l( 0 ); + temp_energy = L_deposit_l( 0 ); + ener_e = 0; + move16(); + L_loop = L_FRAME; + move16(); + if ( flag_16k_smc ) { - T0 = (int16_t) ( ( fac * pitch_fr_local[(int16_t) ( (float) ( i / L_SUBFR ) / fac + 0.5f )] ) + 0.5f ); - gain = get_gain_flt( wsp + i, wsp + i - T0, L_SUBFR, NULL ); - noise = 1e-6f; - for ( j = 0; j < L_SUBFR; j++ ) + L_loop = L_frame_tmp; + move16(); + } + i2 = 0; + move16(); + FOR( i = 0; i < L_loop; i += L_SUBFR ) + { + test(); + IF( flag_16k_smc && EQ_32( st->sr_core, INT_FS_16k ) ) { - tmp = wsp[i + j] - gain * wsp[i + j - T0]; - noise += tmp * tmp; + T0 = shr( add( add( pitch_fr_local[mult_r( i2, 26214 /*(float)L_FRAME/(float)L_FRAME16k Q15*/ )], shr( pitch_fr_local[mult_r( i2, 26214 /*(float)L_FRAME/(float)L_FRAME16k Q15*/ )], 2 ) ), ( 1 << 5 ) ), 6 ); + } + ELSE + { + T0 = shr( add( pitch_fr_local[i2], ( 1 << 5 ) ), 6 ); } - noise *= scale; - snr_acelp += log10f( *pt_ener_sfr / noise ); - pt_ener_sfr++; - } + gain = get_gain2( wsp + i, wsp + sub( i, T0 ), L_SUBFR ); - snr_acelp *= ( (float) ( 10 * L_SUBFR ) ) / (float) L_loop; + noise = L_deposit_l( 1 ); + FOR( j = 0; j < L_SUBFR; j++ ) + { + tmp16 = round_fx_o( L_shl_o( Mpy_32_16_r( gain, wsp[i + j - T0] ), 15, &Overflow ), &Overflow ); // q_in + tmp16 = sub_o( wsp[i + j], tmp16, &Overflow ); // q_in + noise = L_mac0_o( noise, tmp16, tmp16, &Overflow ); // 2*q_in// + } + test(); + IF( noise == 0 || EQ_32( noise, 1 ) ) + { + IF( flag_16k_smc ) + { + tmp32 = -784301312; // Q25 + move32(); + } + ELSE + { + tmp32 = -805809664; // Q25 + move32(); + } + } + ELSE + { + noise = Mpy_32_16_1( noise, scale ); + tmp32 = L_add( BASOP_Util_Log2( noise ), L_shl( sub( 31, add( q_inp, q_inp ) ), 25 ) ); // Q25 + } + tmp32 = L_sub( *pt_ener_sfr, tmp32 ); // Q25 + temp_energy = BASOP_Util_Add_Mant32Exp( tmp32, 6, temp_energy, ener_e, &ener_e ); + pt_ener_sfr++; + i2 = add( i2, 1 ); + } + tmp16 = BASOP_Util_Divide1616_Scale( L_SUBFR, L_loop, &temp32_e ); + tmp16 = shl( tmp16, temp32_e ); + tmp32 = Mpy_32_16_1( temp_energy, tmp16 ); /*ener_e*/ + tmp32 = L_shr( Mpy_32_16_1( tmp32, 0x6054 /* 0x6054 -> 10/log2(10) (2Q13) */ ), sub( 13, ener_e ) ); /* Q16*/ + snr_acelp = tmp32; /*--------------------------------------------------------------* * Switching Decision *---------------------------------------------------------------*/ - dsnr = 0.0f; + dsnr = 0; + move16(); /* hysteresis for very small SNR differences between ACELP and TCX */ /* try to use TCX instead of ACELP on temporally stationary frames */ - if ( ( snr_acelp > snr_tcx ) && ( snr_acelp < snr_tcx + 2.0f ) && - ( st->prevTempFlatness + currFlatness < 3.25f || stab_fac == 1.0f || - ( !flag_16k_smc && st->sp_aud_decision0 > 0 && st->prevTempFlatness + currFlatness < 20.f ) ) && - ( st->Nb_ACELP_frames <= 6 ) ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ( ( GT_32( snr_acelp, tcx_snr ) ) && + ( LT_32( snr_acelp, L_add( tcx_snr, 131072 /*2.0f Q16*/ ) ) ) && + ( LT_16( add_o( st->prevTempFlatness_fx, currFlatness, &Overflow ), 52 /*3.25f Q4*/ ) || EQ_16( stab_fac, 0x7fff ) || + ( !flag_16k_smc && ( st->sp_aud_decision0 > 0 ) && LT_16( add_sat( st->prevTempFlatness_fx, currFlatness ), 2560 /*20.f Q7*/ ) ) ) && + ( LE_16( st->Nb_ACELP_frames, 6 ) ) ) { - dsnr = -2.0f; + dsnr = -131072 /*-2.0f Q16*/; + move32(); } - /* try to use ACELP instead of TCX on transient and "buzzy" frames */ - if ( ( snr_acelp < snr_tcx ) && - ( snr_acelp > snr_tcx - 2.0f ) && - ( st->prevTempFlatness + currFlatness > 3.25f ) && - ( st->Nb_ACELP_frames >= 6 ) ) + test(); + test(); + test(); + if ( ( LT_32( snr_acelp, tcx_snr ) ) && + ( GT_32( snr_acelp, L_sub( tcx_snr, 131072 /*2.0f Q16*/ ) ) ) && + ( GT_16( add_sat( st->prevTempFlatness_fx, currFlatness ), 416 /*3.25f Q7*/ ) ) && + ( GE_16( st->Nb_ACELP_frames, 6 ) ) ) { - dsnr = 2.0f; + dsnr = 131072 /*2.0f Q16*/; + move32(); } - if ( ( !flag_16k_smc ) && ( offset < 74.0f ) && ( non_staX > 5.0f ) && ( snr_acelp >= snr_tcx - 4 ) && st->Nb_ACELP_frames >= 1 && ( ( ( st->hSpMusClas->lps > st->hSpMusClas->lpm ) && mean( voicing_fr_local, 4 ) >= 0.3f ) || ( st->Nb_ACELP_frames >= 6 && ( st->hSpMusClas->lps > st->hSpMusClas->lpm - 1.5f ) ) ) && ( st->sp_aud_decision0 == 0 ) && st->vad_flag ) + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ( ( !flag_16k_smc ) && ( LT_32( offset_tcx, 0x18950F ) ) && GT_16( non_staX, 1280 /*5.0f Q8*/ ) && ( GE_32( snr_acelp, L_sub( tcx_snr, 262144 /*4.0f in Q16*/ ) ) ) && GE_16( st->Nb_ACELP_frames, 1 ) && ( ( GT_16( st->hSpMusClas->lps_fx, st->hSpMusClas->lpm_fx ) && GE_16( shr( sum16_fx( voicing_fr_local, 4 ), 2 ), 9830 ) ) || ( GE_16( st->Nb_ACELP_frames, 6 ) && GT_16( st->hSpMusClas->lps_fx, sub( st->hSpMusClas->lpm_fx, 192 /*1.5in Q7*/ ) ) ) ) && ( st->sp_aud_decision0 == 0 ) && st->vad_flag ) { /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/ - dsnr = 4.0f; + dsnr = 262144; /*4.0f Q16*/ + move32(); } - if ( st->flag_noisy_speech_snr ) + IF( st->flag_noisy_speech_snr ) { - - if ( st->vad_flag || st->Opt_DTX_ON ) + test(); + IF( st->vad_flag || st->Opt_DTX_ON ) { - dsnr += 2.f; + dsnr = L_add( dsnr, 131072 /*2.0f Q16*/ ); } - else + ELSE { - dsnr -= 2.f; + dsnr = L_sub( dsnr, 131072 /*2.0f Q16*/ ); } } + /* Select ACELP or TCX */ - if ( ( snr_acelp + dsnr > snr_tcx ) && ( st->sp_aud_decision0 == 0 || st->prevTempFlatness + currFlatness > 3.25f ) ) + test(); + test(); + IF( GT_32( L_add( snr_acelp, dsnr ), tcx_snr ) && ( st->sp_aud_decision0 == 0 || GT_16( add_sat( st->prevTempFlatness_fx, currFlatness ), 416 /*3.25f Q7*/ ) ) ) { smc_dec_ol = 0; + move16(); } - else + ELSE { smc_dec_ol = 2; + move16(); } - - - st->prevTempFlatness = currFlatness; - + st->prevTempFlatness_fx = currFlatness; + move16(); return smc_dec_ol; } +#endif diff --git a/lib_enc/ivas_td_low_rate_enc.c b/lib_enc/ivas_td_low_rate_enc.c index 451506067602bca1ea3c5b04b50fc9e977c6882c..42cea4ce66215b04b1c5915984b9683151e8b727 100644 --- a/lib_enc/ivas_td_low_rate_enc.c +++ b/lib_enc/ivas_td_low_rate_enc.c @@ -41,6 +41,7 @@ #include "prot_fx.h" #include "prot_fx_enc.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "wmc_auto.h" @@ -288,6 +289,7 @@ void tdm_low_rate_enc( * Encode GC, 2 subframes mode *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void encod_gen_2sbfr( Encoder_State *st, /* i/o: state structure */ const float speech[], /* i : input speech */ @@ -472,3 +474,216 @@ void encod_gen_2sbfr( return; } +#else +void encod_gen_2sbfr( + Encoder_State *st, /* i/o: state structure */ + const Word16 speech[], /* i : input speech Q_new-1 */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes e(norm_s(Aw[0]+1)*/ + const Word16 Aq[], /* i : LP coefficients e(norm_s(Aw[0]+1)*/ + const Word16 *res, /* i : residual signal Q_new */ + Word16 *syn, /* i/o: core synthesis Q_new */ + Word16 *exc, /* i/o: current non-enhanced excitation Q_new-1 */ + Word16 *exc2, /* i/o: current enhanced excitation Q_new-1 */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe Q6 */ + Word16 *voice_factors, /* o : voicing factors Q15 */ + Word16 *bwe_exc, /* o : excitation for SWB TBE Q_new */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[], /* i : pitch values for primary channel Q4 */ + Word16 *Q_new ) +{ + Word16 xn[2 * L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[2 * L_SUBFR]; /* Target vector for codebook search */ + Word16 cn[2 * L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[2 * L_SUBFR + ( M + 1 )]; /* Impulse response vector */ + Word16 code[2 * L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1[2 * L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[2 * L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit; /* Pitch gain */ + Word16 voice_fac; /* Voicing factor */ + Word32 gain_code; /* Gain of code */ + Word16 gain_inov; /* inovation gain */ + Word16 L_frame, coder_type; /* L_frame; coder type */ + Word16 i, i_subfr; /* tmp variables */ + Word16 T0, T0_frac; /* close loop integer pitch and fractional part */ + Word16 T0_min, T0_max; /* pitch variables */ + Word16 *pt_pitch; /* pointer to floating pitch buffer */ + Word16 g_corr[6]; /* ACELP correl, values + gain pitch */ + // Word16 gains_mem[2 * ( NB_SUBFR - 1 )]; /* pitch gain and code gain from previous subframes */ + Word32 gc_mem[2 * ( NB_SUBFR - 1 )]; /* pitch gain and code gain from previous subframes */ + Word16 gp_mem[2 * ( NB_SUBFR - 1 )]; /* pitch gain and code gain from previous subframes */ + Word16 clip_gain; /* LSF clip gain */ + const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector*/ + Word32 norm_gain_code; + Word16 pitch_limit_flag; + Word16 error; + Word16 shift; + + LPD_state_HANDLE hLPDmem = st->hLPDmem; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + gain_pit = 0; + move16(); + gain_code = 0; + move16(); + error = 0; + move16(); + + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + + L_frame = L_FRAME; + move16(); + coder_type = GENERIC; + move16(); + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + + shift = 0; + move16(); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + FOR( i_subfr = 0; i_subfr < L_frame; i_subfr += 2 * L_SUBFR ) + { + /*----------------------------------------------------------------* + * Find the the excitation search target "xn" and innovation + * target in residual domain "cn" + * Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + + Copy( &res[i_subfr], &exc[i_subfr], 2 * L_SUBFR ); // Q_new + + // Scaling mem_syn buffer to Q_new - 1 from e_mem_syn + Scale_sig( &hLPDmem->mem_w0, M + 1, sub( add( *Q_new, hLPDmem->e_mem_syn ), Q16 ) ); // M + 1 to sync mem_syn exponent with mem_w0 exponent + hLPDmem->e_mem_syn = sub( Q16, *Q_new ); + + find_targets_ivas_fx( speech, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq, res, 2 * L_SUBFR, p_Aw, st->preemph_fac, xn, cn, h1 ); + + /*------------------------------------------------------------------------* + * Close-loop pitch search on the 1st and 3rd subfr only and quantization + * Adaptive exc. construction + *------------------------------------------------------------------------*/ + + *pt_pitch = pit_encode_ivas_fx( st->hBstr, st->acelp_cfg.pitch_bits, st->core_brate, 0, L_frame, coder_type, &pitch_limit_flag, i_subfr, exc, 2 * L_SUBFR, st->pitch, &T0_min, &T0_max, &T0, &T0_frac, h1, xn, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + + tbe_celp_exc_ivas( st->element_mode, st->idchan, L_frame, 2 * L_SUBFR, i_subfr, T0, T0_frac, &error, bwe_exc, st->tdm_LRTD_flag ); + + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, 2 * L_SUBFR + 1, inter4_2_fx_Q15, L_INTERPOL2, PIT_UP_SAMP ); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip_fx( st->element_mode, st->core_brate, st->voicing_fx, i_subfr, coder_type, xn, st->clip_var_fx, *Q_new ); // Q0 + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_filt_exc_enc_fx( MODE1, coder_type, i_subfr, exc, h1, xn, y1, xn2, 2 * L_SUBFR, L_frame, g_corr, clip_gain, &gain_pit, &st->acelp_cfg.ltf_mode ); + + /* update long-term pitch gain for speech/music classifier */ + st->hSpMusClas->lowrate_pitchGain = add( mult( 29491, st->hSpMusClas->lowrate_pitchGain ), mult( 3277, gain_pit ) ); // Q14 + move16(); + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode_ivas_fx( st, st->core_brate, 0, L_frame, st->last_L_frame, coder_type, st->bwidth, st->sharpFlag, i_subfr, -1, p_Aq, gain_pit, cn, exc, h1, hLPDmem->tilt_code, *pt_pitch, xn2, code, y2, &i, 2 * L_SUBFR, 0, *Q_new ); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + + gain_enc_lbr_ivas_fx( st->hBstr, st->acelp_cfg.gains_mode, coder_type, i_subfr, xn, y1, add( sub( *Q_new, 1 ), shift ), y2, code, &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, gc_mem, gp_mem, clip_gain, 2 * L_SUBFR ); + + IF( st->Opt_SC_VBR ) + { + IF( EQ_16( st->hSC_VBR->last_ppp_mode, 1 ) ) + { + /* SC-VBR - all other st->clip_var values will be updated even in a PPP frame */ + st->clip_var_fx[1] = gain_pit; + move16(); + } + } + + /*-----------------------------------------------------------------* + * update LP-filtered gains for the case of frame erasures + *-----------------------------------------------------------------*/ + + gp_clip_test_gain_pit_fx( st->element_mode, st->core_brate, gain_pit, st->clip_var_fx ); + + hLPDmem->tilt_code = est_tilt_ivas_fx( exc + i_subfr, gain_pit, code, gain_code, &voice_fac, *Q_new, 2 * L_SUBFR, 0 ); + move16(); + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + hLPDmem->mem_w0 = sub( sub( xn[2 * L_SUBFR - 1], mult_r( gain_pit, y1[2 * L_SUBFR - 1] ) ), mult_r( extract_h( gain_code ), y2[2 * L_SUBFR - 1] ) ); + move16(); + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < 2 * L_SUBFR; i++ ) + { + exc2[i + i_subfr] = mult( gain_pit, exc[i + i_subfr] ); + move16(); + exc[i + i_subfr] = add( exc2[i + i_subfr], mult( extract_h( gain_code ), code[i] ) ); + move16(); + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc_ivas_fx( L_frame, L_SUBFR, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr / L_SUBFR], bwe_exc, 0, NULL, *Q_new, T0, T0_frac, coder_type, st->core_brate, st->element_mode, st->idchan, st->hBWE_TD != NULL, st->tdm_LRTD_flag ); + + voice_factors[i_subfr / L_SUBFR + 1] = voice_factors[i_subfr / L_SUBFR]; + move16(); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn_flt[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + E_UTIL_synthesis( 0, p_Aq, &exc[i_subfr], &syn[i_subfr], 2 * L_SUBFR, hLPDmem->mem_syn, 1, M ); + + p_Aw += 2 * ( M + 1 ); + p_Aq += 2 * ( M + 1 ); + + pt_pitch++; + *pt_pitch = *( pt_pitch - 1 ); + move16(); + pt_pitch++; + } + + /* SC-VBR */ + IF( st->Opt_SC_VBR ) + { + st->hSC_VBR->prev_ppp_gain_pit_fx = gain_pit; + st->hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code; + move16(); + move16(); + } + + return; +} +#endif diff --git a/lib_enc/lib_enc.c b/lib_enc/lib_enc.c index 44f07700bef5511512e7433240c8384ef31f1d6e..bf22fb6011bdbe01a7d163374255bc8f9d1f51bc 100644 --- a/lib_enc/lib_enc.c +++ b/lib_enc/lib_enc.c @@ -1568,7 +1568,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( st_ivas->codec_mode = MODE1; move16(); test(); - IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) ) { reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); } @@ -1593,7 +1593,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( if ( hEncoderConfig->Opt_RF_ON == 0 && EQ_16( hEncoderConfig->ivas_format, MONO_FORMAT ) ) { test(); - IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) ) { reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); } @@ -1706,7 +1706,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( IF( hIvasEnc->switchingActive && EQ_16( hEncoderConfig->ivas_format, MONO_FORMAT ) ) { test(); - IF( NE_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( NE_16( st_ivas->hEncoderConfig->element_mode_init, EVS_MONO ) ) { copy_encoder_config( st_ivas, hCoreCoder, 0 ); } @@ -1731,11 +1731,13 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( IF( hEncoderConfig->Opt_AMR_WB ) { - IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) +#ifndef IVAS_FLOAT_FIXED + IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) ) { amr_wb_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ); } ELSE +#endif { amr_wb_enc_fx( hCoreCoder, inputBuffer, inputBufferSize ); } @@ -1743,6 +1745,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( ELSE { test(); +#ifndef IVAS_FLOAT_FIXED IF( NE_16( hEncoderConfig->element_mode_init, EVS_MONO ) || st_ivas->hEncoderConfig->stereo_dmx_evs ) { IF( NE_32( ( error = evs_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ) ), IVAS_ERR_OK ) ) @@ -1751,6 +1754,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( } } ELSE +#else { hCoreCoder->input_frame_fx = inputBufferSize; move32(); @@ -1759,6 +1763,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( return error; } } +#endif } } else /* IVAS */ @@ -1771,7 +1776,7 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( /* write indices into bitstream buffer */ test(); - IF( EQ_16( hEncoderConfig->element_mode_init, EVS_MONO ) && !st_ivas->hEncoderConfig->stereo_dmx_evs ) + IF( EQ_16( hEncoderConfig->element_mode_init, EVS_MONO ) ) { test(); IF( EQ_16( hEncoderConfig->ivas_format, MONO_FORMAT ) && EQ_16( hCoreCoder->element_mode, EVS_MONO ) ) diff --git a/lib_enc/long_enr.c b/lib_enc/long_enr.c index 93ded51086e595cc192778ab8a49dc677ffd87f3..87b67b12af00fe1b678a5a0cd1a5ec3f7862d1db 100644 --- a/lib_enc/long_enr.c +++ b/lib_enc/long_enr.c @@ -45,7 +45,7 @@ * * Compute relative energy, long-term average total noise energy and total active speech energy *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void long_enr( Encoder_State *st, /* i/o: encoder state structure */ const float Etot, /* i : total channel energy */ @@ -161,3 +161,4 @@ void long_enr( return; } +#endif diff --git a/lib_enc/lp_exc_e_fx.c b/lib_enc/lp_exc_e_fx.c index 9562eabf87f50d1b8a651bfcb05fa8e6aecb7974..d45f959731fb4dda19f657afce18dffbd3d4e6db 100644 --- a/lib_enc/lp_exc_e_fx.c +++ b/lib_enc/lp_exc_e_fx.c @@ -171,6 +171,158 @@ Word16 lp_filt_exc_enc_fx( return select; } +Word16 lp_filt_exc_enc_ivas_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter input response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +) +{ + Word16 gain1, gain2, g_corr2[4], exc_tmp[5 * L_SUBFR], xn2_tmp[5 * L_SUBFR]; + Word16 y1_tmp[5 * L_SUBFR]; + Word16 select, i, exp_ener, exp_ener1; + Word16 wtmp, wtmp1; + Word32 Ltmp; + + Word16 use_prev_sf_pit_gain = 0; + + gain1 = 0; + move16(); + gain2 = 0; + move16(); + + /*----------------------------------------------------------------* + * Find the target energy if the adaptive exc. is not filtered + *----------------------------------------------------------------*/ + test(); + IF( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, 100 ) ) + { + use_prev_sf_pit_gain = 1; + } + exp_ener = 0; + move16(); + wtmp = 0; + move16(); + test(); + IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) ) + { + IF( use_prev_sf_pit_gain == 1 ) + { + wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, gain_pit, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); + } + else + { + wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); + } + } + + /*----------------------------------------------------------------* + * Filter the adaptive excitation + * Find the target energy if the adapt. exc. is filtered + *----------------------------------------------------------------*/ + + exp_ener1 = 0; + move16(); + wtmp1 = 0; + move16(); + test(); + IF( ( EQ_16( *lp_flag, LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) + { + test(); + IF( EQ_16( codec_mode, MODE2 ) && EQ_16( L_frame, L_FRAME16k ) ) + { + FOR( i = 0; i < L_subfr; i++ ) + { + Ltmp = L_mult( 6881, exc[i - 1 + i_subfr] ); /* constants in Q15 */ + Ltmp = L_mac( Ltmp, 19005, exc[i + i_subfr] ); + Ltmp = L_mac( Ltmp, 6881, exc[i + 1 + i_subfr] ); + exc_tmp[i] = round_fx( Ltmp ); + } + } + ELSE + { + FOR( i = 0; i < L_subfr; i++ ) + { + Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */ + Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] ); + Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] ); + exc_tmp[i] = round_fx( Ltmp ); + } + } + IF( use_prev_sf_pit_gain == 1 ) + { + wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, gain_pit, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); + } + ELSE + { + wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); + } + } + + if ( LT_16( exp_ener, exp_ener1 ) ) + { + wtmp = shr( wtmp, 1 ); + } + + if ( GT_16( exp_ener, exp_ener1 ) ) + { + wtmp1 = shr( wtmp1, 1 ); + } + + /*-----------------------------------------------------------------* + * use the best prediction (minimize quadratic error) + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( ( ( LT_16( wtmp1, wtmp ) ) && ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) || ( EQ_16( *lp_flag, LOW_PASS ) ) ) + { + /* use the LP filter for pitch excitation prediction */ + select = LOW_PASS; + move16(); + Copy( exc_tmp, &exc[i_subfr], L_subfr ); + Copy( y1_tmp, y1, L_subfr ); + Copy( xn2_tmp, xn2, L_subfr ); + + IF( use_prev_sf_pit_gain == 0 ) + { + *gain_pit = gain2; + move16(); + g_corr[0] = g_corr2[0]; + move16(); + g_corr[1] = g_corr2[1]; + move16(); + g_corr[2] = g_corr2[2]; + move16(); + g_corr[3] = g_corr2[3]; + move16(); + } + } + ELSE + { + /* no LP filter used for pitch excitation prediction */ + select = FULL_BAND; + move16(); + IF( use_prev_sf_pit_gain == 0 ) + { + *gain_pit = gain1; + move16(); + } + } + + return select; +} + /*-------------------------------------------------------------------* * adpt_enr_fx() * diff --git a/lib_enc/lsf_enc_fx.c b/lib_enc/lsf_enc_fx.c index 058af1b18bbe8e5435d2f93689057f1ec3ca892a..c2635ec428e89b5cecd510057b7cd33333a5b901 100644 --- a/lib_enc/lsf_enc_fx.c +++ b/lib_enc/lsf_enc_fx.c @@ -196,11 +196,11 @@ void lsf_enc_fx( } /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ - IF( EQ_16( st_fx->next_force_safety_net_fx, 1 ) ) + IF( EQ_16( st_fx->next_force_safety_net, 1 ) ) { force_sf = 1; move16(); - st_fx->next_force_safety_net_fx = 0; + st_fx->next_force_safety_net = 0; move16(); } @@ -266,12 +266,12 @@ void lsf_enc_fx( /* If decoder FEC frame may be unstable force safety-net usage */ IF( ( EQ_16( st_fx->L_frame, L_FRAME16k ) ) && ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( coder_type, GENERIC ) ) ) { - st_fx->next_force_safety_net_fx = 1; + st_fx->next_force_safety_net = 1; move16(); } ELSE IF( ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( st_fx->clas, VOICED_CLAS ) || ( LT_16( st_fx->clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) ) ) ) { - st_fx->next_force_safety_net_fx = 1; + st_fx->next_force_safety_net = 1; move16(); } @@ -352,9 +352,8 @@ void lsf_enc_ivas_fx( const Word16 tdm_lsfQ_PCh[M], /* i : Q LSFs for primary channel */ const Word16 Q_new ) { - Word16 nBits = 0; - Word16 int_fs; - Word16 force_sf = 0; + Word16 nBits; + Word16 force_sf; Word16 fec_lsf[M], stab, i; Word16 no_param_lpc; @@ -362,6 +361,11 @@ void lsf_enc_ivas_fx( Word32 L_tmp; Word16 coder_type, ppp_mode, nelp_mode; + nBits = 0; + force_sf = 0; + move16(); + move16(); + test(); IF( EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, SID_1k75 ) ) { @@ -399,22 +403,8 @@ void lsf_enc_ivas_fx( move16(); } - /* initialize */ -#if 0 - int_fs = INT_FS_16k_FX; - move16(); - if (EQ_16(L_frame, L_FRAME)) - { - int_fs = INT_FS_FX; - move16(); - } -#else - assert( st->sr_core <= 32000 ); - int_fs = extract_l( st->sr_core ); - move32(); -#endif /* convert LSPs to LSFs */ - lsp2lsf_fx( lsp_new, lsf_new, M, int_fs ); + lsp2lsf_fx( lsp_new, lsf_new, M, st->sr_core ); /* check resonance for pitch clipping algorithm */ gp_clip_test_lsf_ivas_fx( st->element_mode, st->core_brate, lsf_new, st->clip_var_fx, 0 ); @@ -437,14 +427,16 @@ void lsf_enc_ivas_fx( } ELSE IF( EQ_16( nelp_mode, 1 ) ) { - nBits = 30; - move16(); - - if ( st->bwidth == NB ) + IF( st->bwidth == NB ) { nBits = 32; move16(); } + ELSE IF( EQ_16( st->bwidth, WB ) ) + { + nBits = 30; + move16(); + } } ELSE IF( EQ_16( ppp_mode, 1 ) ) { @@ -463,11 +455,11 @@ void lsf_enc_ivas_fx( } /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ - IF( EQ_16( st->next_force_safety_net_fx, 1 ) ) + IF( EQ_16( st->next_force_safety_net, 1 ) ) { force_sf = 1; move16(); - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); } @@ -481,7 +473,7 @@ void lsf_enc_ivas_fx( lsf2lsp_fx( lsf_new, lsp_new, M, st->sr_core ); test(); - IF( EQ_16( st->last_core, HQ_CORE ) && EQ_16( st->core, ACELP_CORE ) ) + IF( EQ_16( st->last_core, HQ_CORE ) && ( st->core == ACELP_CORE ) ) { /* don't use old LSF values if this is the first ACELP frame after HQ frames */ Copy( lsf_new, st->lsf_old_fx, M ); @@ -489,7 +481,7 @@ void lsf_enc_ivas_fx( /* set seed_acelp used in UC mode */ test(); - IF( EQ_16( coder_type, UNVOICED ) && GT_16( st->element_mode, EVS_MONO ) ) + IF( EQ_16( coder_type, UNVOICED ) && ( st->element_mode > EVS_MONO ) ) { st->seed_acelp = 0; move16(); @@ -497,6 +489,7 @@ void lsf_enc_ivas_fx( { /* rightshift before *seed_acelp+param_lpc[i] to avoid overflows*/ st->seed_acelp = add( i_mult( add( shr( st->seed_acelp, 1 ), param_lpc[i] ), 31821 ), 13849 ); + move16(); } } @@ -529,12 +522,12 @@ void lsf_enc_ivas_fx( /* If decoder FEC frame may be unstable force safety-net usage */ IF( ( EQ_16( st->L_frame, L_FRAME16k ) ) && ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( coder_type, GENERIC ) ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); } ELSE IF( ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( st->clas, VOICED_CLAS ) || ( LT_16( st->clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) ) ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); } @@ -571,7 +564,7 @@ void lsf_enc_ivas_fx( { /* don't use old LSP/LSF values if this is the first ACELP frame after HQ frames */ Copy( lsp_mid, st->lsp_old_fx, M ); - lsp2lsf_fx( lsp_mid, st->lsf_old_fx, M, int_fs ); + lsp2lsf_fx( lsp_mid, st->lsf_old_fx, M, st->sr_core ); } /* LSP interpolation and conversion of LSPs to A(z) */ @@ -581,7 +574,7 @@ void lsf_enc_ivas_fx( IF( EQ_16( st->active_cnt, 1 ) ) { Copy( lsp_mid, st->lsp_old_fx, M ); - lsp2lsf_fx( lsp_mid, st->lsf_old_fx, M, int_fs ); + lsp2lsf_fx( lsp_mid, st->lsf_old_fx, M, st->sr_core ); Copy( lsp_new, lsp_mid, M ); } diff --git a/lib_enc/lsf_msvq_ma_enc.c b/lib_enc/lsf_msvq_ma_enc.c index c1ce3812c5101972dadc968984d979a11c9194fd..9c277ca20b362398615028aa55196f992e204a35 100644 --- a/lib_enc/lsf_msvq_ma_enc.c +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -39,11 +39,21 @@ #include "cnst.h" #include "ivas_prot.h" #include "prot.h" +#include "prot_fx.h" #include "rom_com.h" #include "rom_enc.h" #include "basop_proto_func.h" #include "wmc_auto.h" +#ifndef swap +#define swap( x, y, type ) \ + { \ + type u__p; \ + u__p = x; \ + x = y; \ + y = u__p; \ + } +#endif /*--------------------------------------------------------------------------* * Local constants @@ -51,7 +61,6 @@ #define kMaxC 8 - /*--------------------------------------------------------------------------* * msvq_encmsvq_stage1_dct_search() * @@ -59,6 +68,292 @@ *--------------------------------------------------------------------------*/ /*! r: (p_max , best candidate sofar ) */ +#ifdef IVAS_FLOAT_FIXED +Word16 msvq_stage1_dct_search_fx( + const Word32 *u_fx, /* i : target exp : u_e */ + const Word16 u_e, /* i : exp for target Q0 */ + const Word16 N, /* i : target length and IDCT synthesis length */ + const Word16 maxC_st1, /* i : number of final stage 1 candidates to provide */ + const DCTTYPE dcttype, /* e.g. DCT_T2_16_XX, DCT_T2_24_XX; */ + const Word16 max_dct_trunc, /* i : maximum of truncation lenghts */ + Word32 *invTrfMatrix_fx, /* i : IDCT synthesis matrix for dim N Q31 */ + const Word16 *midQ_truncQ_fx, /* i : midQ vector */ + const Word32 *dct_scaleF_fx, /* i : global scale factors Q10 */ + const Word16 n_segm, /* i : number of segments */ + const Word16 *cols_per_segment, /* i : remaining length per segment */ + const Word16 *trunc_dct_cols_per_segment, /* i : trunc length per segment */ + const Word16 *entries_per_segment, /* i : number of rows per segment */ + const Word16 *cum_entries_per_segment, /* i : number of cumulative entries */ + const Word8 *const W8Qx_dct_sections[], /* i : Word8(byte) segment table ptrs */ + const Word16 *col_syn_shift[], /* i : columnwise syn shift tables */ + const Word8 *segm_neighbour_fwd, /* i : circular neighbour list fwd */ + const Word8 *segm_neighbour_rev, /* i : circular neighbour list reverse */ + const Word16 npost_check, /* i : number of neigbours to check , should be even */ + Word32 *st1_mse_ptr_fx, /* i : dynRAM buffer for MSEs exp : u_e */ + Word16 *indices_st1_local, /* o : selected cand indices */ + Word32 *st1_syn_vec_ptr_fx, /* i/o: buffer for IDCT24 synthesis i :exp : u_e */ + Word32 *dist1_ptr_fx, /* o : resulting stage 1 MSEs in DCT-N domain */ + Word16 *dist1_ptr_e ) +{ + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word32 u_mr_fx[FDCNG_VQ_MAX_LEN]; + Word16 dist1_ptr_e_buf[2 * LSFMBEST_MAX]; + Word64 mse_trunc_segm_fx[FDCNG_VQ_DCT_NSEGM]; + Word32 tmp_fx, check_mse; + Word16 tmp_e, check_mse_e; + Word64 mse_fx; /* Word64 in BASOP */ + + Word16 p_max, c, c2, segm, j_full, j, i; + Word16 n_ana, p_mins[2], idx_min[2]; + + Word16 st1_mse_ptr_e[128]; + + const Word8 *cbpW8; + const Word16 *dct_col_shift_tab; + + Word32 *st1_mse_pair_fx; + Word16 *st1_mse_pair_e; + Word16 *st1_idx_pair; + + Word32 tmp2_fx; + Word16 check_ind[FDCNG_VQ_DCT_NPOST]; + assert( ( npost_check % 2 == 0 ) && ( npost_check <= FDCNG_VQ_DCT_NPOST ) ); + + assert( n_segm <= FDCNG_VQ_DCT_NSEGM ); + + n_ana = N; /* VQ stage#1 core is currently always using stored DCT N coeffs */ + move16(); + assert( n_ana >= max_dct_trunc ); /* check for FDCNGVQ WB , SWB, FB operation */ + + /* remove mid stage#1 vector, in original input domain */ + tmp_e = s_max( 12, u_e ); + FOR( i = 0; i < n_ana; i++ ) + { + u_mr_fx[i] = L_sub( L_shl( u_fx[i], sub( u_e, tmp_e ) ), L_shl( midQ_truncQ_fx[i], sub( Q31 - Q10, tmp_e ) ) ); + move32(); + } + + dctT2_N_apply_matrix_fx( (const Word32 *) u_mr_fx, dct_target_fx, s_min( max_dct_trunc, n_ana ), n_ana, invTrfMatrix_fx, max_dct_trunc, dcttype ); // exp : tmp_e + + /* init search state ptr's at the top */ + set32_fx( dist1_ptr_fx, MAX_32, maxC_st1 ); + set16_fx( dist1_ptr_e_buf, 32, maxC_st1 ); + st1_mse_pair_fx = &( dist1_ptr_fx[0] ); /* req. ptr post upd +=2 */ + st1_mse_pair_e = &( dist1_ptr_e_buf[0] ); /* req. ptr post upd +=2 */ + st1_idx_pair = &( indices_st1_local[0] ); /* req. ptr post upd +=2 */ + set64_fx( mse_trunc_segm_fx, 0, n_segm ); + + // set16_fx( mse_trunc_segm_e, u_e, FDCNG_VQ_DCT_NSEGM ); + + FOR( segm = 0; segm < n_segm; segm++ ) + { /* point to a new paired location for each segment */ + p_max = 0; /* req. to point to one of 1 or 0, this init can potentially be omitted here,as p_max is always 1 or 0 */ + move16(); + + /* compute segment common trunction error in dctN domain */ + + FOR( i = 0; i < trunc_dct_cols_per_segment[segm]; i++ ) + { + mse_trunc_segm_fx[segm] = W_mac_32_32( mse_trunc_segm_fx[segm], dct_target_fx[cols_per_segment[segm] + i], dct_target_fx[cols_per_segment[segm] + i] ); + move64(); + } + + cbpW8 = W8Qx_dct_sections[segm]; /* Word8 column variable Qx storage , table ptr init */ + + FOR( j = 0; j < entries_per_segment[segm]; j++ ) + { + /* unweighted segmented search DCT domain loop */ + j_full = add( j, cum_entries_per_segment[segm] ); /* or simply use j_full++ */ + + mse_fx = mse_trunc_segm_fx[segm]; /* init mse with with common mse truncation part, in BASOP a move32() */ + move64(); + + dct_col_shift_tab = col_syn_shift[segm]; /* ptr init */ + + FOR( c2 = 0; c2 < cols_per_segment[segm]; c2++ ) + { +#define WMC_TOOL_SKIP + tmp_fx = L_sub( dct_target_fx[c2], Mpy_32_32( L_shl( cbpW8[c2], add( sub( Q31, tmp_e ), dct_col_shift_tab[c2] ) ), dct_scaleF_fx[1] ) ); /* note: BASOP shift left defined for signed integers */ + LOGIC( 1 ); + SHIFT( 1 ); + ADD( 1 ); /* in BASOP: s_and(for W8->W16), shl(), sub()*/ +#undef WMC_TOOL_SKIP + mse_fx = W_mac_32_32( mse_fx, tmp_fx, tmp_fx ); /* L_mac or L_mac0() square Word16 -> Word32*/ + } + Word16 L_tmp = W_norm( mse_fx ); + st1_mse_ptr_fx[j_full] = W_extract_h( W_lshl( mse_fx, L_tmp ) ); /* save MSE in shared dynamic RAM, move32() in BASOP */ + move32(); + st1_mse_ptr_e[j_full] = sub( shl( tmp_e, 1 ), L_tmp ); + move16(); + +#define WMC_TOOL_SKIP + cbpW8 += cols_per_segment[segm]; /* fixed pointer increment for each segment */ +#undef WMC_TOOL_SKIP + + /* overwrite with a new worst index at p_max */ + + /* Note: The three inner loop if's below are not 100% properly instrumented by WMC tool */ + // if ( st1_mse_ptr_fx[j_full] < st1_mse_pair_fx[p_max] ) /* L_sub */ + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( st1_mse_ptr_fx[j_full], st1_mse_ptr_e[j_full], st1_mse_pair_fx[p_max], st1_mse_pair_e[p_max] ), -1 ) ) /* L_sub */ + { + st1_idx_pair[p_max] = j_full; /* move16, single BASOP */ + move16(); + } /* BASOP 2 ops */ + + IF( EQ_16( st1_idx_pair[p_max], j_full ) ) + { /* idx updated --> also update mse */ + st1_mse_pair_fx[p_max] = st1_mse_ptr_fx[j_full]; /* move32(), single BASOP */ + move32(); + st1_mse_pair_e[p_max] = st1_mse_ptr_e[j_full]; /* move32(), single BASOP */ + move16(); + } /* BASOP 3 ops */ + + /* avoid WC costly candidate list management by always updating p_max, + as we have only a pair in each segment to maintain */ + p_max = 0; + move16(); + if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( st1_mse_pair_fx[0], st1_mse_pair_e[0], st1_mse_pair_fx[1], st1_mse_pair_e[1] ), -1 ) ) /* L_sub()*/ + { + p_max = 1; /* move16() */ + move16(); + } /* BASOP 3 ops ,Note 2 ops possible in BASOP with L_sub and L_lshr */ + + /* Note: logical shift right not available in ANSI-C */ + /* p_max = (st1_mse_pair[0] - st1_mse_pair[1]) ">>>" 31; */ + /* in java logical shift right is available as >>> , in BASOP it is available as L_lshr */ + + /* Cost: weighted sum with cond moves ('if') => 8 in float , 7 in BASOP with L_lshr */ + } /* j in section */ + + st1_mse_pair_fx += 2; /* req. ptr init */ + st1_mse_pair_e += 2; /* req. ptr init */ + st1_idx_pair += 2; /* req. ptr init */ + + } /* next segment */ + + tmp_e = 0; + move16(); + FOR( j = 0; j < maxC_st1; j++ ) + { + /* compute_full mse using stored DCT24 domain MSE's */ + /* calculate MSE from stage1 inner using existing inner DCT domain variables */ + tmp_e = s_max( dist1_ptr_e_buf[j], tmp_e ); + } + + FOR( j = 0; j < maxC_st1; j++ ) + { + /* compute_full mse using stored DCT24 domain MSE's */ + /* calculate MSE from stage1 inner using existing inner DCT domain variables */ + dist1_ptr_fx[j] = L_shr( dist1_ptr_fx[j], sub( tmp_e, dist1_ptr_e_buf[j] ) ); + move32(); + *dist1_ptr_e = tmp_e; + move16(); + } + + + assert( ( maxC_st1 >= 3 ) ); + assert( ( maxC_st1 <= 8 ) ); + + p_max = maximum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* establish current worst candidate for MSVQ stage#2 among all maxC_st1 candidates so far */ + + p_mins[0] = minimum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* find best entry among all maxC_pre */ + move16(); + tmp_fx = dist1_ptr_fx[p_mins[0]]; + move32(); + dist1_ptr_fx[p_mins[0]] = MAX_32; /* exclude 1st */ + move32(); + + p_mins[1] = minimum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* find 2nd best entry */ + move16(); + tmp2_fx = dist1_ptr_fx[p_mins[1]]; + move32(); + dist1_ptr_fx[p_mins[1]] = MAX_32; /* exclude 2nd */ + move32(); + + dist1_ptr_fx[p_mins[0]] = tmp_fx; /* restore 1st */ + move32(); + dist1_ptr_fx[p_mins[1]] = tmp2_fx; /* restore 2nd */ + move32(); + + idx_min[0] = indices_st1_local[p_mins[0]]; + move16(); + idx_min[1] = indices_st1_local[p_mins[1]]; + move16(); + + + /* use global exclusion list to never reselect the two (best) global MSE values sofar */ + st1_mse_ptr_fx[idx_min[0]] = MAX_32; /* move32() */ + move32(); + st1_mse_ptr_e[idx_min[0]] = MAX_16; + move16(); + st1_mse_ptr_fx[idx_min[1]] = MAX_32; /* move32() */ + move32(); + st1_mse_ptr_e[idx_min[1]] = MAX_16; + move16(); + + /* circular MSE-neigbour list in use to potentially replace some segment search candidates */ + /* using both 1st and 2nd best neighbours in fwd and rev directions */ + check_ind[0] = segm_neighbour_fwd[idx_min[0]]; + move16(); + check_ind[1] = segm_neighbour_rev[idx_min[0]]; + move16(); + + check_ind[2] = segm_neighbour_fwd[idx_min[1]]; + move16(); + check_ind[3] = segm_neighbour_rev[idx_min[1]]; + move16(); + + check_ind[4] = segm_neighbour_fwd[check_ind[0]]; + move16(); + check_ind[5] = segm_neighbour_rev[check_ind[1]]; + move16(); + + check_ind[6] = segm_neighbour_fwd[check_ind[2]]; + move16(); + check_ind[FDCNG_VQ_DCT_NPOST - 1] = segm_neighbour_rev[check_ind[3]]; + move16(); + + FOR( i = 0; i < npost_check; i++ ) + { + /* move MSE from DCT-inner loop search to input synthesis domain */ + /* multiplication by fdcng_dct_scaleF[2] to get the float outer loop scale correct in IDCT synthesis domain */ + check_mse = st1_mse_ptr_fx[check_ind[i]]; + move32(); + check_mse_e = st1_mse_ptr_e[check_ind[i]]; + move16(); + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( check_mse, check_mse_e, dist1_ptr_fx[p_max], *dist1_ptr_e ), -1 ) ) + { /* new winner , replace worst */ + dist1_ptr_fx[p_max] = L_shl( check_mse, sub( check_mse_e, *dist1_ptr_e ) ); + move32(); + indices_st1_local[p_max] = check_ind[i]; + move16(); + st1_mse_ptr_fx[check_ind[i]] = MAX_32; /* exclude, BASOP: move32() */ + move32(); + st1_mse_ptr_e[check_ind[i]] = MAX_16; + move16(); + p_max = maximum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* establish a new current worst candidate among all maxC */ + } + } + + /* extract the selected stage one vectors in DCT_N domain , apply IDCT_N and scale up */ + /* always extract full length signal(e.g. 24) to be able to update WB(e.g. N_in==21) candidate MSE values */ + /* in the case that only a part of the IDCT N vector is in final use */ + + /* note: synthesis not yet fully parameterized/generalized for other IDCT lengths */ + assert( N == 24 ); + { + FOR( c = 0; c < maxC_st1; c++ ) + { + dec_FDCNG_MSVQ_stage1_fx( indices_st1_local[c], N, invTrfMatrix_fx, dcttype + 1, &( st1_syn_vec_ptr_fx[c * N] ), NULL ); // Q11 : output + scale_sig32( &( st1_syn_vec_ptr_fx[c * N] ), N, sub( 11, s_max( u_e, 12 ) ) ); + } + } + + return p_max; /*ptr to worst performing candidate */ +} +#endif + int16_t msvq_stage1_dct_search( const float *u, /* i : target */ const int16_t N, /* i : target length and IDCT synthesis length */ @@ -304,6 +599,74 @@ int16_t msvq_stage1_dct_recalc_candidates_fdcng_wb( return p_max_local; } +#ifdef IVAS_FLOAT_FIXED +Word16 msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( + const Word32 *st1_syn_vec_ptr_fx, /* i : IDCT24 synthesis vectors */ + const Word16 st1_syn_vec_e, /* i : exp for IDCT24 synthesis vectors */ + const Word32 *u_fx, /* i : target signal */ + const Word16 u_e, /* i : exp for target signal */ + const int16_t maxC_st1, /* i : number of candidates in stage1 */ + Word32 *dist_ptr_fx, /* i/o: updated MSE vector for stage1 */ + Word16 *dist_ptr_e /* i/o: exp for updated MSE vector for stage1 */ +) +{ + Word16 i; + Word16 p_max_local, c; + const Word32 *p2_fx; + Word16 tmp_e; + Word32 res24_fx, high_diff_fx[FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB]; + Word64 acc; + Word16 res24_e[FD_CNG_maxC_37bits]; + Word16 dist_e; + + dist_e = *dist_ptr_e; + move16(); + FOR( c = 0; c < maxC_st1; c++ ) + { /* point to extended synthesis part */ + p2_fx = (const Word32 *) &( st1_syn_vec_ptr_fx[c * FDCNG_VQ_MAX_LEN + FDCNG_VQ_MAX_LEN_WB] ); /* ptr init to synthesis candidate c */ + tmp_e = s_max( st1_syn_vec_e, u_e ); + tmp_e = add( tmp_e, 1 ); + /* for stage#1 use "u" instead of the shortened resid[0], to access the extended/extrapolated input target */ + FOR( i = 0; i < FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB; i++ ) + { + high_diff_fx[i] = L_sub( L_shr( p2_fx[i], sub( tmp_e, st1_syn_vec_e ) ), L_shr( u_fx[FDCNG_VQ_MAX_LEN_WB + i], sub( tmp_e, u_e ) ) ); + move32(); + } + acc = 0; + move64(); + FOR( i = 0; i < FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB; i++ ) + { + acc = W_mac_32_32( acc, high_diff_fx[i], high_diff_fx[i] ); + } + res24_e[c] = tmp_e; + move16(); + tmp_e = W_norm( acc ); + res24_fx = W_extract_h( W_shl( acc, tmp_e ) ); + + res24_e[c] = sub( shl( res24_e[c], 1 ), tmp_e ); + move16(); + + dist_ptr_fx[c] = BASOP_Util_Add_Mant32Exp( dist_ptr_fx[c], *dist_ptr_e, L_negate( res24_fx ), res24_e[c], &res24_e[c] ); /* remove DCT24 high band error contribution */ + move32(); + dist_e = s_max( dist_e, res24_e[c] ); + move16(); + } + + + FOR( c = 0; c < maxC_st1; c++ ) + { + dist_ptr_fx[c] = L_shl( dist_ptr_fx[c], sub( res24_e[c], dist_e ) ); + move32(); + } + *dist_ptr_e = dist_e; + move16(); + /* finally update p_max, as it may potentially change, + due to the core DCT24 search originally optimizing over the longer basis vectors than DCT21 */ + p_max_local = maximum_32_fx( dist_ptr_fx, maxC_st1, NULL ); + + return p_max_local; +} +#endif /*--------------------------------------------------------------------------* @@ -592,6 +955,360 @@ void msvq_enc( return; } +#ifdef IVAS_FLOAT_FIXED +void msvq_enc_ivas_fx( + const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) Q_cb */ + const Word16 Q_cb, /* i : Codebook Q */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word32 u_fx[], /* i : Vector to be encoded (prediction and mean removed) (exp : u_e) */ + const Word16 u_e, /* i : Exponent for Vector to be encoded */ + const Word16 *levels, /* i : Number of levels in each stage */ + const Word16 maxC, /* i : Tree search size (number of candidates kept from from one stage to the next == M-best) */ + const Word16 stages, /* i : Number of stages */ + const Word16 w[], /* i : Weights Q8 */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 applyDCT_flag, /* i : applyDCT flag */ + Word32 *invTrfMatrix_fx, /* i/o: synthesis matrix Q31 */ + Word16 Idx[] /* o : Indices */ +) +{ + Word16 j; + const Word16 *cbp, *cb_stage; + Word32 resid_buf_fx[2 * LSFMBEST_MAX * M_MAX], *resid_fx[2]; + Word32 *pTmp, *p1, *p2; + Word16 pTmp_e; + Word16 *indices[2], m, s, c, c2, p_max, i; + Word16 idx_buf[2 * LSFMBEST_MAX * MAX_VQ_STAGES_USED], parents[LSFMBEST_MAX]; + Word32 dist_buf_fx[2 * LSFMBEST_MAX], *dist_fx[2], tmp, en, ss2, Tmp[M_MAX]; + Word16 dist_buf_e[2 * LSFMBEST_MAX], *dist_e[2]; + Word16 tmp_e, tmp_n, en_e; + Word16 resid_e; + Word16 n, maxn, start; + Word64 W_acc; /*64 bit accumulator*/ + + Word32 *st1_syn_vec_ptr_fx = &( resid_buf_fx[1 * LSFMBEST_MAX * M_MAX] ) - FDCNG_VQ_MAX_LEN * maxC; + Word32 *st1_mse_ptr_fx = &( resid_buf_fx[1 * LSFMBEST_MAX * M_MAX] ) - ( levels[0] ); + Word16 indices_st1_local[FDCNG_VQ_DCT_NSEGM * 2]; + + /*----------------------------------------------------------------* + * Allocate memory for previous (parent) and current nodes. + * Parent node is indexed [0], current node is indexed [1]. + *----------------------------------------------------------------*/ + indices[0] = idx_buf; + indices[1] = idx_buf + maxC * stages; /*move16();*/ + /*vr_iset(0, idx_buf, 2*stages*maxC);*/ + set16_fx( idx_buf, 0, (Word16) ( 2 * stages * maxC ) ); + + resid_fx[0] = resid_buf_fx; + resid_fx[1] = resid_buf_fx + maxC * N; /*move16();*/ + + dist_fx[0] = dist_buf_fx; + dist_e[0] = dist_buf_e; + dist_fx[1] = dist_buf_fx + maxC; + dist_e[1] = dist_buf_e + maxC; + + /*vr_iset(0, parents, maxC);*/ + set16_fx( parents, 0, maxC ); + + /*----------------------------------------------------------------* + * LSF weights are normalized, so it is always better to multiply it first + * Set up inital distance vector + *----------------------------------------------------------------*/ + W_acc = W_mult_32_32( Mpy_32_16_1( u_fx[0], shl( w[0], 2 ) ), u_fx[0] ); // 2*Qu - 6 + 1 + FOR( j = 1; j < N; j++ ) + { + W_acc = W_mac_32_32( W_acc, Mpy_32_16_1( u_fx[j], shl( w[j], 2 ) ), u_fx[j] ); // 2*Qu - 6 + 1 + } + + tmp_n = W_norm( W_acc ); + ss2 = W_extract_h( W_shl( W_acc, tmp_n ) ); + tmp_e = sub( add( shl( u_e, 1 ), 5 ), tmp_n ); + + /* Set up inital error (residual) vectors */ + pTmp = resid_fx[1]; /*move16();*/ + resid_e = u_e; + move16(); + IF( applyDCT_flag != 0 ) + { + resid_e = s_max( u_e, 12 ); + } + FOR( c = 0; c < maxC; c++ ) + { + Copy32( u_fx, pTmp + c * N, N ); + test(); + IF( applyDCT_flag != 0 && LT_16( u_e, 12 ) ) + { + scale_sig32( pTmp + c * N, N, sub( u_e, resid_e ) ); + } + dist_fx[1][c] = ss2; + move32(); + dist_e[1][c] = tmp_e; + move16(); + } + + /* Loop over all stages */ + m = 1; + move16(); + FOR( s = 0; s < stages; s++ ) + { + /* codebook pointer is set to point to first stage */ + cbp = cb[s]; /*Q_cb*/ + cb_stage = cbp; + + /* Set up pointers to parent and current nodes */ + swap( indices[0], indices[1], Word16 * ); + move16(); + move16(); + move16(); + swap( resid_fx[0], resid_fx[1], Word32 * ); + move32(); + move32(); + move32(); + swap( dist_fx[0], dist_fx[1], Word32 * ); + swap( dist_e[0], dist_e[1], Word16 * ); + move32(); + move32(); + move32(); + move16(); + move16(); + move16(); + + /* p_max points to maximum distortion node (worst of best) */ + p_max = 0; + move16(); + + n = N; + move16(); + maxn = maxN; + move16(); + if ( dims ) + { + n = dims[s]; + move16(); + } + if ( dims ) + { + maxn = n; + move16(); + } + + assert( ( maxn % 4 ) == 0 ); + + start = 0; + move16(); + if ( offs ) + { + start = offs[s]; + move16(); + } + + set32_fx( Tmp, 0, start ); + set32_fx( Tmp + start + n, 0, sub( N, add( start, n ) ) ); + + /* Set distortions to a large value */ + FOR( j = 0; j < maxC; j++ ) + { + dist_fx[1][j] = MAX_32; + move32(); + dist_e[1][j] = MAX_16 / 2; + move16(); + } + + test(); + IF( !s && applyDCT_flag != 0 ) /* means: m==1 */ + { + /* stage 1 candidates search in truncated dct24 domain without any weights */ + assert( N == FDCNG_VQ_MAX_LEN || N == FDCNG_VQ_MAX_LEN_WB ); /* 21 and 24 allowed */ + assert( maxC == 2 * FDCNG_VQ_DCT_NSEGM ); + p_max = msvq_stage1_dct_search_fx( u_fx, u_e, FDCNG_VQ_MAX_LEN, maxC, DCT_T2_24_XX, FDCNG_VQ_DCT_MAXTRUNC, (Word32 *) invTrfMatrix_fx, cdk1r_tr_midQ_truncQ_fx, fdcng_dct_scaleF_fx, FDCNG_VQ_DCT_NSEGM, + cdk1_ivas_cols_per_segment, cdk1_ivas_trunc_dct_cols_per_segment, cdk1_ivas_entries_per_segment, cdk1_ivas_cum_entries_per_segment, cdk_37bits_ivas_stage1_W8Qx_dct_sections, + stage1_dct_col_syn_shift, cdk1_ivas_segm_neighbour_fwd, cdk1_ivas_segm_neighbour_rev, FDCNG_VQ_DCT_NPOST, st1_mse_ptr_fx, indices_st1_local, st1_syn_vec_ptr_fx, dist_fx[1], &dist_e[1][0] ); + + /* move established stage#1 indices to the global MSVQ list structure */ + set16_fx( dist_e[1], dist_e[1][0], maxC ); + FOR( c = 0; c < maxC; c++ ) + { + indices[1][c * stages] = indices_st1_local[c]; + move16(); + } + } + ELSE + { + FOR( j = 0; j < levels[s]; j++ ) + { + /* Compute weighted codebook element and its energy */ + en = 0; + move32(); + en_e = 0; + move16(); + W_acc = 0; + move64(); + FOR( c2 = 0; c2 < n; c2++ ) + { + Tmp[start + c2] = L_mult0( shl( w[start + c2], 2 ), cbp[c2] ); + move32(); + W_acc = W_mac_32_16( W_acc, Tmp[start + c2], cbp[c2] ); + } + + tmp_n = W_norm( W_acc ); + + en = W_extract_h( W_shl( W_acc, tmp_n ) ); + en_e = sub( sub( 52, shl( Q_cb, 1 ) ), tmp_n ); + + cbp += maxn; /* pointer is incremented */ + + /* Iterate over all parent nodes */ + FOR( c = 0; c < m; c++ ) + { + pTmp = &resid_fx[0][c * N]; + pTmp_e = resid_e; + move16(); + /*tmp = (*pTmp++) * Tmp[0];*/ + W_acc = W_mult_32_32( pTmp[0], Tmp[0] ); + + FOR( i = 1; i < N; i++ ) + { + W_acc = W_mac_32_32( W_acc, pTmp[i], Tmp[i] ); + } + tmp_n = W_norm( W_acc ); + tmp = W_extract_h( W_shl( W_acc, tmp_n ) ); + tmp_e = sub( add( pTmp_e, sub( Q31 - Q10, Q_cb ) ), tmp_n ); + + + tmp_n = s_max( tmp_e, en_e ); + tmp_n = s_max( dist_e[0][c], tmp_n ); + + IF( NE_16( dist_e[0][c], MAX_16 / 2 ) ) + { + tmp_n = add( tmp_n, 2 ); + tmp = L_sub( L_shl( en, sub( en_e, tmp_n ) ), L_shl( tmp, add( sub( tmp_e, tmp_n ), 1 ) ) ); + tmp = L_add( tmp, L_shl( dist_fx[0][c], sub( dist_e[0][c], tmp_n ) ) ); + } + ELSE + { + tmp = MAX_32 - 1; + move32(); + tmp_n = MAX_16 / 2; + move32(); + } + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tmp, tmp_n, dist_fx[1][p_max], dist_e[1][p_max] ), -1 ) ) + { + /* Replace worst */ + dist_fx[1][p_max] = tmp; + move32(); + dist_e[1][p_max] = tmp_n; + move16(); + indices[1][p_max * stages + s] = j; + move16(); + parents[p_max] = c; + move16(); + + p_max = 0; + move16(); + tmp_e = p_max; + move16(); + + tmp_n = dist_e[1][0]; + move16(); + FOR( c2 = 1; c2 < maxC; c2++ ) + { + if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( dist_fx[1][c2], dist_e[1][c2], dist_fx[1][p_max], dist_e[1][p_max] ), 1 ) ) + { + p_max = c2; + move16(); + } + test(); + if ( GT_16( dist_e[1][c2], tmp_n ) && NE_16( dist_e[1][c2], MAX_16 / 2 ) ) + { + tmp_n = dist_e[1][c2]; + move16(); + } + } + FOR( c2 = 0; c2 < maxC; c2++ ) + { + IF( NE_16( dist_e[1][c2], MAX_16 / 2 ) ) + { + dist_fx[1][c2] = L_shl( dist_fx[1][c2], sub( dist_e[1][c2], tmp_n ) ); + move32(); + dist_e[1][c2] = tmp_n; + move16(); + } + } + } /*IF (L_sub(tmp,dist[1][p_max]) < 0) */ + } /* FOR (c=0; c - +#include "ivas_prot_fx.h" /*--------------------------------------------------------------------------* * Local constants diff --git a/lib_enc/mdct_classifier_fx.c b/lib_enc/mdct_classifier_fx.c index dc938766bd6c77053296139df471f7b27195394b..b7725a527036f2018066bd075f8c464422f4e325 100644 --- a/lib_enc/mdct_classifier_fx.c +++ b/lib_enc/mdct_classifier_fx.c @@ -7,8 +7,11 @@ #include "cnst.h" //#include "prot_fx.h" #include "rom_com.h" -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ /*--------------------------------------------------------------------------* * Local constants @@ -588,3 +591,555 @@ Word16 mdct_classifier_fx( /* o: MDCT A/B decision return clas_final; /* Q0 */ } +#ifdef IVAS_FLOAT_FIXED +Word16 mdct_classifier_ivas_fx( + Encoder_State *st, /* i/o: Encoder state variable */ + const Word16 *fft_buff, /* i : FFT spectrum from fft_rel */ + const Word32 enerBuffer[], /* i : energy buffer */ + Word16 enerBuffer_exp, + const Word32 brate /* i : current brate, IVAS: nominal bitrate, EVS: st->total_brate */ +) +{ + Word16 c; + Word32 X[129]; + Word16 k; + Word32 nf; + Word32 pe; + Word16 np; + Word32 max_cand; + Word16 max_i; + Word32 p_energy_man, n_energy_man, man; + Word16 p_energy_exp, n_energy_exp, expo; + Word16 d_acc; + Word16 pos_last; + Word16 clas_sec; + Word16 clas_final; + Word16 i; + Word32 gain1, gain2, gain3, gain11, gain4; + Word32 peak_l, peak_h, avrg_l, avrg_h, peak_H1, avrg_H1, peak_H2, avrg_H2; + Word16 condition1, condition2; + Word16 condition3, condition4; + Word16 gain2_start, gain3_start, gain4_start, H1_start, H2_start, H_length; + Word16 factor; + Word32 acc; + UWord16 lsb16; + UWord32 lsb32; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 exp, exp1, exp2, exp3; + Word32 gain1_tmp = 0, gain2_tmp = 0; + Word32 L_tmp, L_tmp1; + Flag Overflow = 0; + move16(); + move16(); + move16(); + + test(); + IF( EQ_32( st->input_Fs, 32000 ) || EQ_32( st->input_Fs, 48000 ) ) + { + gain2_start = GAIN2_START_SWB; + gain3_start = GAIN3_START_SWB; + gain4_start = GAIN4_START_SWB; + H1_start = H1_START_SWB; + H2_start = H2_START_SWB; + H_length = H_LENGTH_SWB; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE IF( EQ_32( st->input_Fs, 16000 ) ) + { + gain2_start = GAIN2_START_WB; + gain3_start = GAIN3_START_WB; + gain4_start = GAIN4_START_WB; + H1_start = H1_START_WB; + H2_start = H2_START_WB; + H_length = H_LENGTH_WB; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + assert( !"Unknown sampling frequency in MDCT_classifier" ); + H1_start = -1; /* to avoid compilation warning */ + H2_start = -1; /* to avoid compilation warning */ + H_length = -1; /* to avoid compilation warning */ + gain2_start = -1; /* to avoid compilation warning */ + gain3_start = -1; /* to avoid compilation warning */ + gain4_start = -1; /* to avoid compilation warning */ + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + + IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) + { + dft_mag_square_fx( fft_buff, X, 256 ); + } + ELSE + { + Word16 norm_val; + + norm_val = i_mult( L_FFT, shr( L_FFT, 2 ) ); + FOR( k = 0; k < 128; k++ ) + { + X[k + 1] = Mpy_32_16_1( st->Bin_E_old_fx[k], norm_val ); + } + X[0] = X[1]; + move32(); + } + + nf = L_add( X[0], 0 ); + pe = L_add( X[0], 0 ); + np = 0; + move16(); + + max_cand = L_negate( 1 ); + max_i = 0; + move16(); + + p_energy_man = L_deposit_l( 0 ); + n_energy_man = L_deposit_l( 0 ); + p_energy_exp = n_energy_exp = 32; + move16(); + move16(); + d_acc = 0; + move16(); + pos_last = -1; + move16(); + + FOR( k = 0; k < 128; k++ ) + { + /* NB: a*f + b*(1 - f) needs two multiplies + * = (a - b)*f + b saves one multiply */ + IF( GT_32( X[k + 1], nf ) ) + { + factor = 31385; + move16(); /* 0.9578 in Q15 */ + } + ELSE + { + factor = 21207; + move16(); /* 0.6472 in Q15 */ + } + + acc = L_sub( nf, X[k + 1] ); + Mpy_32_16_ss( acc, factor, &acc, &lsb16 ); + nf = L_add( acc, X[k + 1] ); + + IF( GT_32( X[k + 1], pe ) ) + { + factor = 13840; + move16(); /* 0.42237 in Q15 */ + } + ELSE + { + factor = 26308; + move16(); /* 0.80285 in Q15 */ + } + + acc = L_sub( pe, X[k + 1] ); + Mpy_32_16_ss( acc, factor, &acc, &lsb16 ); + pe = L_add( acc, X[k + 1] ); + Mpy_32_16_ss( pe, 20972, &acc, &lsb16 ); /* 0.64 in Q15 */ + + IF( GT_32( X[k + 1], acc ) ) + { + IF( GT_32( X[k + 1], max_cand ) ) + { + max_cand = X[k + 1]; + move32(); + max_i = add( 2, k ); + } + } + ELSE + { + IF( max_i > 0 ) + { + IF( np > 0 ) + { + d_acc = sub( add( d_acc, max_i ), pos_last ); + } + np = add( np, 1 ); + pos_last = max_i; + move16(); + } + + max_cand = L_negate( 1 ); + max_i = 0; + move16(); + } + + IF( pe != 0 ) + { + expo = norm_l( pe ); + man = L_shl( pe, expo ); + Mpy_32_32_ss( man, man, &man, &lsb32 ); /* pe square */ + expo = shl( expo, 1 ); /* Multiply by 2 due to squaring. */ + floating_point_add( &p_energy_man, &p_energy_exp, man, expo ); + } + IF( nf != 0 ) + { + expo = norm_l( nf ); + man = L_shl( nf, expo ); + Mpy_32_32_ss( man, man, &man, &lsb32 ); /* nf square */ + expo = shl( expo, 1 ); /* Multiply by 2 due to squaring. */ + floating_point_add( &n_energy_man, &n_energy_exp, man, expo ); + } + } + + gain1 = L_deposit_l( 0 ); + gain2 = L_deposit_l( 0 ); + gain3 = L_deposit_l( 0 ); + + FOR( i = 0; i < gain2_start; i++ ) + { + IF( EQ_16( gain2_start, GAIN2_START_SWB ) ) + { + gain1 = L_add( gain1, L_shr( enerBuffer[i], 3 ) ); + gain2 = L_add( gain2, L_shr( enerBuffer[gain2_start + i], 3 ) ); + gain3 = L_add( gain3, L_shr( enerBuffer[gain3_start + i], 3 ) ); + } + ELSE + { + gain1 = L_add( gain1, Mult_32_16( enerBuffer[i], 5461 ) ); + gain2 = L_add( gain2, Mult_32_16( enerBuffer[gain2_start + i], 5461 ) ); + gain3 = L_add( gain3, Mult_32_16( enerBuffer[gain3_start + i], 5461 ) ); + } + } + + + IF( EQ_16( gain2_start, GAIN2_START_SWB ) ) + { + acc = L_shr( enerBuffer[0], 3 ); + acc = L_sub( gain1, acc ); + acc = Mult_32_16( acc, 4681 ); + gain11 = L_shl( acc, 3 ); + gain4 = L_deposit_l( 0 ); + } + ELSE + { + acc = Mult_32_16( enerBuffer[0], 5461 ); + acc = L_sub( gain1, acc ); + acc = Mult_32_16( acc, 6553 ); + gain11 = (Word32) W_mult_32_16( acc, 6 ); + gain4 = L_deposit_l( 0 ); + } + + gain4 = L_deposit_l( 0 ); + FOR( i = 0; i < gain4_start; i++ ) + { + IF( EQ_16( gain4_start, GAIN4_START_SWB ) ) + { + gain4 = L_add( gain4, Mult_32_16( enerBuffer[gain4_start + i], 2731 ) ); + } + ELSE + { + gain4 = L_add( gain4, Mult_32_16( enerBuffer[gain4_start + i], 3641 ) ); + } + } + + peak_H1 = enerBuffer[H1_start]; + move32(); + + avrg_H1 = enerBuffer[H1_start]; + move32(); + + FOR( i = 1; i < H_length; i++ ) + { + IF( GT_32( enerBuffer[H1_start + i], peak_H1 ) ) + { + peak_H1 = enerBuffer[H1_start + i]; + move32(); + } + avrg_H1 = L_add( avrg_H1, enerBuffer[H1_start + i] ); + } + + peak_H2 = enerBuffer[H2_start]; + move32(); + + avrg_H2 = enerBuffer[H2_start]; + move32(); + + FOR( i = 1; i < H_length; i++ ) + { + IF( GT_32( enerBuffer[H2_start + i], peak_H2 ) ) + { + peak_H2 = enerBuffer[H2_start + i]; + move32(); + } + avrg_H2 = L_add( avrg_H2, enerBuffer[H2_start + i] ); + } + + peak_l = L_deposit_l( 0 ); + avrg_l = L_deposit_l( 0 ); + peak_h = L_deposit_l( 0 ); + avrg_h = L_deposit_l( 0 ); + + FOR( i = 0; i < 32; i++ ) + { + avrg_l = L_add( avrg_l, L_shr( X[20 + i], 5 ) ); + avrg_h = L_add( avrg_h, L_shr( X[96 + i], 5 ) ); + IF( GT_32( X[20 + i], peak_l ) ) + { + peak_l = L_add( X[20 + i], 0 ); + } + IF( GT_32( X[96 + i], peak_h ) ) + { + peak_h = L_add( X[96 + i], 0 ); + } + } + + /* Compute: d_acc - 12*(np -1). */ + acc = L_deposit_l( d_acc ); + IF( L_msu( acc, 12 / 2, sub( np, 1 ) ) > 0 ) /* 12/2 is to compensate the fractional mode multiply */ + { + condition1 = 1; /* Signifies: d_acc/(np - 1) > 12 */ + move16(); + } + ELSE + { + condition1 = 0; /* Signifies: d_acc/(np - 1) <= 12 */ + move16(); + /* NB: For np = 0 or 1, it fits this condition. */ + } + + /* Compute: p_energy - 147.87276*n_energy. */ + IF( n_energy_man != 0 ) + { + Mpy_32_16_ss( n_energy_man, 18928, &acc, &lsb16 ); /* 147.87276 in Q7 */ + expo = sub( n_energy_exp, 15 - 7 ); /* Due to 18928 in Q7 */ + acc = L_negate( acc ); /* To facilitate the following floating_point_add() to perform subtraction. */ + floating_point_add( &acc, &expo, p_energy_man, p_energy_exp ); + } + ELSE + { + acc = L_deposit_l( 0 ); + } + IF( acc > 0 ) + { + condition2 = 1; /* Signifies: p_energy / n_energy > 147.87276 */ + move16(); + } + ELSE + { + condition2 = 0; /* Signifies: p_energy / n_energy <= 147.87276 */ + move16(); + } + + condition3 = 0; + move16(); + condition4 = 0; + move16(); + + L_tmp = Mult_32_16( peak_h, 12603 ); + IF( GT_32( peak_l, L_tmp ) ) + { + exp = norm_l( peak_l ); + } + ELSE + { + exp = norm_l( L_tmp ); + } + IF( GT_32( avrg_h, avrg_l ) ) + { + exp1 = norm_l( avrg_h ); + } + ELSE + { + exp1 = norm_l( avrg_l ); + } + + L_tmp1 = Mult_32_16( peak_l, 12603 ); + IF( GT_32( peak_h, L_tmp1 ) ) + { + exp2 = norm_l( peak_h ); + } + ELSE + { + exp2 = norm_l( L_tmp1 ); + } + + test(); + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + IF( GT_32( Mult_32_16( gain3, 27307 ), gain2 ) || ( GE_32( gain3, Mult_32_16( gain2, 26214 ) ) && GT_32( peak_H1, L_shl_o( avrg_H1, 1, &Overflow ) ) ) || ( LT_32( Mult_32_32( L_shl_o( peak_l, exp, &Overflow ), L_shl_o( avrg_h, exp1, &Overflow ) ), Mult_32_32( L_shl_o( L_tmp, exp, &Overflow ), L_shl_o( avrg_l, exp1, &Overflow ) ) ) || GT_32( Mult_32_32( L_shl_o( L_tmp1, exp2, &Overflow ), L_shl_o( avrg_h, exp1, &Overflow ) ), Mult_32_32( L_shl_o( peak_h, exp2, &Overflow ), L_shl_o( avrg_l, exp1, &Overflow ) ) ) ) ) +#else + IF( GT_32( Mult_32_16( gain3, 27307 ), gain2 ) || ( GE_32( gain3, Mult_32_16( gain2, 26214 ) ) && GT_32( peak_H1, L_shl( avrg_H1, 1 ) ) ) || ( LT_32( Mult_32_32( L_shl( peak_l, exp ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( L_tmp, exp ), L_shl( avrg_l, exp1 ) ) ) || GT_32( Mult_32_32( L_shl( L_tmp1, exp2 ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( peak_h, exp2 ), L_shl( avrg_l, exp1 ) ) ) ) ) +#endif + { + condition3 = 1; + move16(); + } + + L_tmp = Mult_32_16( peak_h, 12800 ); + IF( GT_32( peak_l, L_tmp ) ) + { + exp = norm_l( peak_l ); + } + ELSE + { + exp = norm_l( L_tmp ); + } + + L_tmp1 = Mult_32_16( peak_l, 6400 ); + IF( GT_32( peak_h, L_tmp1 ) ) + { + exp2 = norm_l( peak_h ); + } + ELSE + { + exp2 = norm_l( L_tmp1 ); + } + + IF( GT_32( peak_h, L_shl( L_tmp1, 1 ) ) ) + { + exp3 = norm_l( peak_h ); + } + ELSE + { + exp3 = sub( norm_l( L_tmp1 ), 1 ); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( GT_32( gain4, Mult_32_16( gain11, 26214 ) ) && GT_32( Mult_32_32( L_shl( peak_l, exp ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( Mult_32_16( peak_h, 12800 ), exp ), L_shl( avrg_l, exp1 ) ) ) && LT_32( Mult_32_32( L_shl( Mult_32_16( peak_l, 6400 ), exp2 ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( peak_h, exp2 ), L_shl( avrg_l, exp1 ) ) ) ) || ( GT_32( gain4, Mult_32_16( gain11, 9830 ) ) && LT_32( Mult_32_16( peak_h, 21845 ), avrg_h ) && LT_32( Mult_32_16( peak_H2, 21845 ), avrg_H2 ) ) || + ( LT_32( Mult_32_32( L_shl( peak_l, exp ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( Mult_32_16( peak_h, 12800 ), exp ), L_shl( avrg_l, exp1 ) ) ) && GT_32( Mult_32_16( peak_h, 21845 ), avrg_h ) ) || ( GT_32( Mult_32_32( L_shl( Mult_32_16( peak_l, 12800 ), exp3 ), L_shl( avrg_h, exp1 ) ), Mult_32_32( L_shl( peak_h, exp3 ), L_shl( avrg_l, exp1 ) ) ) > 0 && LT_32( Mult_32_16( peak_h, 21845 ), avrg_h ) ) ) + { + condition4 = 1; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + + IF( ( GE_32( brate, HQ_MDCTCLASS_CROSSOVER_BRATE ) && GT_32( st->input_Fs, 16000 ) && ( s_xor( condition1, condition2 ) != 0 || condition3 ) ) || ( ( LT_32( brate, HQ_MDCTCLASS_CROSSOVER_BRATE ) || EQ_32( st->input_Fs, 16000 ) ) && condition4 ) ) + { + c = MDCT_CLASSIFER_HQ_LOCAL; /* Q13 */ + move16(); + } + ELSE + { + c = MDCT_CLASSIFER_TCX_LOCAL; /* Q13 */ + move16(); + } + + /* Smooth decision from instantaneous decision*/ + acc = L_mult( hTcxEnc->clas_sec_old_fx, MDCT_CLASSIFER_SMOOTH_FILT_COEFF ); /* st_fx->clas_sec_old_fx in Q13 */ + clas_sec = mac_r( acc, c, 0x7fff - MDCT_CLASSIFER_SMOOTH_FILT_COEFF ); /* clas_sec and c are in Q13 */ + + /* Do thresholding with hysteresis */ + + IF( GT_16( st->last_enerBuffer_exp, enerBuffer_exp ) ) + { + gain1_tmp = L_shr( gain1, sub( st->last_enerBuffer_exp, enerBuffer_exp ) ); + move32(); + gain2_tmp = L_shr( gain2, sub( st->last_enerBuffer_exp, enerBuffer_exp ) ); + move32(); + } + ELSE + { + hTcxEnc->last_gain1 = L_shr( hTcxEnc->last_gain1, sub( enerBuffer_exp, st->last_enerBuffer_exp ) ); + move32(); + hTcxEnc->last_gain2 = L_shr( hTcxEnc->last_gain2, sub( enerBuffer_exp, st->last_enerBuffer_exp ) ); + move32(); + gain1_tmp = gain1; + move32(); + gain2_tmp = gain2; + move32(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + +#ifdef BASOP_NOGLOB + IF( ( EQ_16( hTcxEnc->clas_final_old, HQ_CORE ) || EQ_16( hTcxEnc->clas_final_old, TCX_20_CORE ) ) && ( ( GT_32( hTcxEnc->last_gain1, L_shr( gain1_tmp, 1 ) ) && LT_32( hTcxEnc->last_gain1, L_shl_o( gain1_tmp, 1, &Overflow ) ) ) && ( GT_32( hTcxEnc->last_gain2, L_shr( gain2_tmp, 1 ) ) && LT_32( hTcxEnc->last_gain2, L_shl_o( gain2_tmp, 1, &Overflow ) ) ) ) ) +#else + IF( ( EQ_16( hTcxEnc->clas_final_old, HQ_CORE ) || EQ_16( hTcxEnc->clas_final_old, TCX_20_CORE ) ) && ( ( GT_32( hTcxEnc->last_gain1, L_shr( gain1_tmp, 1 ) ) && LT_32( hTcxEnc->last_gain1, L_shl( gain1_tmp, 1 ) ) ) && ( GT_32( hTcxEnc->last_gain2, L_shr( gain2_tmp, 1 ) ) && LT_32( hTcxEnc->last_gain2, L_shl( gain2_tmp, 1 ) ) ) ) ) +#endif + { + clas_final = hTcxEnc->clas_final_old; + move16(); + } + ELSE IF( GT_16( clas_sec, hTcxEnc->clas_sec_old_fx ) && GT_16( clas_sec, MDCT_CLASSIFER_THRESH_UP ) ) /* Going up? */ + { + clas_final = HQ_CORE; /* Q0 */ + move16(); + } + ELSE IF( LT_16( clas_sec, MDCT_CLASSIFER_THRESH_DOWN ) ) /* Going down */ + { + clas_final = TCX_20_CORE; + move16(); + } + ELSE + { + clas_final = hTcxEnc->clas_final_old; + move16(); + } + + + /* Prevent the usage of HQ_CORE on noisy-speech or inactive */ + test(); + test(); + test(); + if ( EQ_16( st->mdct_sw_enable, MODE2 || st->element_mode > EVS_MONO ) && ( EQ_16( st->flag_noisy_speech_snr, 1 ) || st->vad_flag == 0 ) && EQ_16( clas_final, HQ_CORE ) ) + { + clas_final = TCX_20_CORE; + move16(); + } + + /* Restrict usage of HQ_core to supported operating range */ + /* EVS: brate == st->total_brate */ + /* IVAS: brate is the nominal bitrate while st->total_brate may fluctuate. This sets a hard limit for HQ at HQ_16k40 */ + test(); + test(); + test(); + if ( LE_32( st->total_brate, HQ_16k40 ) || LT_32( brate, HQ_16k40 ) || EQ_16( st->bwidth, NB ) || GT_32( brate, IVAS_48k ) ) + { + clas_final = TCX_20_CORE; + move16(); + } + + + /* Memory update */ + + hTcxEnc->clas_sec_old_fx = clas_sec; + move16(); /* Q13 */ + hTcxEnc->clas_final_old = clas_final; + move16(); /* Q0 */ + hTcxEnc->last_gain1 = gain1; + move32(); + hTcxEnc->last_gain2 = gain2; + move32(); + st->last_enerBuffer_exp = enerBuffer_exp; + move16(); + + return clas_final; +} +#endif diff --git a/lib_enc/multi_harm_fx.c b/lib_enc/multi_harm_fx.c index 2611fec4b542579be041c8e16f7afe2a64afe93d..43e5ff5bb2c66584256cfd24fdb7d515b104ca2b 100644 --- a/lib_enc/multi_harm_fx.c +++ b/lib_enc/multi_harm_fx.c @@ -146,7 +146,7 @@ Word16 multi_harm_fx( /* o : frame multi-harmonicity } /* subtract the floor */ - S[i] = s_max( sub( Bin_E[i], flor ), 0 ); + S[i] = s_max( sub_sat( Bin_E[i], flor ), 0 ); move16(); /* update the floor */ @@ -375,3 +375,362 @@ Word16 multi_harm_fx( /* o : frame multi-harmonicity } return harm; } +#ifdef IVAS_FLOAT_FIXED +Word16 multi_harm_ivas_fx( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const Word16 Bin_E[], /* i : log-energy spectrum of the current frame Q7 */ + Word16 old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor Q7 */ + Word16 cor_map_LT[], /* i/o: LT correlation map Q15 */ + Word16 *multi_harm_limit, /* i/o: multi harminic threshold Q9 */ + const Word32 total_brate, /* i : total bitrate Q0 */ + const Word16 bwidth, /* i : input signal bandwidth Q0 */ + Word16 *cor_strong_limit, /* i/o: HF correlation indicator Q0 */ + Word16 *st_mean_avr_dyn, /* i/o: long term average dynamic Q7 */ + Word16 *st_last_sw_dyn, /* i/o: last dynamic Q7 */ + Word16 *cor_map_sum, /* i : sum of correlation map Q8 */ + Word16 *sp_floor, /* o: noise floor estimate Q7 */ + Word16 S_map[] /* o : short-term correlation map Q7 */ +) +{ + Word16 i, j, k, L, stemp, N_mins, ind_mins[L_FFT / 4], *pt_mins, harm; + Word16 S[L_FFT / 2], flor, step, sign_fx, tmp16, tmp2, ExpInd, tmpdB, ExpdB, Expx2, Expy2; + Word16 corx2, cory2, corxy, cor, cor_map[L_FFT / 2], *pt1, *pt2, cor_strong; + Word32 L_acc; + Word32 Lcorx2, Lcory2, Lcorxy, Lcor_map_LT_sum; + Word16 mean_dyn; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /*------------------------------------------------------------------* + * initialization + *------------------------------------------------------------------*/ + + /* length of the useful part of the spectrum (up to 6.4kHz) */ + L = L_FFT / 2; + move16(); + if ( EQ_16( bwidth, NB ) ) + { + /* length of the useful part of the spectrum (up to 3.6kHz) */ + L = 76; + move16(); + } + + Copy( Bin_E, S, L ); + + /*------------------------------------------------------------------* + * searching of spectral maxima and minima + *------------------------------------------------------------------*/ + + pt_mins = ind_mins; + + /* index of the first minimum */ + if ( LT_16( Bin_E[0], Bin_E[1] ) ) + { + *pt_mins++ = 0; + move16(); + } + + FOR( i = 1; i < L - 1; i++ ) + { + /* minimum found */ + test(); + if ( LT_16( Bin_E[i], Bin_E[i - 1] ) && LT_16( Bin_E[i], Bin_E[i + 1] ) ) + { + *pt_mins++ = i; + move16(); + } + } + + /* index of the last minimum */ + IF( LT_16( Bin_E[L - 1], Bin_E[L - 2] ) ) + { + *pt_mins++ = sub( L, 1 ); + move16(); + } + + /* total number of minimas found */ + N_mins = (Word16) ( pt_mins - ind_mins - 1 ); + move16(); + + /*------------------------------------------------------------------* + * calculation of the spectral floor + * subtraction of the spectral floor + *------------------------------------------------------------------*/ + + set16_fx( S, 0, L ); + + IF( N_mins > 0 ) + { + L_acc = L_deposit_l( 0 ); + FOR( i = 0; i < N_mins; ++i ) + { + L_acc = L_mac0( L_acc, Bin_E[ind_mins[i]], 1 ); + } + *sp_floor = extract_l( Mult_32_16( L_acc, div_s( 1, N_mins ) ) ); + move16(); + + set16_fx( S, 0, ind_mins[0] ); + set16_fx( &S[ind_mins[N_mins]], 0, sub( shr( L_FFT, 1 ), ind_mins[N_mins] ) ); + + pt_mins = ind_mins; + + flor = 0; + move16(); + step = 0; + move16(); + + FOR( i = ind_mins[0]; i < ind_mins[N_mins]; i++ ) + { + /* we are at the end of the next minimum */ + IF( EQ_16( i, *pt_mins ) ) + { + pt_mins++; + flor = Bin_E[i]; + move16(); /*Q7*/ + /* calculate the new step */ + /*step = (Bin_E[*pt_mins] - Bin_E[i]) / (*pt_mins-i);*/ + tmp16 = sub( *pt_mins, i ); + tmpdB = sub( Bin_E[*pt_mins], Bin_E[i] ); + sign_fx = shr( tmpdB, 15 ); /* 0 if positive else -1 */ + ExpdB = sub( norm_s( tmpdB ), 1 ); + tmpdB = abs_s( shl( tmpdB, ExpdB ) ); + ExpInd = norm_s( tmp16 ); + tmp16 = shl( tmp16, ExpInd ); + tmp16 = div_s( tmpdB, tmp16 ); + tmp16 = sub( s_xor( tmp16, sign_fx ), sign_fx ); + step = shr( tmp16, add( sub( ExpdB, ExpInd ), 15 ) ); /* Q7 */ + } + + /* subtract the floor */ + S[i] = s_max( sub_sat( Bin_E[i], flor ), 0 ); + move16(); + + /* update the floor */ + flor = add( flor, step ); /*Q7*/ + } + } + + /* Calculate the maximum dynamic per band */ + /* since we are processing 40 bins we will use 1/40 in Q15 to find the mean */ + /* mean_dyn = mean(&S[L-40], 40);*/ + L_acc = L_deposit_l( 0 ); + FOR( i = L - 40; i < L; i++ ) + { + L_acc = L_mac( L_acc, S[i], 819 /*1 / 40 * (2 ^ 15)*/ ); + } + mean_dyn = round_fx( L_acc ); /*Q7*/ + + /*mean_dyn = 0.6f * *st_mean_avr_dyn + 0.4f * mean_dyn;*/ + L_acc = L_mult( 13107 /*0.4f*/, mean_dyn ); /*Q23*/ + L_acc = L_mac( L_acc, 19661 /*0.6f*/, *st_mean_avr_dyn ); /*Q23*/ + mean_dyn = round_fx( L_acc ); /*Q7*/ + + test(); + IF( LT_16( mean_dyn, 1229 ) /*9.6f*/ && *cor_strong_limit != 0 ) + { + *cor_strong_limit = 0; + move16(); + *st_last_sw_dyn = mean_dyn; + move16(); + } + ELSE IF( GT_16( sub( mean_dyn, *st_last_sw_dyn ), 576 ) /*4.5f*/ ) + { + *cor_strong_limit = 1; + move16(); + } + test(); + if ( LT_32( total_brate, ACELP_9k60 ) || GT_32( total_brate, ACELP_16k40 ) ) + { + *cor_strong_limit = 1; + move16(); + } + + *st_mean_avr_dyn = mean_dyn; + move16(); + + /*------------------------------------------------------------------* + * calculation of the correlation map + *------------------------------------------------------------------*/ + + set16_fx( cor_map, 0, L ); + IF( N_mins > 0 ) + { + Lcorx2 = L_deposit_l( 0 ); + Lcorxy = L_deposit_l( 0 ); + stemp = ind_mins[0]; + move16(); + Lcory2 = L_mult( old_S[stemp], old_S[stemp] ); + k = 1; + move16(); + + FOR( i = add( stemp, 1 ); i <= ind_mins[N_mins]; i++ ) + { + IF( EQ_16( i, ind_mins[k] ) ) + { + /* include the last peak point (new minimum) to the corr. sum */ +#ifdef BASOP_NOGLOB + Lcory2 = L_mac_o( Lcory2, old_S[i], old_S[i], &Overflow ); +#else /* BASOP_NOGLOB */ + Lcory2 = L_mac( Lcory2, old_S[i], old_S[i] ); +#endif /* BASOP_NOGLOB */ + + /* calculation of the norm. peak correlation */ + test(); + IF( Lcorx2 != 0 && Lcory2 != 0 ) + { + /* corxy * corxy*/ + tmp16 = sub( norm_l( Lcorxy ), 1 ); + corxy = extract_h( L_shl( Lcorxy, tmp16 ) ); + corxy = mult_r( corxy, corxy ); + /* (corx2 * cory2) */ + Expx2 = norm_l( Lcorx2 ); + Expy2 = norm_l( Lcory2 ); + corx2 = extract_h( L_shl( Lcorx2, Expx2 ) ); + cory2 = extract_h( L_shl( Lcory2, Expy2 ) ); + corx2 = mult_r( corx2, cory2 ); + Expx2 = add( Expy2, Expx2 ); + /* Validate num < den */ + cor = sub( corx2, corxy ); + cor = shr( cor, 15 ); + /* Add 1 to tmp16 & shr by 2 if corxy > corx2 */ + tmp16 = sub( tmp16, cor ); + corxy = shl( corxy, cor ); + corxy = shl( corxy, cor ); + /* cor = corxy * corxy / (corx2 * cory2) */ + corxy = div_s( corxy, corx2 ); +#ifdef BASOP_NOGLOB + cor = shr_o( corxy, sub( shl( tmp16, 1 ), Expx2 ), &Overflow ); /* Q15 */ +#else /* BASOP_NOGLOB */ + cor = shr( corxy, sub( shl( tmp16, 1 ), Expx2 ) ); /* Q15 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { + cor = 0; + move16(); + } + + /* save the norm. peak correlation in the correlation map */ + FOR( j = ind_mins[k - 1]; j < ind_mins[k]; j++ ) + { + old_S[j] = S[j]; + move16(); + S[j] = shr( cor, 8 ); + move16(); + cor_map[j] = cor; + move16(); + } + + Lcorx2 = L_deposit_l( 0 ); + Lcory2 = L_deposit_l( 0 ); + Lcorxy = L_deposit_l( 0 ); + + k = add( k, 1 ); + } +#ifdef BASOP_NOGLOB + Lcorx2 = L_mac_o( Lcorx2, S[i], S[i], &Overflow ); + Lcory2 = L_mac_o( Lcory2, old_S[i], old_S[i], &Overflow ); + Lcorxy = L_mac_o( Lcorxy, S[i], old_S[i], &Overflow ); +#else /* BASOP_NOGLOB */ + Lcorx2 = L_mac( Lcorx2, S[i], S[i] ); + Lcory2 = L_mac( Lcory2, old_S[i], old_S[i] ); + Lcorxy = L_mac( Lcorxy, S[i], old_S[i] ); +#endif + } + + Copy( S, old_S, ind_mins[0] ); + Copy( &S[ind_mins[N_mins]], &old_S[ind_mins[N_mins]], sub( L, ind_mins[N_mins] ) ); + } + ELSE + { + *sp_floor = Bin_E[0]; + move16(); + } + *sp_floor = mult( *sp_floor, 14231 /*1.0f / logf( 10.0f ) Q15*/ ); + move16(); /* Convert to log10() */ + + /*------------------------------------------------------------------* + * updating of the long-term correlation map + * summation of the long-term correlation map + *------------------------------------------------------------------*/ + + Lcor_map_LT_sum = L_deposit_l( 0 ); + tmp2 = 0; + move16(); + + cor_strong = 0; + move16(); + pt1 = cor_map_LT; + move16(); + pt2 = cor_map; + move16(); + FOR( i = 0; i < L; i++ ) + { + /* tmp2 += S[i]; */ + tmp2 = add( tmp2, shl( S[i], 1 ) ); /* tmp2 in Q8; max value is 128) */ + + /* *pt1 = M_ALPHA_FX * *pt1 + (1-M_ALPHA_FX) * *pt2++ */ + *pt1 = mac_r( L_mult( ONE_MINUS_M_ALPHA, *pt2 ), M_ALPHA_FX, *pt1 ); + move16(); + + /* cor_map_LT_sum += *pt1 */ + Lcor_map_LT_sum = L_add( Lcor_map_LT_sum, *pt1 ); /* cor_map_LT_sum in Q15; max value is 128) */ + + if ( GT_16( *pt1, 31130 ) /*0.95f*/ ) + { + cor_strong = 1; + move16(); + } + + pt1++; + pt2++; + } + + IF( EQ_16( bwidth, NB ) ) + { + /* cor_map_LT_sum *= 1.53f; */ + /* tmp2 *= 1.53f; */ + Lcor_map_LT_sum = L_shl( Mult_32_16( Lcor_map_LT_sum, 25068 /*1.53f Q14*/ ), 1 ); + tmp2 = round_fx( L_mac( L_mult( tmp2, 32767 ), tmp2, 17367 /*0.53 Q15*/ ) ); + } + *cor_map_sum = tmp2; + move16(); + + /* final decision about multi-harmonicity */ + harm = 0; + move16(); + test(); + if ( ( L_msu0( Lcor_map_LT_sum, *multi_harm_limit, 64 ) > 0 ) || ( cor_strong != 0 ) ) + { + harm = 1; + move16(); + } + + /*------------------------------------------------------------------* + * updating of the decision threshold + *------------------------------------------------------------------*/ + + stemp = add( *multi_harm_limit, THR_CORR_STEP_FX ); + if ( GT_32( Lcor_map_LT_sum, THR_CORR_FX ) ) /* Q15 */ + { + /* *multi_harm_limit -= THR_CORR_STEP_FX */ + stemp = sub( *multi_harm_limit, THR_CORR_STEP_FX ); + } + + stemp = s_min( stemp, THR_CORR_MAX_FX ); + *multi_harm_limit = s_max( stemp, THR_CORR_MIN_FX ); + move16(); + + IF( N_mins <= 0 ) + { + set16_fx( old_S, 0, L ); + } + IF( S_map != NULL ) + { + Copy( S, S_map, L ); + } + return harm; +} + +#endif diff --git a/lib_enc/nelp_enc_fx.c b/lib_enc/nelp_enc_fx.c index 576a9ea208e4f0276e6bfe0dd3e33334567305cc..9df21a2001573db739f00716b94511c95fec1ac0 100644 --- a/lib_enc/nelp_enc_fx.c +++ b/lib_enc/nelp_enc_fx.c @@ -34,6 +34,7 @@ #include "control.h" #include "options.h" /* Compilation switches */ #include "cnst.h" /* Common constants */ +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "rom_com.h" @@ -1095,3 +1096,821 @@ void nelp_encoder_fx( return; } + +void nelp_encoder_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state */ + Word16 *in_fx, /* i : residual signal */ + Word16 *exc_fx, /* o : NELP quantized excitation signal */ + Word16 *qIn1, + Word16 reduce_gains ) +{ + Word16 i, j; + Word16 *ptr_fx = exc_fx; + Word16 lag = 25; /* to cover 25*9 + 31 */ + move16(); + Word16 sqrt_inv_lag = 6554; /* sqrt(1/lag) in Q15 */ + move16(); + Word16 sqrt_inv_lframe_lag = 5885; /* sqrt(1/(L_FRAME-lag*9)) */ + move16(); + Word16 Gains_fx[10], gain_fac_fx; + Word16 iG1_fx, iG2_fx[2]; + Word16 fid; + Word16 fdbck_fx; + Word32 var_dB_fx; + Word32 E1_fx = 0, EL1_fx = 0, EH1_fx = 0, E2_fx = 0, E3_fx = 0, EL2_fx = 0, EH2_fx = 0; + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + Word32 RL_fx = 0, RH_fx = 0; + move32(); + move32(); + Word16 R_fx = 0; + move16(); + Word16 filtRes_fx[L_FRAME]; + Word16 ptr_tmp_fx[L_FRAME]; + + Word16 qE1 = 0, qE2 = 0, qE3 = 0, qEL1 = 0, qEL2 = 0, qEH1 = 0, qEH2 = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 qIn = 0, qGain = 0, qf = 0, qf1 = 0, qNelpGain = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 exp1, exp2, tmp1, tmp2; + Word16 f_Noise, etmp, e_Noise; + Word16 max1 = 0; + move16(); + Word32 l_nelp_gain_mem; + Word32 Ltemp = 0, Ltemp1 = 0, L_tmp = 0, L_const_1; + move32(); + move32(); + move32(); + Word16 BP1_ORDER; + Word16 rf_flag; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + RF_ENC_HANDLE hRF = st_fx->hRF; + + rf_flag = st_fx->rf_mode; + move16(); + + test(); + if ( EQ_16( hSC_VBR->last_nelp_mode, 1 ) && NE_16( st_fx->bwidth, st_fx->last_bwidth ) ) + { + hSC_VBR->last_nelp_mode = 0; + move16(); + } + + qIn = *qIn1; + move16(); + test(); + IF( EQ_16( st_fx->bwidth, NB ) ) + { + IF( hSC_VBR->last_nelp_mode != 1 ) + { + BP1_ORDER = 7; + move16(); + set32_fx( hSC_VBR->bp1_filt_mem_nb_fx, 0, BP1_ORDER * 2 ); + hSC_VBR->qprevGain_fx = 0; + move16(); + } + } + ELSE IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + IF( hSC_VBR->last_nelp_mode != 1 ) + { + BP1_ORDER = 4; + move16(); + set16_fx( hSC_VBR->bp1_filt_mem_wb_fx, 0, i_mult( BP1_ORDER, 2 ) ); + } + } + + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) + { + test(); + IF( st_fx->bwidth == WB || EQ_16( st_fx->bwidth, SWB ) ) + { + set16_fx( hSC_VBR->shape1_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->shape2_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->shape3_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txlpf1_filt1_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txlpf1_filt2_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txhpf1_filt1_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txhpf1_filt2_mem_fx, 0, 10 ); + hSC_VBR->qprevIn_fx = 0; + move16(); + hSC_VBR->qprevGain_fx = 0; + move16(); + } + } + + /* Start Unvoiced/NELP Processing */ + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + qE1 = qIn; + move16(); + E1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + E1_fx = L_mac0_o( E1_fx, in_fx[i], in_fx[i], &Overflow ); /*Q(qE1+qE1) */ +#else + E1_fx = L_mac0( E1_fx, in_fx[i], in_fx[i] ); /*Q(qE1+qE1) */ +#endif + } + + qE1 = shl( qE1, 1 ); + + qf = qIn; + move16(); + Scale_sig( hSC_VBR->txlpf1_filt1_mem_fx, 10, ( qf - hSC_VBR->qprevIn_fx ) ); + pz_filter_sp_fx( txlpf1_num_coef_fx, txlpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txlpf1_filt1_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + + qEL1 = qf; + move16(); + EL1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EL1_fx = L_mac0_o( EL1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow ); /*Q(2*qIn) */ +#else + EL1_fx = L_mac0( EL1_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qIn) */ +#endif + } + qEL1 = shl( qEL1, 1 ); + + qf = qIn; + move16(); + Scale_sig( hSC_VBR->txhpf1_filt1_mem_fx, 10, qf - hSC_VBR->qprevIn_fx ); + pz_filter_sp_fx( txhpf1_num_coef_fx, txhpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txhpf1_filt1_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + hSC_VBR->qprevIn_fx = qf; + move16(); + + qEH1 = qf; + move16(); + EH1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EH1_fx = L_mac0_o( EH1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow ); /*Q(2*qEH1) */ +#else + EH1_fx = L_mac0( EH1_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH1) */ +#endif + } + qEH1 = shl( qEH1, 1 ); + move16(); + } + + qGain = qIn; + move16(); + qGain = shl( qGain, 1 ); + move16(); + + FOR( i = 0; i < 9; i++ ) + { + Ltemp = L_deposit_l( 0 ); + FOR( j = (Word16) ( i * lag ); j < (Word16) ( ( i + 1 ) * lag ); j++ ) + { +#ifdef BASOP_NOGLOB + Ltemp = L_mac0_o( Ltemp, in_fx[j], in_fx[j], &Overflow ); /*Q(2*qGain) */ +#else + Ltemp = L_mac0( Ltemp, in_fx[j], in_fx[j] ); /*Q(2*qGain) */ +#endif + } + + /*Gains[i] = (float) sqrt(Gains[i]/lag); */ + IF( Ltemp != 0 ) + { + exp1 = norm_l( Ltemp ); + tmp1 = extract_h( L_shl( Ltemp, exp1 ) ); /*2*qGain+exp1-16 */ + exp1 = sub( exp1, 30 - qGain ); /* */ + + tmp1 = div_s( 16384, tmp1 ); /*14-2*qGain-exp1+16 */ + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + L_tmp = Mult_32_16( L_tmp, sqrt_inv_lag ); +#ifdef BASOP_NOGLOB + Ltemp = L_shl_sat( L_tmp, sub( exp1, 12 ) ); /*Q3 */ +#else + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); /*Q3 */ +#endif + } +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( Ltemp ); +#else + Gains_fx[i] = round_fx( Ltemp ); +#endif + move16(); + } + + + Ltemp = L_deposit_l( 0 ); + FOR( j = i_mult( i, lag ); j < L_FRAME; j++ ) + { +#ifdef BASOP_NOGLOB + Ltemp = L_mac0_o( Ltemp, in_fx[j], in_fx[j], &Overflow ); /*Q(2*qGain) */ +#else + Ltemp = L_mac0( Ltemp, in_fx[j], in_fx[j] ); /*Q(2*qGain) */ +#endif + } + + /*Gains[i] = (float) sqrt(Gains[i]/(L_FRAME-(lag*i))); */ + IF( Ltemp != 0 ) + { + exp1 = norm_l( Ltemp ); + tmp1 = extract_h( L_shl( Ltemp, exp1 ) ); + exp1 = sub( exp1, 30 - qGain ); /* */ + + tmp1 = div_s( 16384, tmp1 ); + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + L_tmp = Mult_32_16( L_tmp, sqrt_inv_lframe_lag ); +#ifdef BASOP_NOGLOB + Ltemp = L_shl_sat( L_tmp, sub( exp1, 12 ) ); +#else + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); +#endif + } + +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( Ltemp ); +#else + Gains_fx[i] = round_fx( Ltemp ); +#endif + move16(); + + IF( EQ_16( reduce_gains, 1 ) ) + { + FOR( i = 0; i < 10; i++ ) + { + Gains_fx[i] = mult( Gains_fx[i], 19661 ); + move16(); + } + } + + + qGain = 3; + move16(); + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) /* if prev frame was not NELP then init mem*/ + { + hSC_VBR->nelp_gain_mem_fx = Gains_fx[0]; + move16(); + qNelpGain = qGain; + move16(); + } + + /* tmp = (float) (20.0 * (log10 (Gains[0]) - log10 (st->nelp_gain_mem) ) ); */ + /* var_dB = tmp * tmp; */ + L_tmp = L_deposit_l( Gains_fx[0] ); + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*log(2) in Q13 format = Q0 format */ + /*tmp1 = round_fx(L_shl(Ltemp,12)); Q12 */ + + L_tmp = L_deposit_l( hSC_VBR->nelp_gain_mem_fx ); /*Q0 */ + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qNelpGain ); + tmp2 = Log2_norm_lc( L_tmp ); + Ltemp1 = Mpy_32_16( exp2, tmp2, 9864 ); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub( Ltemp, Ltemp1 ); /*Q16 */ + Ltemp = Mult_32_16( Ltemp1, 20480 ); /*Q11 (20 in Q10) */ + L_tmp = L_shl( Ltemp, 12 ); /*Q23 */ + var_dB_fx = Mult_32_32( L_tmp, L_tmp ); /*Q15 */ + + FOR( i = 1; i < 10; i++ ) + { + L_tmp = L_deposit_l( Gains_fx[i] ); + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*log(2) in Q13 format = Q0 format */ + + L_tmp = L_deposit_l( Gains_fx[i - 1] ); /*Q0 */ + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp2 = Log2_norm_lc( L_tmp ); + Ltemp1 = Mpy_32_16( exp2, tmp2, 9864 ); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub( Ltemp, Ltemp1 ); /*Q16 */ + Ltemp = Mult_32_16( Ltemp1, 20480 ); /*Q11 (20 in Q10) */ + L_tmp = L_shl( Ltemp, 12 ); /*Q23 */ + L_tmp = Mult_32_32( L_tmp, L_tmp ); /*Q15 */ + var_dB_fx = L_add( L_tmp, var_dB_fx ); /*Q15 */ + } + + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) + { + /*var_dB *= 0.111f; */ + var_dB_fx = Mult_32_16( var_dB_fx, 3637 ); /*0.111 in Q15 */ + } + ELSE + { + /*var_dB *= 0.1f; */ + var_dB_fx = Mult_32_16( var_dB_fx, 3277 ); /*0.1 in Q15 */ + } + + max1 = 0; + move16(); + FOR( i = 0; i < 10; i++ ) + { + max1 = s_max( max1, abs_s( Gains_fx[i] ) ); + } + + qf = norm_s( max1 ); + test(); + IF( ( qf == 0 ) && ( max1 == 0 ) ) + { + qf = 15; + move16(); + } + qf = sub( qf, 1 ); + qGain = add( qGain, qf ); + + Scale_sig( Gains_fx, 10, qf ); + + L_tmp = L_sub( var_dB_fx, 655360 ); /* 20 in Q15 */ + Ltemp = L_shr_r( L_tmp, 2 ); /*Q15 */ + { + /*exp = pow(2, x*log2(e)) */ + L_tmp = Mult_32_16( Ltemp, 23637 ); /*15 + 14 -15 ->Q14 */ + L_tmp = L_shl( L_tmp, 2 ); /*Q16 */ + f_Noise = L_Extract_lc( L_tmp, &e_Noise ); /*Q16 */ + etmp = extract_l( Pow2( 14, f_Noise ) ); /* Put 14 as exponent */ + e_Noise = sub( e_Noise, 14 ); /* Retreive exponent of etmp */ + + + IF( e_Noise > 0 ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( etmp, e_Noise ); /* Result in Q30 */ + L_tmp = L_add_sat( 1, L_tmp ); +#else + L_tmp = L_shl( etmp, e_Noise ); /* Result in Q30 */ + L_tmp = L_add( 1, L_tmp ); +#endif + + + exp1 = norm_l( L_tmp ); + tmp1 = extract_h( L_shl( L_tmp, exp1 ) ); /*exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(exp1-16)-> 30+15-exp1 */ + fdbck_fx = mult( 26870, tmp1 ); /*45-exp1+15-15=>45-exp1 */ + fdbck_fx = shr_r( fdbck_fx, 14 ); + exp1 = sub( 31, exp1 ); + } + ELSE + { + L_tmp = L_shl( etmp, add( e_Noise, 14 ) ); /* Result in Q30 */ + L_tmp = L_add( 16384, L_tmp ); + + exp1 = norm_l( L_tmp ); + tmp1 = extract_h( L_shl( L_tmp, exp1 ) ); /*14+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(14+exp1-16)-> 16+15-exp1 */ + fdbck_fx = mult( 26870, tmp1 ); /*31-exp1+15-15=>31-exp1 */ + exp1 = sub( 31, exp1 ); + } + } + + IF( EQ_16( exp1, 31 ) ) + { + L_const_1 = 0x7fffffff; + move32(); + } + ELSE + { + L_const_1 = L_shl( 1, exp1 ); + } + + l_nelp_gain_mem = L_deposit_l( hSC_VBR->nelp_gain_mem_fx ); + IF( NE_16( qNelpGain, qGain ) ) + { + l_nelp_gain_mem = L_shl( l_nelp_gain_mem, sub( qGain, qNelpGain ) ); + } + + FOR( i = 0; i < 10; i++ ) + { + /*Gains[i] = (float)((1.0f - fdbck) * Gains[i] + fdbck * st->nelp_gain_mem); */ + L_tmp = L_sub( L_const_1, L_deposit_l( fdbck_fx ) ); /*31-exp1 */ + L_tmp = Mult_32_16( L_tmp, Gains_fx[i] ); /*exp1+qGain-15=>exp1-15+qGain */ + Ltemp1 = Mult_32_16( l_nelp_gain_mem, fdbck_fx ); /*exp1+qGain-15 */ + L_tmp = L_add( L_tmp, Ltemp1 ); + L_tmp = L_shr_r( L_tmp, ( exp1 - 15 ) ); +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); +#else + Gains_fx[i] = round_fx( L_shl( L_tmp, 16 ) ); +#endif + move16(); + l_nelp_gain_mem = L_tmp; + } + + hSC_VBR->nelp_gain_mem_fx = round_fx( L_shl( l_nelp_gain_mem, 16 ) ); + move16(); + + Scale_sig( &hSC_VBR->nelp_gain_mem_fx, 1, -qGain ); + Scale_sig( Gains_fx, 10, -qGain ); + qGain = 0; + move16(); + + quantize_uvg_fx( Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth ); + + IF( EQ_16( rf_flag, 1 ) ) + { + hRF->rf_indx_nelp_iG1[0] = iG1_fx; + move16(); + hRF->rf_indx_nelp_iG2[0][0] = iG2_fx[0]; + move16(); + hRF->rf_indx_nelp_iG2[0][1] = iG2_fx[1]; + move16(); + } + ELSE + { + push_indice( hBstr, IND_IG1, iG1_fx, 5 ); + push_indice( hBstr, IND_IG2A, iG2_fx[0], 6 ); + push_indice( hBstr, IND_IG2B, iG2_fx[1], 6 ); + } + + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + gain_fac_fx = 19005; + move16(); /* 1.16f in Q14 */ + } + ELSE + { + gain_fac_fx = 22446; + move16(); /* 1.37f in Q14 */ + } + + /* Normalize Gains_fx[10] with headroom 4 */ + /* This fills up qGain with some new value */ + normalize_arr( Gains_fx, &qGain, 10, 4 ); + + generate_nelp_excitation_fx( &( hSC_VBR->nelp_enc_seed ), Gains_fx, ptr_fx, gain_fac_fx ); + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + BP1_ORDER = 4; + move16(); + Scale_sig( hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER * 2, qGain - hSC_VBR->qprevGain_fx ); /*qf-qAdj */ + pz_filter_sp_fx( bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, 2 ); + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + } + ELSE IF( EQ_16( st_fx->bwidth, NB ) ) + { + BP1_ORDER = 7; + move16(); + Scale_sig32( hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER * 2, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_dp_fx( bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_NB_QF_ORDER7 ) ) ); + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + Scale_sig( ptr_fx, L_FRAME, -1 ); /* bring exc to qgain-1 */ + *qIn1 = sub( qGain, 1 ); /* use this temp only in the parent */ + } + + E3_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + E3_fx = L_mac_sat( E3_fx, ptr_fx[i], ptr_fx[i] ); /*Q1 */ +#else + E3_fx = L_mac( E3_fx, ptr_fx[i], ptr_fx[i] ); /*Q1 */ +#endif + } + qE3 = add( shl( qGain, 1 ), 1 ); + + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + Scale_sig( hSC_VBR->shape1_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape1_num_coef_fx, shape1_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape1_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + qf = qGain; + move16(); + E2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( ptr_fx[i], ptr_fx[i] ); /*Q(2*qE2+1) */ + Ltemp = L_shr_r( Ltemp, 4 ); + E2_fx = L_add( E2_fx, Ltemp ); + } + qE2 = sub( shl( qf, 1 ), 4 ); + + test(); + IF( E1_fx == 0 ) + { + R_fx = 0; + move16(); + } + ELSE IF( ( E2_fx == 0 ) && ( E1_fx != 0 ) ) + { + exp1 = norm_l( E1_fx ); + tmp1 = extract_h( L_shl( E1_fx, exp1 ) ); /*qE1+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE1+exp1-16)-> 30-qE1-exp1 */ + exp1 = sub( exp1, 30 - qE1 ); + + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); + R_fx = round_fx( Ltemp ); + } + ELSE + { + exp1 = norm_l( E1_fx ); + tmp1 = extract_h( L_shl( E1_fx, exp1 ) ); /*qE1+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE1+exp1-16)-> 30-qE1-exp1 */ + L_tmp = Mult_32_16( E2_fx, tmp1 ); /*qE2+30-qE1-exp1-15=>15+qE2-qE1-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qE2-qE1-exp1+exp2 */ + exp2 = add( 15, add( sub( sub( qE2, qE1 ), exp1 ), exp2 ) ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); /*Q(31+exp2) */ + R_fx = round_fx( L_tmp ); + exp1 = sub( 8, exp2 ); + } + + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( R_fx, ptr_fx[i] ); + Ltemp = L_shr_r( Ltemp, exp1 ); +#ifdef BASOP_NOGLOB + filtRes_fx[i] = round_fx_sat( L_shl_sat( Ltemp, 16 ) ); +#else + filtRes_fx[i] = round_fx( L_shl( Ltemp, 16 ) ); +#endif + move16(); + } + + qf1 = qGain; + move16(); + Scale_sig( hSC_VBR->txlpf1_filt2_mem_fx, 10, ( qf1 - hSC_VBR->qprevGain_fx ) ); + + pz_filter_sp_fx( txlpf1_num_coef_fx, txlpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txlpf1_filt2_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, filtRes_fx, L_FRAME ); + + qEL2 = qf1; + move16(); + EL2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EL2_fx = L_mac0_sat( EL2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEL2) */ +#else + EL2_fx = L_mac0( EL2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEL2) */ +#endif + } + qEL2 = shl( qEL2, 1 ); + + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( R_fx, ptr_fx[i] ); + Ltemp = L_shr_r( Ltemp, exp1 ); +#ifdef BASOP_NOGLOB + filtRes_fx[i] = round_fx_sat( L_shl_sat( Ltemp, 16 ) ); +#else + filtRes_fx[i] = round_fx( L_shl( Ltemp, 16 ) ); +#endif + move16(); + } + + qf = qGain; + move16(); + Scale_sig( hSC_VBR->txhpf1_filt2_mem_fx, 10, ( qf - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( txhpf1_num_coef_fx, txhpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txhpf1_filt2_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + + Copy( ptr_tmp_fx, filtRes_fx, L_FRAME ); + + qEH2 = qf; + move16(); + EH2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EH2_fx = L_mac0_sat( EH2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH2) */ +#else + EH2_fx = L_mac0( EH2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH2) */ +#endif + } + qEH2 = shl( qEH2, 1 ); + IF( EL2_fx == 0 ) + { + exp2 = norm_l( EL1_fx ); + L_tmp = L_shl( EL1_fx, exp2 ); + exp2 = sub( sub( 30, exp2 ), qEL1 ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q15 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RL_fx = L_mult0( tmp1, 10 ); + } + ELSE + { + exp1 = norm_l( EL2_fx ); + tmp1 = extract_h( L_shl( EL2_fx, exp1 ) ); /*qEL2+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qEL2+exp1-16)-> 30-qEL2-exp1 */ + L_tmp = Mult_32_16( EL1_fx, tmp1 ); /*qEL1+30-qEL2-exp1-15=>15+qE1-qEL2-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( 30, add( sub( sub( add( 30, qEL1 ), qEL2 ), exp1 ), exp2 ) ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q15 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RL_fx = L_mult0( tmp1, 10 ); + } + + IF( EH2_fx == 0 ) + { + exp2 = norm_l( EH2_fx ); + L_tmp = L_shl( EH2_fx, exp2 ); + exp2 = sub( sub( 30, exp2 ), qEH2 ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q13 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RH_fx = L_mult0( tmp1, 10 ); + } + ELSE + { + exp1 = norm_l( EH2_fx ); + tmp1 = extract_h( L_shl( EH2_fx, exp1 ) ); /*qEH2+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qEH2+exp1-16)-> 30-qEH2-exp1 */ + L_tmp = Mult_32_16( EH1_fx, tmp1 ); /*15+qEH1-qEH2-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEH1-qEH2-exp1+exp2 */ + exp2 = sub( 30, add( 30, add( sub( sub( qEH1, qEH2 ), exp1 ), exp2 ) ) ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q13 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RH_fx = L_mult0( tmp1, 10 ); + } + + fid = 0; + move16(); + IF( LT_32( RL_fx, -12288 ) ) /* -3 in Q12 */ + { + fid = 1; + move16(); + } + ELSE IF( LT_32( RH_fx, -12288 ) ) /* -3 in Q12 */ + { + fid = 2; + move16(); + } + + IF( rf_flag == 0 ) + { + + SWITCH( fid ) + { + case 1: + /* Update other filter memory */ + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + BREAK; + case 2: + /* Update other filter memory */ + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + BREAK; + default: + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + BREAK; + } + + qE2 = qGain; + move16(); + + E2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( ptr_fx[i], ptr_fx[i] ); /*Q(2*qE2+1) */ + Ltemp = L_shr_r( Ltemp, 4 ); + E2_fx = L_add( E2_fx, Ltemp ); + } + qE2 = sub( shl( qE2, 1 ), 4 ); + + test(); + IF( E3_fx == 0 ) + { + R_fx = 0; + move16(); + } + ELSE IF( ( E2_fx == 0 ) && ( E3_fx != 0 ) ) + { + exp1 = norm_l( E3_fx ); + tmp1 = extract_h( L_shl( E3_fx, exp1 ) ); /*qE3+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE3+exp1-16)-> 30-qE3-exp1 */ + exp1 = sub( exp1, 30 - qE3 ); + + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); + R_fx = round_fx( Ltemp ); + } + ELSE + { + exp1 = norm_l( E3_fx ); + tmp1 = extract_h( L_shl( E3_fx, exp1 ) ); /*qE3+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE3+exp1-16)-> 30-qE3-exp1 */ + L_tmp = Mult_32_16( E2_fx, tmp1 ); /*qE2+30-qE3-exp1-15=>15+qE2-qE3-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qE2-qE3-exp1+exp2 */ + exp2 = sub( 30, add( sub( sub( add( 15, qE2 ), qE3 ), exp1 ), exp2 ) ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); /*Q(31+exp2) */ + R_fx = round_fx( L_tmp ); + exp1 = sub( sub( sub( 31, exp2 ), 16 ), 7 ); + } + + FOR( i = 0; i < L_FRAME; i++ ) + { + L_tmp = L_mult0( R_fx, ptr_fx[i] ); + L_tmp = L_shr_r( L_tmp, exp1 + 1 ); + ptr_fx[i] = round_fx( L_shl( L_tmp, 16 ) ); + } + *qIn1 = sub( qGain, 1 ); + } + + IF( EQ_16( rf_flag, 1 ) ) + { + hRF->rf_indx_nelp_fid[0] = fid; + move16(); + } + ELSE + { + push_indice( hBstr, IND_NELP_FID, fid, 2 ); + } + } + + hSC_VBR->qprevGain_fx = qGain; + move16(); + + IF( rf_flag == 0 ) + { + FOR( i = 0; i < L_FRAME; i++ ) + { + exc_fx[i] = ptr_fx[i]; + move16(); + } + } + + return; +} diff --git a/lib_enc/nois_est.c b/lib_enc/nois_est.c index 792ecd2f0075d197565413e9ca522bd44b0e598d..d6ebcc603fc5af430c084182da032a7187e1d238 100644 --- a/lib_enc/nois_est.c +++ b/lib_enc/nois_est.c @@ -85,7 +85,7 @@ * * Initialization of Noise estimator *-----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void noise_est_init( NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ ) @@ -102,8 +102,8 @@ void noise_est_init( hNoiseEst->bckr[i] = E_MIN; hNoiseEst->ave_enr[i] = E_MIN; } - hNoiseEst->totalNoise = 0.0f; + hNoiseEst->first_noise_updt = 0; hNoiseEst->first_noise_updt_cnt = 0; @@ -148,8 +148,9 @@ void noise_est_init( return; } +#endif - +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------* * noise_est_pre() * @@ -514,7 +515,7 @@ void noise_est( { ftemp2 /= ftemp; } - +#ifndef IVAS_FLOAT_FIXED if ( hStereoClassif != NULL ) { if ( st->idchan == 0 ) @@ -526,7 +527,7 @@ void noise_est( hStereoClassif->nchar_ch2 = ftemp2; } } - +#endif if ( ftemp2 > 10 ) { ftemp2 = 10; @@ -628,7 +629,7 @@ void noise_est( { if ( i >= START_BAND_SPMUS && i < NB_BANDS_SPMUS + START_BAND_SPMUS && st->hSpMusClas != NULL ) { - log_enr = (float) log( enr[i] ); + log_enr = (float) log( enr[i] + EPSILON ); if ( log_enr > st->hSpMusClas->past_log_enr[i - START_BAND_SPMUS] ) { *non_staX += log_enr - st->hSpMusClas->past_log_enr[i - START_BAND_SPMUS]; @@ -1002,3 +1003,4 @@ void noise_est( return; } +#endif diff --git a/lib_enc/nois_est_fx.c b/lib_enc/nois_est_fx.c index dbb29cc6c27df3c6cee8a3a85e790040fc03315d..c3af6c90467ce04790c938151de2acc60a678894 100644 --- a/lib_enc/nois_est_fx.c +++ b/lib_enc/nois_est_fx.c @@ -224,7 +224,20 @@ void noise_est_init_fx( move16(); hNoiseEst->lt_aEn_zero_fx = 0; move16(); - + hNoiseEst->Etot_h_32fx = 0; + move32(); + hNoiseEst->Etot_l_32fx = 0; + move32(); + hNoiseEst->Etot_l_lp_32fx = 0; + move32(); + hNoiseEst->Etot_last_32fx = 0; + move32(); + hNoiseEst->Etot_v_h2_32fx = 0; + move32(); + hNoiseEst->Etot_lp_32fx = 0; + move32(); + hNoiseEst->sign_dyn_lp_32fx = 0; + move32(); /* Tonal detector */ FOR( i = 0; i < L_FFT / 2; i++ ) { @@ -255,6 +268,140 @@ void noise_est_init_fx( return; } + +void noise_est_init_ivas_fx( + NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ +) +{ + Word16 i; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( i = 0; i < NB_BANDS; i++ ) + { + hNoiseEst->fr_bands1[i] = 1e-5f; + hNoiseEst->fr_bands2[i] = 1e-5f; + hNoiseEst->ave_enr2[i] = E_MIN; + + hNoiseEst->enrO[i] = E_MIN; + hNoiseEst->bckr[i] = E_MIN; + hNoiseEst->ave_enr[i] = E_MIN; + } + hNoiseEst->first_noise_updt = 0; + hNoiseEst->first_noise_updt_cnt = 0; + + hNoiseEst->aEn = 6; + hNoiseEst->aEn_inac_cnt = 0; + hNoiseEst->harm_cor_cnt = 0; + hNoiseEst->bg_cnt = 0; + hNoiseEst->low_tn_track_cnt = 0; + + hNoiseEst->Etot_lp = 0.0f; + hNoiseEst->Etot_l_lp = 0.0f; + hNoiseEst->Etot_last = 0.0f; + hNoiseEst->Etot_v_h2 = 0.0f; + hNoiseEst->sign_dyn_lp = 0.0f; +#endif + FOR( i = 0; i < NB_BANDS; i++ ) + { + hNoiseEst->fr_bands1_fx[i] = 1; + move32(); /*1e-5f; */ + hNoiseEst->fr_bands2_fx[i] = 1; + move32(); /*1e-5f; */ + hNoiseEst->ave_enr2_fx[i] = E_MIN_FX; + move32(); /*Q7//E_MIN; */ + hNoiseEst->enrO_fx[i] = E_MIN_Q11_FX; + move32(); + hNoiseEst->bckr_fx[i] = E_MIN_Q11_FX; + move32(); + hNoiseEst->ave_enr_fx[i] = E_MIN_FX; + move32(); + } + move16(); + hNoiseEst->totalNoise_fx = 0; + move16(); + hNoiseEst->first_noise_updt = 0; + // hNoiseEst->first_noise_updt_cnt_fx = 0; IVAS_CODE ?? + move16(); + + hNoiseEst->aEn = 6; + // hNoiseEst->aEn_inac_cnt = 0; IVAS_CODE + move16(); + + hNoiseEst->harm_cor_cnt = 0; + move16(); + hNoiseEst->bg_cnt = 0; + move16(); + + hNoiseEst->lt_tn_track_fx = 6554; /*.20 in Q15*/ + move16(); + hNoiseEst->lt_tn_dist_fx = 0; + move16(); + hNoiseEst->lt_Ellp_dist_fx = 0; + move16(); + hNoiseEst->lt_haco_ev_fx = 13107; /*.40 in Q15*/ + move16(); + hNoiseEst->low_tn_track_cnt = 0; + move16(); + + hNoiseEst->Etot_st_est_fx = 5120; /* 20.0f in Q8 */ + hNoiseEst->Etot_sq_st_est_fx = 1600; /* 400 in Q2 */ + //### + + hNoiseEst->epsP_0_2_lp_fx = 4096; /*1.0 Q12*/ + move16(); + hNoiseEst->epsP_0_2_ad_lp_fx = 0; + move16(); + hNoiseEst->epsP_2_16_lp_fx = 4096; + move16(); + hNoiseEst->epsP_2_16_lp2_fx = 4096; + move16(); + hNoiseEst->epsP_2_16_dlp_lp2_fx = 0; + move16(); + hNoiseEst->lt_aEn_zero_fx = 0; + move16(); + hNoiseEst->Etot_h_32fx = 0; + move32(); + hNoiseEst->Etot_l_32fx = 0; + move32(); + hNoiseEst->Etot_l_lp_32fx = 0; + move32(); + hNoiseEst->Etot_last_32fx = 0; + move32(); + hNoiseEst->Etot_v_h2_32fx = 0; + move32(); + hNoiseEst->Etot_lp_32fx = 0; + move32(); + hNoiseEst->sign_dyn_lp_32fx = 0; + move32(); + /* Tonal detector */ + FOR( i = 0; i < L_FFT / 2; i++ ) + { + hNoiseEst->old_S_fx[i] = ONE_IN_Q7; + move16(); + } + set16_fx( hNoiseEst->cor_map_fx, 0, L_FFT / 2 ); + hNoiseEst->act_pred_fx = 32767; + move16(); + hNoiseEst->noise_char_fx = 0; + move16(); + hNoiseEst->multi_harm_limit_fx = THR_CORR_INIT_FX; + + hNoiseEst->Etot_lp_fx = 0; + hNoiseEst->Etot_h_fx = 0; + hNoiseEst->Etot_l_fx = 0; + hNoiseEst->Etot_l_lp_fx = 0; + hNoiseEst->Etot_last_fx = 0; + hNoiseEst->Etot_v_h2_fx = 0; + hNoiseEst->sign_dyn_lp_fx = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + return; +} /*-----------------------------------------------------------------* * noise_est_pre_fx() * @@ -2025,6 +2172,7 @@ void noise_est_ivas_fx( const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ Word16 *cor_map_sum, /* o : Q8 */ + Word16 *ncharX, /* o : Q11 */ Word16 *sp_div, /* o : Q_sp_div */ Word16 *Q_sp_div, /* o : Q factor for sp_div */ Word16 *non_staX, /* o : non-stationarity for sp/mus classifier */ @@ -2051,6 +2199,7 @@ void noise_est_ivas_fx( Word32 th_sta, Lnum, Lden, non_sta, LepsP, Ltmpden; Word16 e_ener, f_ener; Word32 Ltmp, Ltmp1, Lsum_num, Lsum_den, *pt1, *pt2, Ltmp2, Lnon_sta2; + Word64 w_sum_num, w_tmp; Word16 spec_div, noise_char; Word16 log_enr16; Word16 updt_step; /* Q15 */ @@ -2096,6 +2245,7 @@ void noise_est_ivas_fx( GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif /*-----------------------------------------------------------------* @@ -2220,6 +2370,7 @@ void noise_est_ivas_fx( move16(); *loc_harm = multi_harm_fx( EspecdB, hNoiseEst->old_S_fx, hNoiseEst->cor_map_fx, &hNoiseEst->multi_harm_limit_fx, st_fx->total_brate, st_fx->bwidth, ( st_fx->hGSCEnc != NULL ) ? &hGSCEnc->cor_strong_limit : &i, &hSpMusClas->mean_avr_dyn_fx, &hSpMusClas->last_sw_dyn_fx, cor_map_sum, sp_floor, S_map ); + move16(); } } /*-----------------------------------------------------------------* @@ -2227,7 +2378,8 @@ void noise_est_ivas_fx( *-----------------------------------------------------------------*/ /* weighted sum of spectral changes per critical bands */ - Lsum_num = L_deposit_l( 0 ); + w_sum_num = 0; + move64(); Lsum_den = L_deposit_l( 0 ); /* Find a proper scaling to prevent overflow, but acheiving good computation on low level signals */ @@ -2265,38 +2417,35 @@ void noise_est_ivas_fx( ExpDen = norm_l( Ltmpden ); den = extract_h( L_shl( Ltmpden, ExpDen ) ); num = div_s( num, den ); - Ltmp = L_shr( num, add( sub( sub( shl( ExpNum, 1 ), ExpDen ), 15 + 1 ), tmpExp ) ); - Lsum_num = L_add( Lsum_num, Ltmp ); + w_tmp = W_shr( num, add( sub( sub( shl( ExpNum, 1 ), ExpDen ), 15 + 1 ), tmpExp ) ); + w_sum_num = W_add( w_sum_num, w_tmp ); pt1++; pt2++; } Lsum_den = L_shr( Lsum_den, tmpExp ); + ExpNum = W_norm( w_sum_num ); + Lsum_num = W_extract_h( W_shl( w_sum_num, ExpNum ) ); + ExpNum = sub( ExpNum, 32 ); /* calculation of spectral diversity */ /* THR_SPDIV_FX = 5 , 1/5 Q15 = 6554 */ spec_div = 0; move16(); - if ( GT_32( Mult_32_16( Lsum_num, 6554 ), Lsum_den ) ) /* Qx+Q15+1-16 ==> Qx */ + if ( GT_32( Mult_32_16( Lsum_num, 6554 ), L_shl_sat( Lsum_den, ExpNum ) ) ) /* Qx+Q15+1-16 ==> Qx */ { spec_div = 1; move16(); } /* *sp_div = Lsum_num / (Lsum_den + 1e-5f); */ - ExpNum = sub( norm_l( Lsum_num ), 1 ); - num = extract_h( L_shl( Lsum_num, ExpNum ) ); - Lsum_den = L_add( Lsum_den, 1 ); - - ExpDen = norm_l( Lsum_den ); - den = extract_h( L_shl( Lsum_den, ExpDen ) ); - - *sp_div = div_s( num, den ); + Word16 exp = 0; + *sp_div = BASOP_Util_Divide3232_Scale( Lsum_num, Lsum_den, &exp ); move16(); - *Q_sp_div = add( 15, sub( ExpNum, ExpDen ) ); + *Q_sp_div = add( sub( 15, exp ), ExpNum ); move16(); /*-----------------------------------------------------------------* @@ -2336,6 +2485,30 @@ void noise_est_ivas_fx( #endif /* BASOP_NOGLOB */ } + if ( ncharX != NULL ) + { + *ncharX = noise_chartmp; /* Q11 */ + move16(); + } + + IF( hStereoClassif != NULL ) + { + IF( st_fx->idchan == 0 ) + { + hStereoClassif->nchar_ch1_fx = noise_chartmp; /* Q11 */ + move32(); + hStereoClassif->nchar_ch1_e = 31 - Q11; + move16(); + } + ELSE + { + hStereoClassif->nchar_ch2_fx = noise_chartmp; /* Q11 */ + move32(); + hStereoClassif->nchar_ch2_e = 31 - Q11; + move16(); + } + } + noise_chartmp = s_min( noise_chartmp, (Word16) 10 << 11 ); /* Q11 */ /* update LT value of the final parameter */ @@ -2423,8 +2596,7 @@ void noise_est_ivas_fx( L_tmp_enr = L_add( enr[i], Ltmp ); /* enr scale dynamic */ L_tmp_ave_enr = L_add( hNoiseEst->ave_enr_fx[i], Ltmp ); /* ave__enr scale dynamic */ #endif /* BASOP_NOGLOB */ - - IF( LE_32( non_sta, th_sta ) ) /* Just to limit the saturation */ + IF( LE_32( non_sta, th_sta ) ) /* Just to limit the saturation */ { /* if( enr[i] > st_ave_enr2[i] ) */ /* non_sta2 = non_sta2 * ((enr[i]+1) / (st_ave_enr2[i]+1)) */ @@ -2559,7 +2731,7 @@ void noise_est_ivas_fx( lim_Etot_fx = s_max( 5120, Etot ); /* 20.0f Q8 */ lim_Etot_sq_fx = extract_h( L_shl_r( L_mult( lim_Etot_fx, lim_Etot_fx ), 1 ) ); /* Q2 */ - if ( st_fx->ini_frame < 150 ) + IF( LT_16( st_fx->ini_frame, 150 ) ) { /* Allow use of quicker filter during init - if needed */ /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ @@ -2569,7 +2741,7 @@ void noise_est_ivas_fx( hNoiseEst->Etot_sq_st_est_fx = mac_r( L_mult( 8192, lim_Etot_sq_fx ), 24576, hNoiseEst->Etot_sq_st_est_fx ); move16(); } - else + ELSE { /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ hNoiseEst->Etot_st_est_fx = mac_r( L_mult( 8192, lim_Etot_fx ), 24576, hNoiseEst->Etot_st_est_fx ); @@ -2894,8 +3066,7 @@ void noise_est_ivas_fx( /*-----------------------------------------------------------------* * Stereo classifier - save raw aEn *-----------------------------------------------------------------*/ - - if ( hStereoClassif != NULL ) + IF( hStereoClassif != NULL ) { /* if ( ( non_sta > th_sta ) || @@ -2903,21 +3074,26 @@ void noise_est_ivas_fx( ( 0.5f * ( st->voicing[0] + st->voicing[1] ) > cor_max ) || ( epsP[2] / epsP[16] > th_eps ) || ( ( hNoiseEst->act_pred > 0.8f ) && ( non_sta2 > th_sta ) ) )*/ - if ( ( GT_32( non_sta, th_sta ) ) || ( LT_16( tmp_pc, TH_PC_FX ) ) || - ( GT_16( cor_tmp, cor_max ) ) || - ( GT_32( LepsP, th_eps ) ) || - ( ( GT_16( hNoiseEst->act_pred_fx, 26214 ) ) && ( GT_32( Lnon_sta2, th_sta ) ) ) ) /*act_pred in Q15 , th_sta in Q10 */ + test(); + test(); + test(); + test(); + test(); + IF( ( GT_32( non_sta, th_sta ) ) || ( LT_16( tmp_pc, TH_PC_FX ) ) || + ( GT_16( cor_tmp, cor_max ) ) || + ( GT_32( LepsP, th_eps ) ) || + ( ( GT_16( hNoiseEst->act_pred_fx, 26214 ) ) && ( GT_32( Lnon_sta2, th_sta ) ) ) ) /*act_pred in Q15 , th_sta in Q10 */ { /* active signal present - increment counter */ hStereoClassif->aEn_raw[st_fx->idchan] = hStereoClassif->aEn_raw[st_fx->idchan] + 2; } - else + ELSE { /* background noise present - decrement counter */ hStereoClassif->aEn_raw[st_fx->idchan] = hStereoClassif->aEn_raw[st_fx->idchan] - 1; } - - if ( hStereoClassif->aEn_raw[st_fx->idchan] > 6 ) + move16(); + if ( GT_16( hStereoClassif->aEn_raw[st_fx->idchan], 6 ) ) { hStereoClassif->aEn_raw[st_fx->idchan] = 6; } @@ -2925,6 +3101,7 @@ void noise_est_ivas_fx( { hStereoClassif->aEn_raw[st_fx->idchan] = 0; } + move16(); } @@ -3358,16 +3535,25 @@ void noise_est_ivas_fx( } } } - /*st->lt_aEn_zero = 0.2f * (st->aEn==0) + (1-0.2f) *st->lt_aEn_zero;*/ - /* y(n+1)= alpha*tmp + (1-alpha)*y(n) */ - tmp = 0; + } + /*st->lt_aEn_zero = 0.2f * (st->aEn==0) + (1-0.2f) *st->lt_aEn_zero;*/ + /* y(n+1)= alpha*tmp + (1-alpha)*y(n) */ + tmp = 0; + move16(); + if ( hNoiseEst->aEn == 0 ) + { + tmp = 32767; move16(); - if ( hNoiseEst->aEn == 0 ) + } + hNoiseEst->lt_aEn_zero_fx = noise_est_AR1_Qx( tmp, hNoiseEst->lt_aEn_zero_fx, 6554 ); /* alpha=0.2 , Q15 */ + IF( st_fx->element_mode > EVS_MONO ) + { + test(); + if ( hNoiseEst->first_noise_updt > 0 && LT_16( hNoiseEst->first_noise_updt_cnt, 100 ) ) { - tmp = 32767; + hNoiseEst->first_noise_updt_cnt = add( hNoiseEst->first_noise_updt_cnt, 1 ); move16(); } - hNoiseEst->lt_aEn_zero_fx = noise_est_AR1_Qx( tmp, hNoiseEst->lt_aEn_zero_fx, 6554 ); /* alpha=0.2 , Q15 */ } return; diff --git a/lib_enc/pit_enc_fx.c b/lib_enc/pit_enc_fx.c index 6bcf678a1dab815e60eeb7d424324c04c11cde48..b49e52fad2cb086226cf9b610aece67c1389e60d 100644 --- a/lib_enc/pit_enc_fx.c +++ b/lib_enc/pit_enc_fx.c @@ -10,69 +10,490 @@ #include "rom_com.h" /* Static table prototypes */ //#include "prot_fx.h" /* Function prototypes */ #include "rom_basop_util.h" +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define inv_T0_res InvIntTable + +static void limit_T0_voiced2( Word16 res, const Word16 *T_op, Word16 *T0_min, Word16 *T0_min_frac, Word16 *T0_max, Word16 *T0_max_frac, Word16 pit_min, Word16 pit_max, Word16 i_subfr ); + +/*==============================================================================*/ +/* FUNCTION : pit_encode_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Close-loop pitch lag search and pitch lag quantization */ +/* Adaptive excitation construction */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) core_brate: core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/* _ (Word16[]) T_op : open loop pitch estimates in current frame Q0 */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) h1 : weighted filter input response Q15 */ +/* _ (Word16[]) xn : target vector Q_new */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) i_subfr : current sub frame indicator Q0 */ +/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ +/* _ (Word16[]) L_subfr : subframe length Q0 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ + +Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 pitch_bits[], /* i : pitch bits */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *pitch, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ +) +{ + Word16 pitch_cl; + Word16 pit_flag, delta, mult_Top, nBits; + Word16 L_sufr_sft; + Word16 T_op[2]; /* values for two half-frames */ +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void) tdm_Pitch_reuse_flag; +#endif + + L_sufr_sft = 6; + move16(); + if ( EQ_16( L_subfr, 2 * L_SUBFR ) ) + { + L_sufr_sft = 7; + } + + /*----------------------------------------------------------------* + * convert pitch values to 16kHz domain + *----------------------------------------------------------------*/ + IF( EQ_16( L_frame, L_FRAME ) || ( tdm_Pri_pitch_buf != NULL && tdm_Pri_pitch_buf[0] < 0 ) ) + { + Copy( pitch, T_op, 2 ); + } + ELSE /* L_frame == L_FRAME16k */ + { + /*T_op[0] = (int16_t)(pitch[0] * 1.25f + 0.5f); + T_op[1] = (int16_t)(pitch[1] * 1.25f + 0.5f);*/ + T_op[0] = shr( add( round_fx( L_shl( L_mult( 20480, pitch[0] ), 2 ) ), 1 ), 1 ); + move16(); + T_op[1] = shr( add( round_fx( L_shl( L_mult( 20480, pitch[1] ), 2 ) ), 1 ), 1 ); + move16(); + } + + /*----------------------------------------------------------------* + * Set pit_flag to 0 for every subframe with absolute pitch search + *----------------------------------------------------------------*/ + pit_flag = i_subfr; + move16(); + if ( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + pit_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Limit range of pitch search + * Fractional pitch search + * Pitch quantization + *-----------------------------------------------------------------*/ + mult_Top = 1; + move16(); + + IF( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * pitch Q: Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + test(); + test(); + IF( i_subfr == 0 ) + { + *limit_flag = 1; + move16(); + if ( EQ_16( coder_type, VOICED ) ) + { + *limit_flag = 2; + move16(); /* double-extended limits */ + } + test(); + if ( EQ_16( coder_type, GENERIC ) && EQ_32( core_brate, ACELP_7k20 ) ) + { + *limit_flag = 0; + move16(); + } + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) && EQ_16( coder_type, GENERIC ) && LE_32( core_brate, ACELP_13k20 ) ) + { + /*if( *T0 > (PIT_FR1_EXTEND_8b + PIT_MIN)>>1 )*/ + if ( GT_16( *T0, shr( add( PIT_FR1_EXTEND_8b, PIT_MIN ), 1 ) ) ) + { + *limit_flag = 0; + move16(); + } + } + + IF( *limit_flag == 0 ) + { + test(); + test(); + IF( i_subfr == 0 && LT_16( T_op[0], PIT_MIN ) ) + { + mult_Top = 2; + move16(); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) && LT_16( T_op[1], PIT_MIN ) ) + { + mult_Top = 2; + move16(); + } + } + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + nBits = 0; + move16(); + IF( NE_16( coder_type, AUDIO ) ) + { + nBits = pitch_bits[shr( i_subfr, L_sufr_sft )]; + } + IF( EQ_16( coder_type, AUDIO ) ) + { + /*-------------------------------------------------------* + * Pitch encoding in AUDIO coder type + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + test(); + test(); + if ( EQ_16( L_subfr, L_frame / 2 ) && i_subfr != 0 && EQ_16( L_frame, L_FRAME ) ) + { + pit_flag = L_SUBFR; + move16(); + } + IF( pit_flag == 0 ) + { + nBits = 10; + move16(); + } + ELSE + { + nBits = 6; + move16(); + } + + /* pitch lag search limitation */ + test(); + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top * T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) && pit_flag == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top * T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_subfr ); + + pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16( coder_type, VOICED ) ) + { + /*-------------------------------------------------------* + * Pitch encoding in VOICED code type (ACELP@12k8 core only) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + if ( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + pit_flag = i_subfr; + move16(); + } + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, mult_Top * T_op[0], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + test(); + test(); + IF( EQ_16( nBits, 9 ) || EQ_16( nBits, 5 ) ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_DOUBLEEXTEND_9b, PIT_FR1_DOUBLEEXTEND_9b, L_FRAME, L_SUBFR ); + move16(); + } + ELSE IF( EQ_16( nBits, 10 ) ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + move16(); + } + + pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } +#ifdef ADD_LRTD + else if ( tdm_Pitch_reuse_flag == 1 || nBits == 4 ) + { + /*-------------------------------------------------------* + * Pitch encoding with reusing primary channel information + *-------------------------------------------------------*/ + int16_t loc_T0, loc_frac; + + delta = 4; + + pit_flag = L_SUBFR; + + if ( L_subfr == 2 * L_SUBFR ) + { + loc_T0 = (int16_t) ( 0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[( i_subfr + L_SUBFR ) / L_SUBFR] ); + loc_frac = (int16_t) ( ( ( 0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[( i_subfr + L_SUBFR ) / L_SUBFR] ) - loc_T0 ) * 4.0f ); + } + else + { + loc_T0 = (int16_t) tdm_Pri_pitch_buf[i_subfr / L_SUBFR]; + loc_frac = (int16_t) ( ( tdm_Pri_pitch_buf[i_subfr / L_SUBFR] - loc_T0 ) * 4.0f ); + } + + /* pitch lag search limitation */ + limit_T0( L_FRAME, delta, pit_flag, *limit_flag, loc_T0, loc_frac, T0_min, T0_max ); + if ( nBits > 0 ) + { + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + if ( delta == 8 ) + { + *T0_frac = 0; + } + pit_Q_enc( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + else + { + *T0 = loc_T0; + *T0_frac = loc_frac; + } + } +#endif + ELSE + { + /*-------------------------------------------------------* + * Pitch encoding in GENERIC coder type + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 8; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top * T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top * T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + IF( EQ_16( L_frame, L_FRAME ) ) + { + test(); + test(); + IF( EQ_16( nBits, 8 ) || EQ_16( nBits, 5 ) ) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN_EXTEND, PIT_FR1_EXTEND_8b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16( nBits, 9 ) || EQ_16( nBits, 6 ) ) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_EXTEND_9b, PIT_FR1_EXTEND_9b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16( nBits, 10 ) ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + } + + pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE /* L_frame == L_FRAME16k */ + { + test(); + IF( EQ_16( nBits, 9 ) || EQ_16( nBits, 6 ) ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_9b, PIT16k_FR1_EXTEND_9b, L_FRAME16k, L_SUBFR ); + } + ELSE IF( nBits == 10 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + + pit16k_Q_enc_fx( hBstr, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + } + } + + /*-------------------------------------------------------* + * Pitch encoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + ELSE + { + delta = 8; + move16(); + *limit_flag = 0; + move16(); + + IF( EQ_32( core_brate, ACELP_6k60 ) ) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2( mult_Top, T_op[0] ), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + if ( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + /* rewrite pit_flag - it must not be zero */ + pit_flag = i_subfr; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE IF( EQ_32( core_brate, ACELP_8k85 ) ) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2( mult_Top, T_op[0] ), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2( mult_Top, T_op[1] ), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + nBits = 6; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2( mult_Top, T_op[0] ), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE IF( EQ_16( i_subfr, 2 * L_SUBFR ) ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2( mult_Top, T_op[1] ), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } -#define inv_T0_res InvIntTable + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } -static void limit_T0_voiced2( Word16 res, const Word16 *T_op, Word16 *T0_min, Word16 *T0_min_frac, Word16 *T0_max, Word16 *T0_max_frac, Word16 pit_min, Word16 pit_max, Word16 i_subfr ); + pit_Q_enc_fx( hBstr, 1, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } -/*==============================================================================*/ -/* FUNCTION : pit_encode_fx() */ -/*------------------------------------------------------------------------------*/ -/* PURPOSE : Close-loop pitch lag search and pitch lag quantization */ -/* Adaptive excitation construction */ -/*------------------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* _ (Word16) core_brate: core bitrate Q0 */ -/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ -/* _ (Word16) bwidth : input signal bandwidth Q0 */ -/* _ (Word16[]) T_op : open loop pitch estimates in current frame Q0 */ -/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ -/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ -/* _ (Word16) T0 : close loop integer pitch Q0 */ -/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ -/* _ (Word16) L_frame_fx : length of the frame Q0 */ -/* _ (Word16[]) h1 : weighted filter input response Q15 */ -/* _ (Word16[]) xn : target vector Q_new */ -/* _ (Word16) coder_type : coding type Q0 */ -/* _ (Word16) i_subfr : current sub frame indicator Q0 */ -/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ -/* _ (Word16[]) L_subfr : subframe length Q0 */ -/*------------------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ -/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ -/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ -/* _ (Word16) T0 : close loop integer pitch Q0 */ -/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ -/*------------------------------------------------------------------------------*/ + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ -/*------------------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : */ -/* _ None */ -/*==============================================================================*/ + /*pitch = (float)(*T0) + (float)(*T0_frac)/4.0f;*/ /* save subframe pitch values */ + pitch_cl = shl( add( shl( *T0, 2 ), *T0_frac ), 4 ); /* save subframe pitch values Q6 */ -Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ - const Word16 pitch_bits[], /* i : pitch bits */ - const Word32 core_brate, /* i : core bitrate */ - const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ - const Word16 L_frame, /* i : length of the frame */ - const Word16 coder_type, /* i : coding type */ - Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ - const Word16 i_subfr, /* i : subframe index */ - Word16 *exc, /* i/o: pointer to excitation signal frame */ - const Word16 L_subfr, /* i : subframe length */ - const Word16 *pitch, /* i : open loop pitch estimates in current frame */ - Word16 *T0_min, /* i/o: lower limit for close-loop search */ - Word16 *T0_max, /* i/o: higher limit for close-loop search */ - Word16 *T0, /* i/o: close loop integer pitch */ - Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ - const Word16 *h1, /* i : weighted filter input response */ - const Word16 *xn, /* i : target vector */ - const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ - const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ + return pitch_cl; +} + +#ifdef IVAS_FLOAT_FIXED +Word16 pit_encode_ivas_fx( /* o : Fractional pitch for each subframe */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 pitch_bits[], /* i : pitch bits */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *pitch, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ ) { Word16 pitch_cl; @@ -262,45 +683,56 @@ Word16 pit_encode_fx( /* o : Fractional pitc pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); } -#ifdef ADD_LRTD - else if ( tdm_Pitch_reuse_flag == 1 || nBits == 4 ) +#if 1 + //#ifdef ADD_LRTD + ELSE IF( EQ_16( tdm_Pitch_reuse_flag, 1 ) || EQ_16( nBits, 4 ) ) { /*-------------------------------------------------------* * Pitch encoding with reusing primary channel information *-------------------------------------------------------*/ - int16_t loc_T0, loc_frac; + Word16 loc_T0, loc_frac; delta = 4; + move16(); pit_flag = L_SUBFR; + move16(); - if ( L_subfr == 2 * L_SUBFR ) + Word16 idx1 = shr( i_subfr, L_sufr_sft ); + Word16 idx2 = shr( add( i_subfr, 64 ), L_sufr_sft ); + + IF( EQ_16( L_subfr, 2 * L_SUBFR ) ) { - loc_T0 = (int16_t) ( 0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[( i_subfr + L_SUBFR ) / L_SUBFR] ); - loc_frac = (int16_t) ( ( ( 0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[( i_subfr + L_SUBFR ) / L_SUBFR] ) - loc_T0 ) * 4.0f ); + loc_T0 = add( shr( tdm_Pri_pitch_buf[idx1], 1 ), shr( tdm_Pri_pitch_buf[idx2], 1 ) ); // Q6 + loc_frac = shr( sub( loc_T0, shl( shr( loc_T0, 6 ), 6 ) ), 4 ); // Q2 + loc_T0 = shr( loc_T0, 6 ); // Q0 } - else + ELSE { - loc_T0 = (int16_t) tdm_Pri_pitch_buf[i_subfr / L_SUBFR]; - loc_frac = (int16_t) ( ( tdm_Pri_pitch_buf[i_subfr / L_SUBFR] - loc_T0 ) * 4.0f ); + loc_T0 = tdm_Pri_pitch_buf[idx1]; // Q6 + loc_frac = shr( sub( loc_T0, shl( shr( loc_T0, 6 ), 6 ) ), 4 ); // Q2 + loc_T0 = shr( loc_T0, 6 ); // Q0 } /* pitch lag search limitation */ - limit_T0( L_FRAME, delta, pit_flag, *limit_flag, loc_T0, loc_frac, T0_min, T0_max ); - if ( nBits > 0 ) + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, loc_T0, loc_frac, T0_min, T0_max ); + IF( nBits > 0 ) { /* search and encode the closed loop pitch period */ - *T0 = pitch_fr4( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); - if ( delta == 8 ) + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + IF( EQ_16( delta, 8 ) ) { *T0_frac = 0; + move16(); } - pit_Q_enc( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); } - else + ELSE { *T0 = loc_T0; + move16(); *T0_frac = loc_frac; + move16(); } } #endif @@ -356,7 +788,7 @@ Word16 pit_encode_fx( /* o : Fractional pitc *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); } - pit_Q_enc_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + pit_Q_enc_ivas_fx( hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); } ELSE /* L_frame == L_FRAME16k */ { @@ -370,7 +802,7 @@ Word16 pit_encode_fx( /* o : Fractional pitc *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); } - pit16k_Q_enc_fx( hBstr, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + pit16k_Q_enc_ivas_fx( hBstr, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); } } } @@ -470,6 +902,7 @@ Word16 pit_encode_fx( /* o : Fractional pitc return pitch_cl; } +#endif /*-------------------------------------------------------------------* * abs_pit_enc() @@ -1119,6 +1552,99 @@ void pit_Q_enc_fx( return; } +void pit_Q_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +) +{ + Word16 pitch_index; + + IF( EQ_16( nBits, 10 ) ) /* absolute encoding with 10 bits */ + { + IF( limit_flag == 0 ) + { + /* pitch_index = T0*4 + T0_frac - (PIT_MIN*4);*/ + pitch_index = sub( add( shl( T0, 2 ), T0_frac ), ( PIT_MIN * 4 ) ); + } + ELSE IF( EQ_16( limit_flag, 1 ) ) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4);*/ + pitch_index = sub( add( shl( T0, 2 ), T0_frac ), ( PIT_MIN_EXTEND * 4 ) ); + } + ELSE /* limit_flag == 2 */ + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4);*/ + pitch_index = sub( add( shl( T0, 2 ), T0_frac ), ( PIT_MIN_DOUBLEEXTEND * 4 ) ); + } + } + ELSE IF( EQ_16( nBits, 9 ) ) /* absolute encoding with 9 bits */ + { + pitch_index = abs_pit_enc_fx( 4, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16( nBits, 8 ) ) /* absolute encoding with 8 bits */ + { + pitch_index = abs_pit_enc_fx( 2, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16( nBits, 6 ) ) /* relative encoding with 6 bits */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + ELSE IF( EQ_16( nBits, 5 ) ) /* relative encoding with 5 bits */ + { + IF( EQ_16( delta, 8 ) ) + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + } + ELSE /* nBits == 4 ) */ /* relative encoding with 4 bits */ + { + IF( EQ_16( delta, 8 ) ) + { + pitch_index = delta_pit_enc_fx( 0, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + } + + IF( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0_fx( L_FRAME, delta, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + } + + { + push_indice( hBstr, IND_PITCH, pitch_index, nBits ); + } + + return; +} + /*-------------------------------------------------------------------* * pit16k_Q_enc() * @@ -1197,6 +1723,77 @@ void pit16k_Q_enc_fx( return; } +void pit16k_Q_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +) +{ + Word16 pitch_index; + + IF( EQ_16( nBits, 10 ) ) /* absolute encoding with 10 bits */ + { + { + IF( LT_16( T0, PIT16k_FR2_EXTEND_10b ) ) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add( shl( T0, 2 ), sub( T0_frac, ( PIT16k_MIN_EXTEND * 4 ) ) ); + } + ELSE + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_10b*2) + ((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add( sub( add( shl( T0, 1 ), shr( T0_frac, 1 ) ), ( PIT16k_FR2_EXTEND_10b * 2 ) ), ( ( PIT16k_FR2_EXTEND_10b - PIT16k_MIN_EXTEND ) * 4 ) ); + } + } + + push_indice( hBstr, IND_PITCH, pitch_index, nBits ); + } + ELSE IF( EQ_16( nBits, 9 ) ) /* absolute encoding with 9 bits */ + { + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT16k_EXTEND_MIN to PIT16k_FR2_EXTEND_9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_EXTEND_9b to PIT16k_FR1_EXTEND_9b-1 resolution 1/2 (frac = 0 or 2) + * PIT16k_FR1_EXTEND_9b to PIT16k_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF( LT_16( T0, PIT16k_FR2_EXTEND_9b ) ) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add( shl( T0, 2 ), sub( T0_frac, ( PIT16k_MIN_EXTEND * 4 ) ) ); + } + ELSE IF( LT_16( T0, PIT16k_FR1_EXTEND_9b ) ) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_9b*2) + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add( sub( add( shl( T0, 1 ), shr( T0_frac, 1 ) ), ( PIT16k_FR2_EXTEND_9b * 2 ) ), ( ( PIT16k_FR2_EXTEND_9b - PIT16k_MIN_EXTEND ) * 4 ) ); + } + ELSE + { + /*pitch_index = T0 - PIT16k_FR1_EXTEND_9b + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) + ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2);*/ + pitch_index = add( add( sub( T0, PIT16k_FR1_EXTEND_9b ), ( ( PIT16k_FR2_EXTEND_9b - PIT16k_MIN_EXTEND ) * 4 ) ), ( ( PIT16k_FR1_EXTEND_9b - PIT16k_FR2_EXTEND_9b ) * 2 ) ); + } + } + + push_indice( hBstr, IND_PITCH, pitch_index, 9 ); + } + ELSE /* nBits == 6 */ /* relative encoding with 6 bits */ + { + /*pitch_index = (T0 - *T0_min) * 4 + T0_frac;*/ + pitch_index = add( shl( sub( T0, *T0_min ), 2 ), T0_frac ); + + push_indice( hBstr, IND_PITCH, pitch_index, nBits ); + } + + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + + return; +} /*------------------------------------------------------------------* * pit_encode: diff --git a/lib_enc/pitch_ol2.c b/lib_enc/pitch_ol2.c index 1b55d5a7665f07155749e9b7c9a54df3d7bfc3dc..6c5ed0123b9375a0bcd37d68df9ad7fef9fe7819 100644 --- a/lib_enc/pitch_ol2.c +++ b/lib_enc/pitch_ol2.c @@ -41,6 +41,11 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#endif // IVAS_FLOAT_FIXED + /*-------------------------------------------------------------------* * Local constants *-------------------------------------------------------------------*/ @@ -164,7 +169,227 @@ void pitch_ol2( * * Very short stable pitch detection *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void StableHighPitchDetect_ivas_fx( + Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */ + Word16 pitch[], /* i/o: OL pitch buffer */ + const Word16 voicing[], /* i : OL pitch gains */ + const Word16 wsp[], /* i : weighted speech */ + const Word16 localVAD, /* i : local VAD flag */ + Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains */ + Word16 *voicing0_sm, /* i/o: smoothed high pitch gains */ + Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/ + Word16 *predecision_flag, /* i/o: predecision flag */ + Word32 *diff_sm, /* i/o: smoothed pitch frequency difference */ + Word32 *energy_sm, /* i/o: smoothed energy around pitch frequency */ + Word16 Q_new, + Word16 EspecdB[] ) +{ + Word16 i, pitch_freq_point; + Word16 T, Tp, pit_min; + Word16 energy0_16, energy1_16, ratio, voicing_m; + Word32 energy0, energy1, cor_max, diff, sum_energy; + const Word16 *pt_wsp; + Word16 tmp, tmp1, exp, diff16, cor_max16, exp1, exp2, pit_min_up; + Word32 L_tmp, L_tmp1; + Word16 Top; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /*voicing = (voicing[0] + voicing[1] + voicing[2] )/3;*/ + L_tmp = L_mult( voicing[0], 10923 ); + L_tmp = L_mac( L_tmp, voicing[1], 10923 ); + L_tmp = L_mac( L_tmp, voicing[2], 10923 ); +#ifdef BASOP_NOGLOB + voicing_m = round_fx_sat( L_tmp ); +#else + voicing_m = round_fx( L_tmp ); +#endif + /**voicing_sm = 0.75f*(*voicing_sm) + 0.25f*voicing;*/ + *voicing_sm = round_fx( L_mac( L_mult( *voicing_sm, 24576 ), voicing_m, 8192 ) ); + move16(); + + /* pitch_freq_point = (short)(L_FFT/(mult_fact*T_op[1])+0.5f);*/ + Top = pitch[1]; + move16(); + pitch_freq_point = idiv1616( L_FFT, Top ); /* Q0*/ + diff = L_deposit_l( 0 ); + sum_energy = L_deposit_l( 0 ); + FOR( i = 1; i < 2 * pitch_freq_point; i++ ) + { + diff = L_add( diff, sub( EspecdB[pitch_freq_point], EspecdB[i] ) ); + sum_energy = L_add( sum_energy, EspecdB[i] ); + } + /*sum_energy /= (2*pitch_freq_point-1);*/ + tmp = sub( shl( pitch_freq_point, 1 ), 1 ); + exp = norm_s( tmp ); + tmp1 = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*Q(29-exp)*/ + L_tmp = Mult_32_16( sum_energy, tmp1 ); + sum_energy = L_shl( L_tmp, sub( exp, 14 ) ); + /**diff_sm = 0.2f * diff + 0.8f * *diff_sm;*/ + *diff_sm = L_add( Mult_32_16( diff, 6554 ), Mult_32_16( *diff_sm, 26214 ) ); + move32(); + /**energy_sm = 0.2f * sum_energy + 0.8f * *energy_sm;*/ + *energy_sm = L_add( Mult_32_16( sum_energy, 6554 ), Mult_32_16( *energy_sm, 26214 ) ); + move32(); + /*diff /= sum_energy;*/ + + IF( sum_energy ) + { + exp = norm_l( sum_energy ); + tmp = extract_h( L_shl( sum_energy, exp ) ); + exp = sub( sub( 30, exp ), 7 ); + IF( tmp < 0 ) + { + tmp = abs_s( tmp ); + tmp = div_s( 16384, tmp ); /*Q(15+exp)*/ + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + diff = L_negate( L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow ) ); +#else /* BASOP_NOGLOB */ + diff = L_negate( L_shr( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) ) ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS +#ifdef BASOP_NOGLOB + diff16 = round_fx_o( diff, &Overflow ); +#else /* BASOP_NOGLOB */ + diff16 = round_fx( diff ); +#endif /* BASOP_NOGLOB */ + } + ELSE + { + tmp = div_s( 16384, tmp ); /*Q(15+exp)*/ + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + diff = L_shr_o( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ), &Overflow ); +#else /* BASOP_NOGLOB */ + diff = L_shr( Mult_32_16( diff, tmp ), sub( exp + 7, 31 ) ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS +#ifdef BASOP_NOGLOB + diff16 = round_fx_o( diff, &Overflow ); +#else /* BASOP_NOGLOB */ + diff16 = round_fx( diff ); +#endif /* BASOP_NOGLOB */ + } + } + ELSE + { +#ifdef BASOP_NOGLOB + diff16 = round_fx_o( L_shl_o( diff, 25, &Overflow ), &Overflow ); +#else + diff16 = round_fx( L_shl( diff, 25 ) ); +#endif + } + test(); + test(); + IF( LT_32( *diff_sm, -1280 ) && LT_32( *energy_sm, 4928 ) && LT_16( diff16, -26214 ) ) + { + *predecision_flag = 1; + move16(); + } + test(); + test(); + if ( GT_32( *diff_sm, 1280 ) && GT_32( *energy_sm, 10624 ) && GT_16( diff16, 16384 ) ) + { + *predecision_flag = 0; + move16(); + } + + /* short pitch possiblity pre-decision */ + maximum_fx( EspecdB, 7, &energy0_16 ); + maximum_fx( EspecdB + 8, 7, &energy1_16 ); + ratio = s_max( sub( energy1_16, energy0_16 ), 0 ); /*Q7 */ + /*ratio *= max(voicing,0);*/ + tmp = s_max( voicing_m, 0 ); + ratio = mult_r( ratio, tmp ); /*Q7*/ + /**LF_EnergyRatio_sm = (15*(*LF_EnergyRatio_sm) + ratio)/16;*/ + L_tmp = L_mult( ratio, 2048 ); + L_tmp = L_mac( L_tmp, *LF_EnergyRatio_sm, 30720 ); + *LF_EnergyRatio_sm = round_fx( L_tmp ); + move16(); + test(); + if ( GT_16( *LF_EnergyRatio_sm, 4480 ) || GT_16( ratio, 6400 ) ) + { + *predecision_flag = 1; + move16(); + } + + if ( LT_16( *LF_EnergyRatio_sm, 2048 ) ) + { + *predecision_flag = 0; + move16(); + } + + /* short pitch candidate detection */ + Tp = pitch[1]; + move16(); + cor_max = 0; + move16(); + pt_wsp = wsp + 3 * L_SUBFR; + pit_min = PIT_MIN_DOUBLEEXTEND; + move16(); + pit_min_up = PIT_MIN; + move16(); + FOR( T = pit_min; T <= pit_min_up; T++ ) + { + energy1 = Dot_product( pt_wsp, pt_wsp - T, L_SUBFR ); + test(); + IF( ( GT_32( energy1, cor_max ) ) || ( EQ_16( T, pit_min ) ) ) + { + cor_max = L_add( energy1, 0 ); + Tp = T; + move16(); + } + } + energy0 = Dot_product12( pt_wsp, pt_wsp, L_SUBFR, &exp1 ); + exp1 = sub( exp1, shl( Q_new, 1 ) ); + energy1 = Dot_product12( pt_wsp - Tp, pt_wsp - Tp, L_SUBFR, &exp2 ); + exp2 = sub( exp2, shl( Q_new, 1 ) ); + /* cor_max *= inv_sqrt( energy0*energy1 );*/ + L_tmp = Mult_32_32( energy0, energy1 ); + exp = norm_l( L_tmp ); + L_tmp1 = L_shl( L_tmp, exp ); + + exp = sub( sub( 31, exp ), ( sub( sub( 31, exp1 ), exp2 ) ) ); + move16(); + L_tmp1 = Isqrt_lc( L_tmp1, &exp ); /*Q(31-exp)*/ + cor_max = Mult_32_32( cor_max, L_tmp1 ); + exp = add( sub( sub( 31, add( shl( Q_new, 1 ), 1 ) ), sub( 31, exp ) ), 31 ); +#ifdef BASOP_NOGLOB + cor_max16 = round_fx_o( L_shl_o( cor_max, exp, &Overflow ), &Overflow ); /*Q15*/ +#else /* BASOP_NOGLOB */ + cor_max16 = round_fx( L_shl( cor_max, exp ) ); /*Q15*/ +#endif + /**voicing0_sm = add(mult_r(24576 ,(*voicing0_sm)) , mult_r(8192 , cor_max16));*/ + *voicing0_sm = round_fx( L_mac( L_mult( 24576, *voicing0_sm ), 8192, cor_max16 ) ); + move16(); + + /* final short pitch detection */ + test(); + test(); + test(); + *flag_spitch = 0; + move16(); + IF( ( EQ_16( localVAD, 1 ) ) && ( EQ_16( *predecision_flag, 1 ) ) && + ( GT_16( *voicing0_sm, 16384 ) ) && ( GT_16( *voicing0_sm, mult_r( *voicing_sm, 21299 ) ) ) ) + { + *flag_spitch = 1; + move16(); + pitch[0] = Tp; + move16(); + pitch[1] = Tp; + move16(); + pitch[2] = Tp; + move16(); + } + + return; +} +#endif void StableHighPitchDetect( int16_t *flag_spitch, /* o : flag to indicate very short stable pitch*/ int16_t pitch[], /* i/o: OL pitch buffer */ diff --git a/lib_enc/pre_proc.c b/lib_enc/pre_proc.c index 065fb2a45df2040d79d80bcc9d495987732278c8..f9210f67550def169bb85b428e570058feb13563 100644 --- a/lib_enc/pre_proc.c +++ b/lib_enc/pre_proc.c @@ -42,7 +42,13 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#include "prot_fx_enc.h" +#endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * pre_proc() * @@ -74,6 +80,10 @@ void pre_proc( { int16_t delay; const float *signal_in; + +#ifdef IVAS_FLOAT_FIXED + const Word16 *signal_in_fx; +#endif float *inp_12k8, *new_inp_12k8, *inp_16k, *new_inp_16k; /* pointers to current frame and new data */ float old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ float pitch_fr[NB_SUBFR]; /* fractional pitch values */ @@ -121,6 +131,10 @@ void pre_proc( signal_in = st->input; +#ifdef IVAS_FLOAT_FIXED + signal_in_fx = st->input_fx; +#endif + localVAD_HE_SAD = 0; NB_speech_HO = 0; clean_speech_HO = 0; @@ -239,8 +253,52 @@ void pre_proc( /*----------------------------------------------------------------* * FD-CNG Noise Estimator *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->last_totalNoise_fx = float_to_fix16( st->last_totalNoise, Q8 ); + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, Q8 ); + + FOR( Word16 n = 0; n < TOTALNOISE_HIST_SIZE; n++ ) + { + st->totalNoise_increase_hist_fx[n] = float_to_fix16( st->totalNoise_increase_hist[n], Q8 ); + move16(); + } +#endif + resetFdCngEnc_fx( st ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 totalNoiseIncrease_fx = st->hNoiseEst->totalNoise_fx - st->last_totalNoise_fx; + st->last_totalNoise = fix16_to_float( st->last_totalNoise_fx, Q8 ); + IF( + ( totalNoiseIncrease_fx > 5 * 256 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) || + ( st->input_bwidth > st->last_input_bwidth ) || + ( st->last_core == AMR_WB_CORE ) ) + { + st->hFdCngEnc->hFdCngCom->init_old_flt = fix16_to_float( st->hFdCngEnc->hFdCngCom->init_old, Q15 ); + move16(); + } + IF( totalNoiseIncrease_fx > 0 ) + { + IF( EQ_16( st->totalNoise_increase_len, TOTALNOISE_HIST_SIZE ) ) + { + FOR( Word16 n = 0; n < TOTALNOISE_HIST_SIZE; n++ ) + { + st->totalNoise_increase_hist[n] = fix16_to_float( st->totalNoise_increase_hist_fx[n + 1], Q8 ); + move16(); + } + } + ELSE + { + st->totalNoise_increase_hist[st->totalNoise_increase_len] = fix16_to_float( st->totalNoise_increase_hist_fx[st->totalNoise_increase_len], Q8 ); + move16(); + } + } +#endif +#else resetFdCngEnc( st ); +#endif perform_noise_estimation_enc( band_energies, enerBuffer, st->hFdCngEnc, 1, NULL ); @@ -956,3 +1014,4 @@ void pre_proc( pop_wmops(); return; } +#endif diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index c406c4389f9992d2de2ced560f804710718fcad6..1e7315e652ed0afc634ae46d091570a12b78f934 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -166,13 +166,29 @@ Word16 dtx_hangover_addition_fx( VAD_HANDLE hVAD, /* i/o: VAD data handle */ NOISE_EST_HANDLE hNoiseEst /* i : Noise estimation handle */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_dtx_hangover_addition_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 number of DTX-HO frames CLDFB wants to reduce */ + Word16 *vad_hover_flag_ptr, + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + Word16 *rem_dtx_ho ); +#endif void fb_tbe_enc_fx( Encoder_State *st, /* i/o: encoder state structure */ const Word16 new_input[], /* i : i speech at 48 kHz sample rate */ const Word16 fb_exc[], /* i : FB excitation from the SWB part */ Word16 Q_fb_exc ); +void fb_tbe_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : i speech at 48 kHz sample rate Q0*/ + const Word16 fb_exc[], /* i : FB excitation from the SWB part Q_fb_exc*/ + Word16 Q_fb_exc ); + void fb_tbe_reset_enc_fx( Word32 elliptic_bpf_2_48k_mem_fx[][4], Word32 *prev_fb_energy_fx, @@ -183,6 +199,23 @@ Word16 ffr_getSfWord32( const Word32 *vector, /*!< Pointer to i vector */ const Word16 len /*!< Length of i vector */ ); +#ifdef IVAS_FLOAT_FIXED +void find_tilt_ivas_fx( + const Word32 fr_bands[], /* i : energy in frequency bands Q_new*/ + const Word32 bckr[], /* i : per band background noise energy estimate Q_new*/ + Word32 ee[2], /* o : lf/hf E ration for present frame Q6*/ + const Word16 pitch[3], /* i : open loop pitch values for 3 half-frames Q0*/ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames Q15*/ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new - 2*/ + const Word16 corr_shift, /* i : normalized correlation correction Q15*/ + const Word16 bwidth, /* i : i signal bandwidth */ + const Word16 max_band, /* i : maximum critical band */ + Word32 hp_E[], /* o : energy in HF Q_new*/ + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + const Word16 Q_new, /* i : scaling factor */ + Word32 *bckr_tilt_lt, + Word16 Opt_vbr_mode ); +#endif // IVAS_FLOAT_FIXED void find_tilt_fx( const Word32 fr_bands[], /* i : energy in frequency bands Q_new + Q_SCALE*/ @@ -200,6 +233,24 @@ void find_tilt_fx( Word32 *bckr_tilt_lt, Word16 Opt_vbr_mode ); +#ifdef IVAS_FLOAT_FIXED +Word16 find_uv_ivas_fx( /* o : coding type */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *T_op_fr, /* i : pointer to adjusted fractional pitch (4 val.) Q6 */ + const Word16 *voicing_fr, /* i : refined correlation for each subframes Q15 */ + const Word16 *speech, /* i : pointer to speech signal for E computation Q_new */ + const Word32 *ee, /* i : lf/hf Energy ratio for present frame Q6 */ + Word32 *dE1X, /* o : sudden energy increase for S/M classifier */ + const Word16 corr_shift, /* i : normalized correlation correction in noise Q15 */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 Etot, /* i : total energy Q8 */ + const Word32 hp_E[], /* i : energy in HF Q_new */ + Word16 *flag_spitch, /* i/o: flag to indicate very short stable pitch and high correlation */ + const Word16 last_core_orig, /* i : original last core */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 Q_new, + const Word16 q_hp_E ); +#endif // IVAS_FLOAT_FIXED Word16 find_uv_fx( /* o : coding type */ Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *T_op_fr, /* i : pointer to adjusted fractional pitch (4 val.) Q6*/ @@ -328,6 +379,7 @@ void noise_est_ivas_fx( const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ Word16 *cor_map_sum, /* o : Q8 */ + Word16 *ncharX, /* o : Q11 */ Word16 *sp_div, /* o : Q_sp_div */ Word16 *Q_sp_div, /* o : Q factor for sp_div */ Word16 *non_staX, /* o : non-stationarity for sp/mus classifier */ @@ -517,6 +569,24 @@ void StableHighPitchDetect_fx( Word16 Q_new, Word16 EspecdB[] ); +#ifdef IVAS_FLOAT_FIXED +void StableHighPitchDetect_ivas_fx( + Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */ + Word16 pitch[], /* i/o: OL pitch buffer Q0 */ + const Word16 voicing[], /* i : OL pitch gains Q15 */ + const Word16 wsp[], /* i : weighted speech Qx */ + const Word16 localVAD, + Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains Q15 */ + Word16 *voicing0_sm, /* i/o: smoothed high pitch gains Q15 */ + Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy Q7 */ + Word16 *predecision_flag, /* i/o: predecision flag */ + Word32 *diff_sm, /* i/o: smoothed pitch frequency difference Q7 */ + Word32 *energy_sm, /* i/o: smoothed energy around pitch frequency Q7 */ + Word16 Q_new, + Word16 EspecdB[] /* Q7 */ +); +#endif + void swb_bwe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word16 *old_input_12k8_fx, /* i : i signal @12.8kHz for SWB BWE */ @@ -528,12 +598,29 @@ void swb_bwe_enc_fx( Word16 Q_shb_speech, Word16 Q_slb_speech ); +void swb_bwe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const int16_t last_element_mode, /* i : last element mode */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + Word16 Q_shb_speech, + Word16 Q_slb_speech ); + void swb_CNG_enc_fx( Encoder_State *st_fx, /* i/o: State structure */ const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz */ ); +void swb_CNG_enc_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q0 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz Q0 */ +); + void swb_pre_proc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *input_fx, /* i : original i signal */ @@ -548,6 +635,11 @@ void swb_pre_proc_fx( const CLDFB_SCALE_FACTOR *cldfbScale /* i : scale data of real and imag CLDFB buffers */ ); +void InitSWBencBufferStates_fx( + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + Word16 *shb_speech /* o : SHB target signal (6-14kHz) at 16kHz */ +); + void swb_tbe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 coder_type, /* i : coding type */ @@ -562,6 +654,20 @@ void swb_tbe_enc_fx( const Word16 pitch_buf[] /* i : pitch for each subframe */ ); +void swb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: IC-BWE state structure */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb */ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2 * Q_new */ + const Word16 voice_factors_fx[], /* i : voicing factors Q15 */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc */ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6 */ +); + void tbe_write_bitstream_fx( Encoder_State *st_fx /* i/o: encoder state structure */ ); @@ -597,18 +703,31 @@ void vad_param_updt_fx( FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ const Word16 n_channels /* i : number of channels */ ); + void wb_bwe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *new_wb_speech_fx, /* i : original i signal at 16kHz */ Word16 coder_type /* i : coding type */ ); +void wb_bwe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *new_wb_speech_fx /* i : original i signal at 16kHz */ +); + void wb_pre_proc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *new_inp_resamp16k, /* i : original i signal */ Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz */ ); +void wb_pre_proc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 last_element_mode, /* i : last element mode */ + const Word16 *new_inp_resamp16k, /* i : original input signal in Q-1 */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz in Q-1 */ +); + void wb_tbe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 coder_type, /* i : coding type */ @@ -620,6 +739,16 @@ void wb_tbe_enc_fx( const Word16 voicing[] /* i : OL maximum normalized correlation */ ); +void wb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz Q(-1) */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation Q(2*Q_new) */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors Q15 */ + const Word16 pitch_buf[] /* i : pitch for each subframe Q6 */ +); + + Word16 wb_vad_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word32 fr_bands[], /* i : per band i energy (contains 2 vectors) Q_new+QSCALE*/ @@ -824,6 +953,16 @@ void pit16k_Q_enc_fx( Word16 *T0_max /* o : delta search max */ ); +void pit16k_Q_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +); + Word16 pitch_fr4_fx( /* o : chosen integer pitch lag */ const Word16 exc[], /* i : excitation buffer Q_new*/ const Word16 xn[], /* i : target signal Q_new-1+shift*/ @@ -851,6 +990,19 @@ void pit_Q_enc_fx( Word16 *T0_max /* o : delta search max */ ); +void pit_Q_enc_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +); + void PsychAdaptLowFreqEmph_fx( Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[] ); @@ -869,6 +1021,13 @@ Word16 WB_BWE_encoding_fx( /* o : classification of wb Word16 Q_synth, Word16 Q_synth_lf ); +Word16 WB_BWE_encoding_ivas_fx( /* o : classification of wb signal */ + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Word16 Q_synth, + Word16 Q_synth_lf ); + void calculate_hangover_attenuation_gain_fx( Encoder_State *st, /* i : encoder state structure */ Word16 *att, /* o : attenuation factor */ @@ -901,6 +1060,13 @@ void InitTransientDetection_ivas_fx( Word16 nFrameLength, */ void RunTransientDetection_fx( Word16 const *i, Word16 nSamplesAvailable, struct TransientDetection *pTransientDetection ); + +void RunTransientDetection_ivas_fx( + const Word16 *input_fx, /* i : input signal Q: -1 */ + const int16_t length, /* i : frame length */ + TRAN_DET_HANDLE hTranDet /* i/o: transient detection handle */ +); + /** Get the average temporal flatness measure using subblock energies aligned with the TCX. * @param pTransientDetection Structure that contains transient detectors to be run. * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. @@ -909,6 +1075,7 @@ void RunTransientDetection_fx( Word16 const *i, Word16 nSamplesAvailable, struct * @return average temporal flatness measure with exponent AVG_FLAT_E */ Word16 GetTCXAvgTemporalFlatnessMeasure_fx( struct TransientDetection const *pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ); +Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ); /** Get the maximum energy change using subblock energies aligned with the TCX. * @param pTransientDetection Structure that contains transient detectors to be run. @@ -982,6 +1149,10 @@ void speech_music_clas_init_fx( SP_MUS_CLAS_HANDLE hSpMusClas /* i/o: speech/music classifier handle */ ); +void speech_music_clas_init_ivas_fx( + SP_MUS_CLAS_HANDLE hSpMusClas /* i/o: speech/music classifier handle */ +); + void pitchDoubling_det_fx( Word16 *wspeech, Word16 *pitch_ol, @@ -1001,6 +1172,22 @@ void AVQ_cod_lpc_fx( Word16 *indx, /* o : index[] (4 bits per words) */ Word16 Nsv /* i : number of subvectors (lg=Nsv*8) */ ); + +#ifdef IVAS_FLOAT_FIXED +void ProcessIGF_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + Word32 *pMDCTSpectrum, /* i : MDCT spectrum */ + const Word32 *pITFMDCTSpectrum, /* i : MDCT spectrum fir ITF */ + Word16 *q_spectrum, /* i/o: Q of spectrum */ + Word32 *pPowerSpectrum, /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 *q_powerSpec, /* i/o: Q of power spectrum */ + const Word16 isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const Word16 frameno, /* i : flag indicating index of current subframe */ + const Word16 sp_aud_decision0, /* i : first stage switching decision */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); +#endif + void ProcessIGF_fx( IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ Encoder_State *st, /**< in: Encoder state */ @@ -1040,6 +1227,13 @@ Word16 SQ_gain_fx( /* o : SQ gain */ Word16 lg, /* i : vector size (2048 max) */ Word16 *gain_e ); /* o : SQ gain exponent */ +Word16 SQ_gain_estimate_fx( /* o : SQ gain */ + Word32 x[], /* i : vector to quantize */ + Word16 x_e, /* i : exponent */ + Word16 nbitsSQ, /* i : number of bits targeted */ + Word16 lg, /* i : vector size (2048 max) */ + Word16 *gain_e ); /* o : SQ gain exponent */ + void tcx_scalar_quantization_fx( Word32 *x, /* i: i coefficients */ Word16 x_e, /* i: exponent */ @@ -1070,6 +1264,28 @@ Word16 tcx_scalar_quantization_rateloop_fx( const Word8 tcxonly, CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ ); + +Word16 tcx_scalar_quantization_rateloop_ivas_fx( + Word32 *x, /* i : input coefficients Q = 31 - x_e*/ + Word16 x_e, /* i : exponent Q0*/ + Word16 *xq, /* o : quantized coefficients Q0*/ + Word16 L_frame, /* i : frame length Q0*/ + Word16 *gain, /* i/o: quantization gain Q = gaine_e*/ + Word16 *gain_e, /* i/o: gain exponent Q0*/ + Word16 offset, /* i : rounding offset (deadzone) Q0*/ + Word8 const *memQuantZeros_fx, /* i : coefficients to be set to 0 Q0*/ + Word16 *lastnz_out, /* i/o: last nonzero coeff index Q0*/ + Word16 target, /* i : target number of bits Q0*/ + Word16 *nEncoded, /* o : number of encoded coeff Q0*/ + Word16 *stop, /* i/o: stop param Q0*/ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) Q0*/ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) Q0*/ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word16 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg, /* i : configuration of the context-based harmonic model */ + const Word16 iter_max, + const Word16 element_mode ); + void tcx_noise_factor_fx( Word32 *x_orig, /* i: unquantized mdct coefficients */ Word16 x_orig_e, /* i: exponent */ @@ -1101,6 +1317,18 @@ void tcx_noise_factor_ivas_fx( Word16 element_mode /* i: element mode */ ); +void tcx_encoder_memory_update_ivas_fx( + Word16 *wsig, /* i : target weighted signal, Q_new */ + Word16 *xn_buf, /* i/o: mdct output buffer/time domain weigthed synthesis, Q_new */ + Word16 L_frame_glob, /* i: global frame length */ + const Word16 *Ai, /* i: Unquantized (interpolated) LPC coefficients, Q12 */ + const Word16 *A, /* i: Quantized LPC coefficients, Q = 14 - norm_s(A[0]) */ + Word16 preemph, /* i: preemphasis factor, Q15 */ + LPD_state *LPDmem, /* i/o: coder memory state */ + Encoder_State *st, + Word16 *synthout, /* Q_new */ + Word16 Q_new ); + void tcx_encoder_memory_update_fx( Word16 *wsig, /* i: targert weighted signal */ Word16 *xn_buf, /* i/o: mdct output buffer/TD weigthed synthesis */ @@ -1129,6 +1357,22 @@ Word16 tcx_ari_res_Q_spec_fx( const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ ); +Word16 tcx_ari_res_Q_spec_ivas_fx( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +); + Word16 tcx_res_Q_gain_fx( Word16 sqGain, Word16 sqGain_e, @@ -1151,6 +1395,20 @@ Word16 tcx_res_Q_spec_fx( Word16 sq_round, const Word16 lf_deemph_factors[] ); +Word16 tcx_res_Q_spec_ivas_fx( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] ); + /* compute noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ void ComputeSpectrumNoiseMeasure_fx( const Word32 *powerSpec, Word16 L_frame, @@ -1176,6 +1434,21 @@ void lpc_quantization_fx( Word16 *no_param_lpc, const Word16 Q_ener ); +void lpc_quantization_ivas_fx( + Encoder_State *st, + const Word16 lsp[], /* Q15 */ + const Word16 lspmid[], /* Q15 */ + Word16 lsp_q[], /* Q15 */ + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], /* Q15 */ + const Word16 coder_type, + const Word16 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 *bits_param_lpc, + Word16 *no_param_lpc, + const Word16 Q_ener ); + void Mode2_pit_encode_fx( const Word16 coder_type, /* i : coding model */ const Word16 i_subfr, /* i : subframe index */ @@ -1238,6 +1511,13 @@ void E_ACELP_innovative_codebook_fx( const Word32 total_brate /* i : ttoal bit-rate */ ); +void CalculateTnsFilt_fx( + STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + const Word32 pSpectrum[], /* i : MDCT spectrum Qx*/ + STnsData *pTnsData, /* o : TNS data struct */ + Word16 *predictionGain /* o : TNS prediction gain Q7*/ +); + /** Detect TNS parameters. * Detects if TNS should be used and fills TNS data in pTnsData. * @param pTnsConfig TNS configuration. @@ -1398,6 +1678,21 @@ void CNG_enc_fx( Word32 *q_env, Word16 *sid_bw ); +#ifdef IVAS_FLOAT_FIXED +void CNG_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: State structure */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word16 *speech, /* i : pointer to current frame i speech buffer Q_new */ + // Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */ + const Word16 *lsp_mid, /* i : mid frame LSPs Q15 */ + Word16 *lsp_new, /* i/o: current frame ISPs Q15 */ + Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */ + Word16 *allow_cn_step, /* o : allow CN step Q0 */ + Word16 Q_new, /* i : Q value of speech */ + Word32 *q_env, + Word16 *sid_bw ); +#endif + /* Generate a bitstream out of the partition levels */ void FdCng_encodeSID_fx( HANDLE_FD_CNG_ENC st, /* i/o: FD_CNG structure containing all buffers and variables */ Encoder_State *corest, @@ -1480,6 +1775,22 @@ void encod_nelp_fx( ); +void encod_nelp_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 *speech_fx, /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *res_fx, /* o : residual signal */ + Word16 *synth_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift ); + Word16 encod_tran_fx( Encoder_State *st_fx, /* i/o: state structure */ const Word16 speech_fx[], /* i : i speech */ @@ -1537,13 +1848,14 @@ void perform_noise_estimation_enc_fx( Word16 enerBuffer_exp, HANDLE_FD_CNG_ENC st ); /* i/o: FD_CNG structure containing all buffers and variables */ -void perform_noise_estimation_enc_ivas_fx( Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ - Word16 band_energies_exp, /* i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */ - Word32 *enerBuffer, - Word16 enerBuffer_exp, - HANDLE_FD_CNG_ENC st, /* i/o: FD_CNG structure containing all buffers and variables */ - const int32_t input_Fs, /* i : input sampling rate */ - CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ +void perform_noise_estimation_enc_ivas_fx( + Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp, + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate */ + CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ ); /* Adjust the noise estimator at the beginning of each CNG phase (encoder-side) */ @@ -1652,6 +1964,16 @@ void stat_noise_uv_enc_fx( const Word16 uc_two_stage_flag, /* o : flag undicating two-stage UC */ Word16 Q_new ); +void stat_noise_uv_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word32 *LepsP, /* i : LP prediction errors Q=Qx*/ + const Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr Q=15*/ + const Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr Q=15*/ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes Q=12 */ + Word16 *exc2, /* i/o: excitation buffer Q=Q_stat_noise */ + const Word16 uc_two_stage_flag, /* o : flag undicating two-stage UC */ + Word16 Q_new ); + void analy_sp_fx( const Word16 element_mode, /* i : element mode */ #ifdef IVAS_CODE_CPE @@ -1674,7 +1996,28 @@ void analy_sp_fx( Word32 *band_energies, /* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN */ Word16 *fft_buff /* o : FFT coefficients */ ); - +#ifdef IVAS_FLOAT_FIXED +void ivas_analy_sp_fx( + const Word16 element_mode, /* i : element mode */ + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word32 input_Fs, /* i : input sampling rate */ + Word16 *speech, /* i : speech buffer Q_new - preemph_bits */ + const Word16 Q_new, /* i : current scaling exp Q0 */ + Word32 *fr_bands, /* o : energy in critical frequency bands Q_new + QSCALE */ + Word32 *lf_E, /* o : per bin E for first... Q_new + QSCALE - 2*/ + Word16 *Etot, /* o : total input energy Q8 */ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word32 e_min_scaled, /* i : minimum energy scaled Q_new + QSCALE */ + Word16 Scale_fac[2], /* o : FFT scales factors (2 values by frame) Q0 */ + Word32 *Bin_E, /* o : per-bin energy spectrum Q7 */ + Word32 *Bin_E_old, /* o : per-bin energy spectrum of the previous frame Q7 */ + Word32 *PS, /* o : per-bin energy spectrum Q_new + QSCALE */ + Word16 *EspecdB, /* o : per-bin log energy spectrum (with f=0) Q7 */ + Word32 *band_energies, /* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN (Q_new + QSCALE + 2)*/ + Word16 *fft_buff /* o : FFT coefficients (Q_new + QSCALE + 2) */ +); +#endif void find_wsp_fx( const Word16 Az[], const Word16 speech[], @@ -1729,6 +2072,20 @@ void find_targets_fx( , Word16 *h1 /* Q14 ?*/ ); +void find_targets_ivas_fx( + const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/ + const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/ + const Word16 i_subfr, /* i : subframe index */ + Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/ + const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/ + const Word16 *res, /* i : residual signal Q_new*/ + const Word16 L_subfr, /* i : length of vectors for gain quantization */ + const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/ + Word16 tilt_fac, /* i : tilt factor Q15 */ + Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/ + Word16 *cn, /* o : target vector in residual domain Q_new*/ + Word16 *h1 /* o : impulse response of weighted synthesis filter */ +); void E_ACELP_adaptive_codebook( Word16 *exc, /* i : pointer to the excitation frame */ @@ -1835,6 +2192,27 @@ void core_signal_analysis_high_bitrate_fx( Word16 *spectrum_e, Word16 *Q_new ); +#ifdef IVAS_FLOAT_FIXED +void core_signal_analysis_high_bitrate_ivas_fx( + const Word16 *new_samples, /*i: Q0 */ + const Word16 T_op[3], /* i : open-loop pitch values for quantiz. */ + Word16 lsp_new[], /* Q15 */ + Word16 lsp_mid[], /* Q15 */ + Encoder_State *st, + Word16 pTnsSize[], + Word16 pTnsBits[], + Word16 param_core[], + Word16 *ltpBits, + Word32 *windowed_samples, + const Word16 L_frame, + const Word16 L_frameTCX, + const Word16 last_element_mode, + const Word16 vad_hover_flag, /* i : VAD hangover flag */ + Word32 **spectrum, + Word16 *spectrum_e, + Word16 *Q_new ); +#endif + void ShapeSpectrum_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 A[], /* i : quantized coefficients NxAz_q[M+1] */ @@ -1846,6 +2224,20 @@ void ShapeSpectrum_fx( Word8 pfUseTns, /* o : Flag indicating if TNS is used */ Encoder_State *st ); +void ShapeSpectrum_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1], Q = 14 - norm(A[0]) */ + Word16 gainlpc[], /* output: MDCT gains for the previous frame */ + Word16 gainlpc_e[], /* output: MDCT gains exponents */ + Word16 L_frame_glob, /* input: frame length */ + Word16 L_spec, + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + Word8 pfUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State *st, + Word32 *scf /* Q16 */ +); + void QuantizeSpectrum_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 A[], /* i : quantized coefficients NxAz_q[M+1] */ @@ -1868,6 +2260,35 @@ void QuantizeSpectrum_fx( Encoder_State *st, CONTEXT_HM_CONFIG *hm_cfg ); +void QuantizeTCXSpectrum_fx( + Encoder_State *st, /* i : state handle */ + const Word16 frame_cnt, /* i : frame counter in the super_frame Q0 */ + Word32 *x_orig_fx, /* i : shaped MDCT spectrum */ + const Word16 x_orig_e, /* i : exp of shaped MDCT spectrum */ + Word16 *gainlpc_fx, /* i : FDNS gains */ + Word16 *gainlpc_e, /* i : exp of FDNS gains */ + const Word16 *Aqind, /* i : frame-independent quantized coefficients (M+1) Q0 */ + const Word16 tnsSize, /* i : number of tns parameters put into prm Q0 */ + const Word16 nb_bits, /* i : bit budget Q0 */ + const Word16 vad_hover_flag, /* i : VAD hangover flag Q0 */ + Word16 *pL_frameTCX, /* o : full frame length Q0 */ + Word16 *pL_frame, /* o : frame length Q0 */ + Word16 *pL_spec, /* o : length of the coded spectrum Q0 */ + Word16 *ptcx_offset, /* o : folding point offset relative to the end of the previous frame Q0 */ + Word16 *pnoiseFillingBorder, /* o : noise filling border Q0 */ + Word32 spectrum_fx[], /* o : quantized MDCT spectrum */ + Word16 *spectrum_e, /* o : exp of quantized MDCT spectrum */ + CONTEXT_HM_CONFIG *hm_cfg, /* o : Context-based harmonic model configuration */ + Word16 *hm_active, /* o : flag indicating if the harmonic model is active */ + Word16 lf_deemph_fact_fx[], /* o : low frequency deemphasis factors Q14*/ + Word16 *nf_seed, /* o : noise filling random seed Q0*/ + Word32 *ener_fx, /* o : energy of the quantized spectrum */ + Word16 *ener_e, /* o : exp of energy of the quantized spectrum */ + Word16 *gain_tcx_fx, /* o : global gain */ + Word16 *gain_tcx_e, /* o : exp of global gain */ + Word16 prm[] /* o : tcx parameters Q0 */ +); + void coder_tcx_post_fx( Encoder_State *st, LPD_state *LPDmem, @@ -1879,6 +2300,16 @@ void coder_tcx_post_fx( Word16 Q_new, Word16 shift ); +void coder_tcx_post_ivas_fx( + Encoder_State *st, + LPD_state *LPDmem, + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 *synth, + const Word16 *A, + const Word16 *Ai, + Word16 *wsig, + Word16 Q_new ); + void enc_prm_fx( const Word16 coder_type, /* (i) : coding type */ Word16 param[], /* (i) : parameters */ @@ -2032,6 +2463,20 @@ void tcx_ltp_encode_fx( Word16 tcxltp_on, Word16 *A, Word16 lpcorder ); +void tcx_ltp_encode_ivas_fx( + Encoder_State *st, + const Word16 tcxMode, + const Word16 L_frame, + Word16 *speech_fx, + Word16 *speech_ltp_fx, + const Word16 *wsp_fx, + const Word16 Top[], + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *A_fx, + const Word16 disable_ltp, + const Word16 element_mode ); + void init_coder_ace_plus_fx( Encoder_State *st, const Word32 last_total_brate, /* i : last total bitrate */ @@ -2043,7 +2488,9 @@ void enc_prm_rf_fx( Encoder_State *st, const Word16 rf_frame_type, const Word16 fec_offset ); - +void enc_prm_rf_ivas_fx( Encoder_State *st, + const Word16 rf_frame_type, + const Word16 fec_offset ); void E_ACELP_pulsesign( const Word16 cn[], Word16 dn[], Word16 dn2[], Word16 sign[], Word16 vec[], const Word16 alp, Word16 const sign_val, const Word16 L_subfr ); void E_ACELP_findcandidates( Word16 dn2[], Word16 dn2_pos[], Word16 pos_max[] ); @@ -2207,7 +2654,9 @@ Word16 IGFEncWriteConcatenatedBitstream_ivas_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ ); - +void signaling_enc_rf_fx( + Encoder_State *st /* i : encoder state structure */ +); void signalling_enc_rf( Encoder_State *st /* i : encoder state structure */ ); @@ -2262,6 +2711,13 @@ void corr_xh_fx( const Word16 h[] /* i : impulse response (of weighted synthesis filter) */ ); +void corr_xh_ivas_fx( + const Word16 *x, /* i : target signal Q_new - 1 */ + Word16 *y, /* o : correlation between x[] and h[] Q_new + 1 */ + const Word16 *h, /* i : impulse response (of weighted synthesis filter) e(norm_s(h1[0])+1) */ + const Word16 L_subfr /* i : length of the subframe */ +); + void qlpc_avq_fx( const Word16 *lsf, /* i : Input LSF vectors (14Q1*1.28) */ const Word16 *lsfmid, /* i : Input LSF vectors (14Q1*1.28) */ @@ -2315,6 +2771,27 @@ void IGFEncApplyMono_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | Word16 last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ ); +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyMono_ivas_fx( Encoder_State *st, /* i : Encoder state */ + const int16_t igfGridIdx, /* i : IGF grid index */ + Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ + Word16 e_mdct, /* i : exponent of pMDCTspectrum */ + Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exponent of pPowerSpectrum */ + const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int16_t sp_aud_decision0, /* i : first stage switching decision */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +); +#endif + +#ifdef IVAS_FLOAT_FIXED +void IGFEncConcatenateBitstream_ivas_fx( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + const Word16 bsBits, /* i : number of IGF bits written to list of indices */ + BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ +); +#endif + void IGFEncConcatenateBitstream_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ Word16 bsBits, /**< in: Q0 | number of IGF bits written to list of indices */ Word16 *next_ind, /**< in/out: | pointer to actual bit indice */ @@ -2635,6 +3112,28 @@ Word16 pit_encode_fx( /* o : Fractional pitc const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ ); +Word16 pit_encode_ivas_fx( /* o : Fractional pitch for each subframe */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 pitch_bits[], /* i : pitch bits */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *pitch, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ +); + Word16 lp_filt_exc_enc_fx( const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ const Word16 coder_type, /* i : coding type Q0 */ @@ -2652,6 +3151,23 @@ Word16 lp_filt_exc_enc_fx( Word16 *lp_flag /* i/o: mode selection Q0 */ ); +Word16 lp_filt_exc_enc_ivas_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter i response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +); + Word16 inov_encode_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word32 core_brate, /* i : core bitrate */ @@ -2677,6 +3193,32 @@ Word16 inov_encode_fx( const Word16 L_subfr, /* i : subframe length */ Word16 shift ); +Word16 inov_encode_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16 *cn, /* i/o: target vector in residual domain Q_new*/ + const Word16 *exc, /* i : pointer to excitation signal frame Q_new*/ + Word16 *h2, /* i/o: weighted filter input response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16 *xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16 *code, /* o : algebraic excitation Q9*/ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16 *unbits, /* o : number of unused bits for PI */ + const Word16 L_subfr, /* i : subframe length */ + Word16 shift, + Word16 Q_new ); + void gain_enc_mless_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 gains_mode[], /* i : gain bits */ @@ -2697,6 +3239,27 @@ void gain_enc_mless_fx( Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 */ const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ ); + +void gain_enc_mless_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 element_mode, /* i : element mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *xn, /* i : target vector */ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation */ + const Word16 Q_xn, /* i : xn and y1 scaling */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word16 Es_pred, /* i : predicted scaled innovation energy */ + Word16 *gain_pit, /* o : quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); void updt_IO_switch_enc_fx( Encoder_State *st, /* i/o: state structure */ const Word16 input_frame /* i : i frame length */ @@ -2759,6 +3322,14 @@ void acelp_core_switch_enc_fx( Word16 shift, Word16 Q_new ); +void acelp_core_switch_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 inp12k8[], /* i : i signal @12.8 kHz Q0 */ + const Word16 inp16k[], /* i : i signal @16 kHz Q0 */ + const Word16 A[NB_SUBFR16k * ( M + 1 )], /* i : A(z) unquantized for the 4 subframes Q12*/ + Word16 shift, + Word16 Q_new ); + void gain_enc_amr_wb_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 *xn, /* i : target vector */ @@ -2840,6 +3411,27 @@ void gain_enc_lbr_fx( const Word16 L_subfr /* i : subframe length */ ); +void gain_enc_lbr_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *xn, /* i : target vector Q_xn*/ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn*/ + const Word16 Q_xn, /* i : xn and y1 format */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9*/ + const Word16 *code, /* i : algebraic excitation Q9*/ + Word16 *gain_pit, /* o : quantized pitch gain Q14*/ + Word32 *gain_code, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + const int16_t L_subfr /* i : subframe length */ +); + void gain_enc_SQ_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 gains_mode[], /* i : gain bits */ @@ -3113,15 +3705,6 @@ void hq_lr_enc_fx( const Word16 is_transient_fx /* i : Q0 : transient flag */ ); -void hq_hr_enc_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - Word32 *t_audio, /* i/o: transform-domain coefficients Q12*/ - const Word16 length, /* i : length of spectrum */ - Word16 *num_bits, /* i/o: number of available bits */ - const Word16 is_transient, /* i : transient flag */ - const Word16 vad_hover_flag /* i : VAD hangover flag */ -); - void hq_lr_enc_ivas_fx( Encoder_State *st_fx, /* i/o: : encoder state structure */ Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ @@ -3380,6 +3963,10 @@ void noise_est_init_fx( NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ ); +void noise_est_init_ivas_fx( + NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ +); + void InitSWBencBuffer_fx( Encoder_State *st_fx /* i/o: SHB encoder structure */ ); @@ -3505,7 +4092,22 @@ Word16 multi_harm_fx( /* o : frame multi-harmonicity Word16 *sp_floor, /* o: noise floor estimate Q7 */ Word16 S_map[] /* o : short-term correlation map Q7 */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 multi_harm_ivas_fx( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const Word16 Bin_E[], /* i : log-energy spectrum of the current frame Q7 */ + Word16 old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor Q7 */ + Word16 cor_map_LT[], /* i/o: LT correlation map Q15 */ + Word16 *multi_harm_limit, /* i/o: multi harminic threshold Q9 */ + const Word32 total_brate, /* i : total bitrate Q0 */ + const Word16 bwidth, /* i : input signal bandwidth Q0 */ + Word16 *cor_strong_limit, /* i/o: HF correlation indicator Q0 */ + Word16 *st_mean_avr_dyn, /* i/o: long term average dynamic Q7 */ + Word16 *st_last_sw_dyn, /* i/o: last dynamic Q7 */ + Word16 *cor_map_sum, /* i : sum of correlation map Q8 */ + Word16 *sp_floor, /* o: noise floor estimate Q7 */ + Word16 S_map[] /* o : short-term correlation map Q7 */ +); +#endif void pvq_encode_frame_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 *coefs_norm, /* i : normalized coefficients to encode */ @@ -3738,4 +4340,33 @@ void writeLPCparam_fx( const Word16 no_param_lpc, /* i : number of LPC parameters */ Word16 *nbits_lpc /* o : LPC bits written */ ); + +Word16 cng_energy_ivas_fx( + const Word16 element_mode, /* i : element mode */ + const Word16 bwidth, /* i : audio bandwidh */ + const Word16 CNG_mode, /* i : mode for DTX configuration */ + const Word16 CNG_att, /* i : attenuation factor for CNG Q7 */ + const Word16 *exc, /* i : input signal */ + const Word16 len, /* i : vector length */ + const Word16 Q_new /* i : Input scaling */ +); + +void generate_comfort_noise_enc_ivas_fx( Encoder_State *stcod, + Word16 Q_new, + Word16 gen_exc ); + +void SynthesisSTFT_enc_ivas_fx( + Word32 *fftBuffer, /* i : pointer to FFT bins */ + Word16 fftBufferExp, /* i : exponent of FFT bins */ + Word16 *timeDomainOutput, /* o : pointer to time domain signal */ + Word16 *olapBuffer, /* i/o : pointer to overlap buffer */ + const PWord16 *olapWin, /* i : pointer to overlap window */ + Word16 tcx_transition, + HANDLE_FD_CNG_COM hFdCngCom, /* i/o : pointer to FD_CNG structure containing all buffers and variables */ + Word16 gen_exc, + Word16 *Q_new, + const Word16 element_mode, /* i : element mode */ + const Word16 nchan_out /* i : number of output channels */ +); + #endif diff --git a/lib_enc/qlpc_stoch_fx.c b/lib_enc/qlpc_stoch_fx.c index dab87e3b32c946701fff65c5e76c260a19cc3b8b..afc45cdb63dcaa598f0425a2dcbf1cd9520a2a40 100644 --- a/lib_enc/qlpc_stoch_fx.c +++ b/lib_enc/qlpc_stoch_fx.c @@ -102,19 +102,19 @@ void lpc_quantization_fx( /*Force safety net when possible in case of transitions*/ test(); test(); - IF( st->tc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net_fx, 1 ) ) ) + IF( st->tc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net, 1 ) ) ) { force_sf = 1; move16(); - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); } test(); - IF( EQ_16( st->next_force_safety_net_fx, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) + IF( EQ_16( st->next_force_safety_net, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) { force_sf = 1; - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; } test(); @@ -146,7 +146,7 @@ void lpc_quantization_fx( IF( LT_16( stab, add( STAB_FAC_LIMIT_FX, 6553 /* =0.2 in Q15*/ ) ) && ( EQ_16( coder_type, VOICED ) || EQ_16( coder_type, GENERIC ) ) && EQ_16( st->Opt_RF_ON, 1 ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; } lsf2lsp_fx( lsf_q, lsp_q, M, st->sr_core ); @@ -201,6 +201,170 @@ void lpc_quantization_fx( return; } +#ifdef IVAS_FLOAT_FIXED +void lpc_quantization_ivas_fx( + Encoder_State *st, + const Word16 lsp[], /* Q15 */ + const Word16 lspmid[], /* Q15 */ + Word16 lsp_q[], /* Q15 */ + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], /* Q15 */ + const Word16 coder_type, + const Word16 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 *bits_param_lpc, + Word16 *no_param_lpc, + const Word16 Q_ener ) +{ + Word16 nb_indices; + Word16 lsfmid_q[M]; /* 14Q1*1.28 */ + Word16 lsfmid_idx; + Word16 i, force_sf; + Word16 lsf[M], lsfmid[M]; + Word16 fec_lsf[M], stab; + + nb_indices = 0; + move16(); + + /****** High-rate LPC quantizer *******/ + + IF( st->lpcQuantization == 0 ) + { + E_LPC_lsp_lsf_conversion( lsp, lsf, M ); + + IF( ( EQ_16( st->core, TCX_10_CORE ) ) ) + { + E_LPC_lsp_lsf_conversion( lspmid, lsfmid, M ); + } + + /* LPC quantizer */ + qlpc_avq_fx( lsf, lsfmid, lsf_q, lsfmid_q, param_lpc, &nb_indices, nbits_lpc, st->core, st->sr_core ); + + E_LPC_lsf_lsp_conversion( lsf_q, lsp_q, M ); + + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + E_LPC_lsf_lsp_conversion( lsfmid_q, lspmid_q, M ); + } + + assert( nb_indices <= NPRM_LPC_NEW ); + } + + /****** Low-rate LPC quantizer *******/ + + ELSE IF( EQ_16( st->lpcQuantization, 1 ) ) + { + + lsp2lsf_fx( lsp, lsf, M, extract_l( st->sr_core ) ); + + force_sf = 0; + move16(); + /*Force safety net when possible in case of transitions*/ + test(); + test(); + IF( st->tc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net, 1 ) ) ) + { + force_sf = 1; + move16(); + st->next_force_safety_net = 0; + move16(); + } + + test(); + IF( EQ_16( st->next_force_safety_net, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) + { + force_sf = 1; + st->next_force_safety_net = 0; + move16(); + move16(); + } + + test(); + IF( EQ_32( st->sr_core, INT_FS_16k ) && EQ_16( coder_type, UNVOICED ) ) + { + lsf_end_enc_ivas_fx( st, lsf, lsf_q, ENDLSF_NBITS, GENERIC, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, GENERIC, NULL ); + + nb_indices = *no_param_lpc; + move16(); + } + ELSE + { + lsf_end_enc_ivas_fx( st, lsf, lsf_q, ENDLSF_NBITS, coder_type, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, coder_type, NULL ); + + nb_indices = *no_param_lpc; + move16(); + } + + + FEC_lsf_estim_enc_fx( st, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab_fx( lsf_q, fec_lsf, 0, st->L_frame ); /*Q15*/ + + + test(); + test(); + test(); + IF( LT_16( stab, add( STAB_FAC_LIMIT_FX, 6553 /* =0.2 in Q15*/ ) ) && + ( EQ_16( coder_type, VOICED ) || EQ_16( coder_type, GENERIC ) ) && EQ_16( st->Opt_RF_ON, 1 ) ) + { + st->next_force_safety_net = 1; + move16(); + } + + lsf2lsp_fx( lsf_q, lsp_q, M, st->sr_core ); + + *nbits_lpc = ENDLSF_NBITS; + move16(); + } + ELSE + { + assert( 0 ); + } + + st->seed_acelp = 0; + move16(); + FOR( i = nb_indices - 1; i >= 0; i-- ) + { + st->seed_acelp = extract_l( L_mac0( L_mac0( 13849, shr( st->seed_acelp, 1 ), 31821 ), param_lpc[i], 31821 ) ); + move16(); + } + + /* Mid-frame LPC quantization */ + + test(); + IF( st->lpcQuantization && acelp_midLpc ) + { + + IF( st->rate_switching_reset == 0 ) + { + lsp2lsf_fx( lspmid, lsfmid, M, extract_l( st->sr_core ) ); + + midlsf_enc_fx( st->lsf_old_fx, lsf_q, lsfmid, &lsfmid_idx, M, st->Bin_E_old_fx, Q_ener, (Word8) st->narrowBand, st->sr_core, coder_type ); + param_lpc[nb_indices] = lsfmid_idx; + move16(); + nb_indices = add( nb_indices, 1 ); + midlsf_dec( st->lsf_old_fx, lsf_q, lsfmid_idx, lsfmid_q, coder_type, NULL, 0, 1 ); + + reorder_lsf_fx( lsfmid_q, LSF_GAP_MID_FX, M, st->sr_core ); + lsf2lsp_fx( lsfmid_q, lspmid_q, M, st->sr_core ); + } + ELSE + { + param_lpc[nb_indices] = 0; + move16(); + nb_indices = add( nb_indices, 1 ); + } + } + + + return; +} +#endif + /*-------------------------------------------------------------------* * Unified_weighting() diff --git a/lib_enc/setmodeindex.c b/lib_enc/setmodeindex.c index 8077db8e8b8337934902fb41c3ca6b561a647807..7c9b89ab2f0d63d7958cb7851ce8c302a8a0c84f 100644 --- a/lib_enc/setmodeindex.c +++ b/lib_enc/setmodeindex.c @@ -52,6 +52,7 @@ ---------------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void SetModeIndex( Encoder_State *st, /* i : Encoder state */ const int32_t last_total_brate, /* i : last total bitrate */ @@ -81,8 +82,7 @@ void SetModeIndex( return; } - -#ifdef IVAS_FLOAT_FIXED +#else void SetModeIndex_ivas_fx( Encoder_State *st, /* i : Encoder state */ const Word32 last_total_brate, /* i : last total bitrate */ diff --git a/lib_enc/spec_flatness_fx.c b/lib_enc/spec_flatness_fx.c index 271f7ba1b3ed974d0d1b8239c68c123e6386bf24..2ee10bf068b1469a7a2e455367b9d106b52b8123 100644 --- a/lib_enc/spec_flatness_fx.c +++ b/lib_enc/spec_flatness_fx.c @@ -133,7 +133,7 @@ void spec_flatness_fx( SFM_Qtmp = sub( SFM_Qtmp, SPEC_AMP_Q ); SFM_Qtmp = sub( SFM_Qtmp, SFM_Q ); - sSFM[0] = add( mult( sSFM[0], 0x6ccc ), shr( mult( SFM, 0x1333 ), SFM_Qtmp ) ); + sSFM[0] = add_sat( mult( sSFM[0], 0x6ccc ), shr( mult( SFM, 0x1333 ), SFM_Qtmp ) ); move16(); /*sSFM2*/ diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c index 7d605217ae59c2235f6c5139117c9ab18fb495ab..9fe43f12846962966bd49785423ec37c0cd2e413 100644 --- a/lib_enc/speech_music_classif.c +++ b/lib_enc/speech_music_classif.c @@ -49,6 +49,7 @@ #endif +#ifndef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * Local constants *---------------------------------------------------------------------*/ @@ -98,6 +99,7 @@ static int16_t sp_mus_classif_1st( Encoder_State *st, const int16_t localVAD_HE_ static void sp_mus_classif_2nd( Encoder_State *st, const float Etot, int16_t *attack_flag, const float *inp ); static void music_mixed_classif_improv( Encoder_State *st, const float *new_inp, const float *epsP, const float etot, const float old_cor, const float cor_map_sum ); +#endif /*---------------------------------------------------------------------* @@ -155,8 +157,10 @@ void speech_music_clas_init( hSpMusClas->last_non_sta = 0.0f; set_f( hSpMusClas->past_PS, 0.0f, HIGHEST_FBIN - LOWEST_FBIN ); hSpMusClas->past_ps_diff = 0; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->past_epsP2 = 01; hSpMusClas->past_epsP = 0; +#endif hSpMusClas->flag_spitch_cnt = 0; hSpMusClas->gsc_thres[0] = TH_0_MIN; @@ -169,17 +173,24 @@ void speech_music_clas_init( hSpMusClas->gsc_nb_thr_1 = 0; hSpMusClas->gsc_nb_thr_3 = 0; hSpMusClas->mold_corr = 0.9f; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->mean_avr_dyn = 0.5f; hSpMusClas->last_sw_dyn = 10.0f; +#endif hSpMusClas->relE_attack_cnt = 0; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->prev_relE = 0.0f; hSpMusClas->prev_Etot = 0.0f; +#endif hSpMusClas->prev_vad = 0; hSpMusClas->vad_0_1_cnt = 0; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->relE_attack_sum = 0; +#endif /* speech/music classifier improvement */ +#ifndef IVAS_FLOAT_FIXED for ( i = 0; i < BUF_LEN; i++ ) { hSpMusClas->buf_flux[i] = -100; @@ -190,72 +201,100 @@ void speech_music_clas_init( hSpMusClas->buf_Ntonal2[i] = 0; hSpMusClas->buf_Ntonal_lf[i] = 0; } +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->lpe_buf, 0, HANG_LEN_INIT ); set_f( hSpMusClas->voicing_buf, 0, HANG_LEN_INIT ); +#endif hSpMusClas->gsc_hangover = 0; +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->sparse_buf, 0, HANG_LEN_INIT ); set_f( hSpMusClas->hf_spar_buf, 0, HANG_LEN_INIT ); hSpMusClas->LT_sparse = 0.0f; +#endif hSpMusClas->gsc_cnt = 0; hSpMusClas->last_vad_spa = 0; +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->old_Bin_E, 0.0f, 3 * N_OLD_BIN_E ); set_f( hSpMusClas->buf_etot, 0, 4 ); set_f( hSpMusClas->buf_dlp, 0, 10 ); +#endif hSpMusClas->UV_cnt1 = 300; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->LT_UV_cnt1 = 250.0f; +#endif hSpMusClas->onset_cnt = 0; hSpMusClas->attack_hangover = 0; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->dec_mov = 0.0f; hSpMusClas->dec_mov1 = 0.0f; hSpMusClas->mov_log_max_spl = 200.0f; hSpMusClas->old_lt_diff[0] = 0.0f; hSpMusClas->old_lt_diff[1] = 0.0f; +#endif set_f( hSpMusClas->finc_prev, 0.0f, ATT_NSEG ); hSpMusClas->lt_finc = 0.0f; hSpMusClas->last_strong_attack = 0; +#ifdef IVAS_FLOAT_FIXED + hSpMusClas->tdm_lt_Etot_fx = 328 /* 0.01 in Q15*/; +#else hSpMusClas->tdm_lt_Etot = 0.01f; +#endif set_f( hSpMusClas->tod_lt_Bin_E, 0.0f, TOD_NSPEC ); +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->tod_S_map_lt, 0.0f, TOD_NSPEC ); hSpMusClas->tod_thr_lt = TOD_THR_MASS; hSpMusClas->tod_weight = 0.0f; hSpMusClas->tod_S_mass_prev = 0.0f; hSpMusClas->tod_S_mass_lt = 0.0f; +#endif /* speech/music classification */ set_s( hSpMusClas->lt_old_mode, 1, 3 ); +#ifndef IVAS_FLOAT_FIXED hSpMusClas->lt_voicing_flt = 0.5f; hSpMusClas->lt_corr_flt = 0.5f; hSpMusClas->lt_tonality_flt = 0; +#endif set_s( hSpMusClas->lt_corr_pitch, 0, 3 ); hSpMusClas->lt_hangover = 0; hSpMusClas->lowrate_pitchGain_flt = 0; hSpMusClas->lt_music_hangover = 0; +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->tonality2_buf, 0, HANG_LEN_INIT ); set_f( hSpMusClas->tonality3_buf, 0, HANG_LEN_INIT ); set_f( hSpMusClas->LPCErr_buf, 0, HANG_LEN_INIT ); +#endif hSpMusClas->lt_music_state = 0; hSpMusClas->lt_speech_state = 0; hSpMusClas->lt_speech_hangover = 0; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->lt_dec_thres = 10.0f; hSpMusClas->ener_RAT = 0.0f; +#endif hSpMusClas->high_stable_cor = 0; +#ifndef IVAS_FLOAT_FIXED set_f( hSpMusClas->var_cor_t, 0.0f, VAR_COR_LEN ); +#endif hSpMusClas->lps = 0.0f; hSpMusClas->lpm = 0.0f; +#ifndef IVAS_FLOAT_FIXED hSpMusClas->lpn = 0.0f; +#endif return; } +#ifndef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * speech_music_classif() * @@ -950,950 +989,200 @@ static float tonal_det( } *tod_S_mass_prev = S_mass; *tod_S_mass_lt = alpha * *tod_S_mass_lt + ( 1 - alpha ) * S_mass; - S_mass = *tod_S_mass_lt; - - /* updating adaptive decision threshold */ - if ( S_mass > *tod_thr_lt ) - { - *tod_thr_lt -= THR_MASS_STEP_DN; - } - else - { - *tod_thr_lt += THR_MASS_STEP_UP; - } - - if ( *tod_thr_lt > THR_MASS_MAX ) - { - *tod_thr_lt = THR_MASS_MAX; - } - - if ( *tod_thr_lt < THR_MASS_MIN ) - { - *tod_thr_lt = THR_MASS_MIN; - } - - return S_mass; -} - -/*---------------------------------------------------------------------* - * var_cor_calc() - * - * Calculate variance of correlation - *---------------------------------------------------------------------*/ - -static void var_cor_calc( - const float old_corr, - float *mold_corr, - float var_cor_t[], - int16_t *high_stable_cor ) -{ - int16_t i; - float var_cor; - - /* update buffer of old correlation values */ - for ( i = VAR_COR_LEN - 1; i > 0; i-- ) - { - var_cor_t[i] = var_cor_t[i - 1]; - } - var_cor_t[i] = old_corr; - - /* calculate variance of correlation */ - var_cor = var( var_cor_t, VAR_COR_LEN ); - - /* set flag in case of highly-correlated stable signal */ - if ( *mold_corr > 0.8f && var_cor < 5e-4f ) - { - *high_stable_cor = 1; - } - else - { - *high_stable_cor = 0; - } - - /* update average correlation */ - *mold_corr = 0.1f * old_corr + 0.9f * *mold_corr; - - return; -} - -/*---------------------------------------------------------------------* - * attack_det() - * - * Attack detection - *---------------------------------------------------------------------*/ - -static int16_t attack_det( - const float *inp, /* i : input signal */ - const int16_t last_clas, /* i : last signal clas */ - const int16_t localVAD, /* i : local VAD flag */ - const int16_t coder_type, /* i : coder type */ - const int32_t total_brate, /* i : total bitrate */ - const int16_t element_mode, /* i : IVAS element mode */ - const int16_t clas, /* i : signal class */ - float finc_prev[], /* i/o: previous finc */ - float *lt_finc, /* i/o: long-term mean finc */ - int16_t *last_strong_attack /* i/o: last strong attack flag */ -) -{ - int16_t i, attack; - float etmp, etmp2, finc[ATT_NSEG]; - int16_t att_3lsub_pos; - int16_t attack1; - - att_3lsub_pos = ATT_3LSUB_POS; - if ( total_brate >= ACELP_24k40 ) - { - att_3lsub_pos = ATT_3LSUB_POS_16k; - } - - /* compute energy per section */ - for ( i = 0; i < ATT_NSEG; i++ ) - { - finc[i] = sum2_f( inp + i * ATT_SEG_LEN, ATT_SEG_LEN ); - } - - attack = maximum( finc, ATT_NSEG, &etmp ); - attack1 = attack; - - if ( localVAD == 1 && coder_type == GENERIC ) - { - /* compute mean energy in the first three subframes */ - etmp = mean( finc, att_3lsub_pos ); - - /* compute mean energy after the attack */ - etmp2 = mean( finc + attack, ATT_NSEG - attack ); - - /* and compare them */ - if ( etmp * 8 > etmp2 ) - { - /* stop, if the attack is not sufficiently strong */ - attack = 0; - } - - if ( last_clas == VOICED_CLAS && etmp * 20 > etmp2 ) - { - /* stop, if the signal was voiced and the attack is not sufficiently strong */ - attack = 0; - } - - /* compare wrt. other sections (reduces miss-classification) */ - if ( attack > 0 ) - { - etmp2 = finc[attack]; - - for ( i = 2; i < att_3lsub_pos - 2; i++ ) - { - if ( finc[i] * 2.0f > etmp2 ) - { - /* stop, if the attack is not sufficiently strong */ - attack = 0; - break; - } - } - } - - if ( attack == 0 && element_mode > EVS_MONO && ( clas < VOICED_TRANSITION || clas == ONSET ) ) - { - mvr2r( finc, finc_prev, attack1 ); - - /* compute mean energy before the attack */ - etmp = mean( finc_prev, ATT_NSEG ); - - etmp2 = finc[attack1]; - - if ( ( etmp * 16 < etmp2 ) || ( etmp * 12 < etmp2 && last_clas == UNVOICED_CLAS ) ) - { - attack = attack1; - } - - if ( 20 * *lt_finc > etmp2 || *last_strong_attack ) - { - attack = 0; - } - } - - *last_strong_attack = attack; - } - - /* compare wrt. other sections (reduces miss-classification) */ - else if ( attack > 0 ) - { - for ( i = 2; i < att_3lsub_pos - 2; i++ ) - { - if ( i != attack && finc[i] * 1.3f > finc[attack] ) - { - /* stop, if the attack is not sufficiently strong */ - attack = 0; - break; - } - } - *last_strong_attack = 0; - } - - /* updates */ - mvr2r( finc, finc_prev, ATT_NSEG ); - *lt_finc = 0.95f * *lt_finc + 0.05f * mean( finc, ATT_NSEG ); - - return attack; -} - -/*---------------------------------------------------------------------* - * ivas_smc_gmm() - * - * 1st stage of the speech/music classification (based on the GMM model) - *---------------------------------------------------------------------*/ -/*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ - -#ifdef IVAS_FLOAT_FIXED -int16_t ivas_smc_gmm( - Encoder_State *st, /* i/o: state structure */ - STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ - const int16_t localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ - const float Etot, /* i : total frame energy */ - const float lsp_new[M], /* i : LSPs in current frame */ - const float cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.) */ - const float epsP[M + 1], /* i : LP prediciton error */ - const float PS[], /* i : energy spectrum */ - const float non_sta, /* i : unbound non-stationarity */ - const float relE, /* i : relative frame energy */ - int16_t *high_lpn_flag, /* i/o: sp/mus LPN flag */ - const int16_t flag_spitch /* i : flag to indicate very short stable pitch */ -) -{ - int16_t i, m, dec; - int16_t flag_odv; - float lps, lpm, lpn; - float ps[N_SMC_MIXTURES], pm[N_SMC_MIXTURES], pn[N_SMC_MIXTURES]; - float fvm[N_PCA_COEF], lprob; - float dlp, ftmp, sum_PS, ps_diff, ps_sta, wrelE, wdrop, wght; - float wrise; - float dlp_mean2var; - float FV[N_SMC_FEATURES], *pFV, PS_norm[128], dPS[128]; - const float *pODV; - float *pFV_st, smc_st_mean_fact; - int16_t relE_attack_flag; - int16_t j, len; - const float *pt_mel_fb; - float melS[NB_MEL_BANDS], mfcc[NB_MEL_BANDS]; - int16_t odv_cnt; - int16_t i_out[N_SMC_FEATURES], *p_out; - - /*------------------------------------------------------------------* - * Initialization - *------------------------------------------------------------------*/ - - SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; - - /*------------------------------------------------------------------* - * State machine (sp_mus_state: -8 = INACTIVE, -7:-1 = UNSTABLE, 0:7 = ENTRY, 8 = STABLE ) - *------------------------------------------------------------------*/ - - if ( localVAD_HE_SAD ) - { - if ( relE < -20 ) - { - if ( hSpMusClas->sp_mus_state > 0 ) - { - if ( hSpMusClas->sp_mus_state < HANG_LEN ) - { - /* energy is too low but we are in entry period -> reset the inactive counter to allow new entry later */ - hSpMusClas->inact_cnt = 0; - } - - /* energy is too low -> we are going to instable state */ - hSpMusClas->sp_mus_state = 0; - } - else if ( hSpMusClas->sp_mus_state > -HANG_LEN ) - { - /* energy is still too low -> we are still in instable state */ - hSpMusClas->sp_mus_state--; - } - } - else if ( hSpMusClas->sp_mus_state <= 0 ) - { - if ( hSpMusClas->inact_cnt == 0 ) - { - - hSpMusClas->sp_mus_state = 1; - } - else - { - - hSpMusClas->sp_mus_state = HANG_LEN; - } - - hSpMusClas->inact_cnt = 12; - } - else if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) - { - /* we are inside an entry period -> increment the counter of entry frames */ - hSpMusClas->sp_mus_state++; - } - - if ( hSpMusClas->sp_mus_state < 0 && hSpMusClas->inact_cnt > 0 ) - { - hSpMusClas->inact_cnt--; - } - } - else - { - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) - { - hSpMusClas->inact_cnt = 0; - } - else if ( hSpMusClas->inact_cnt > 0 ) - { - hSpMusClas->inact_cnt--; - } - - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) - { - hSpMusClas->sp_mus_state = -HANG_LEN; - } - else if ( hSpMusClas->sp_mus_state > 0 ) - { - hSpMusClas->sp_mus_state = -1; - } - else if ( hSpMusClas->sp_mus_state > -HANG_LEN ) - { - /* we are in inactive state */ - hSpMusClas->sp_mus_state--; - } - } - - /* detect attacks based on relE */ - if ( relE > hSpMusClas->prev_relE ) - { - hSpMusClas->relE_attack_sum += relE - hSpMusClas->prev_relE; - } - else - { - hSpMusClas->relE_attack_sum = 0; - } - hSpMusClas->prev_relE = relE; - - /* update counter from last VAD 0->1 change */ - if ( hSpMusClas->prev_vad == 0 && localVAD_HE_SAD == 1 ) - { - hSpMusClas->vad_0_1_cnt = 1; - } - else if ( localVAD_HE_SAD == 1 && hSpMusClas->vad_0_1_cnt > 0 && hSpMusClas->vad_0_1_cnt < 50 ) - { - hSpMusClas->vad_0_1_cnt++; - } - else - { - hSpMusClas->vad_0_1_cnt = 0; - } - hSpMusClas->prev_vad = localVAD_HE_SAD; - - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && hSpMusClas->relE_attack_sum > 5.0f ) - { - hSpMusClas->relE_attack_cnt++; - - /* set flag only in the first X frames in a series */ - if ( hSpMusClas->relE_attack_cnt > 0 && hSpMusClas->relE_attack_cnt < 3 ) - { - relE_attack_flag = 1; - } - else - { - relE_attack_flag = 0; - } - } - else - { - hSpMusClas->relE_attack_cnt = 0; - relE_attack_flag = 0; - } - - hSpMusClas->prev_Etot = Etot; - - /*------------------------------------------------------------------* - * Preparation of the feature vector - *------------------------------------------------------------------*/ - - pFV = FV; - - /* [0] OL pitch */ - if ( relE_attack_flag || st->tc_cnt == 1 || st->tc_cnt == 2 ) - { - *pFV++ = (float) st->pitch[2]; - } - else - { - *pFV++ = (float) ( st->pitch[0] + st->pitch[1] + st->pitch[2] ) / 3.0f; - } - - /* [1] voicing */ - if ( relE_attack_flag || st->tc_cnt == 1 || st->tc_cnt == 2 ) - { - *pFV++ = st->voicing[2]; - } - else - { - *pFV++ = ( st->voicing[0] + st->voicing[1] + st->voicing[2] ) / 3.0f; - } - - /* [2,3,4,5,6] LSFs */ - *pFV++ = acosf( lsp_new[2] ); - *pFV++ = acosf( lsp_new[3] ); - *pFV++ = acosf( lsp_new[4] ); - *pFV++ = acosf( lsp_new[5] ); - *pFV++ = acosf( lsp_new[6] ); - - /* [7] cor_map_sum */ - *pFV++ = cor_map_sum; - - /* [8] non_sta */ - *pFV++ = non_sta; - - /* [9] epsP */ - *pFV++ = logf( epsP[14] + 1e-5f ) - logf( epsP[0] + 1e-5f ); - - /* [10,11,12] MFCCs */ - set_zero( melS, NB_MEL_BANDS ); - pt_mel_fb = mel_fb; - for ( i = 0; i < NB_MEL_BANDS; i++ ) - { - j = mel_fb_start[i]; - len = mel_fb_len[i]; - melS[i] = logf( dotp( &PS[j], pt_mel_fb, len ) + 1e-5f ); - pt_mel_fb += len; - } - -#ifdef IVAS_FLOAT_FIXED - //////////////////// to be removed ////////////////////// - Word32 y_fx[NB_MEL_BANDS]; - Word32 x_fx[NB_MEL_BANDS]; - Word32 A_fx[NB_MEL_BANDS * NB_MEL_COEF]; - Word16 y_q_fx[NB_MEL_BANDS]; - Word16 x_q_fx[NB_MEL_BANDS]; - Word16 A_q_fx[NB_MEL_BANDS * NB_MEL_COEF]; - Word32 *pt_x_fx, *pt_A_fx; - const Float32 *pt_x, *pt_A; - Word16 *pt_x_q_fx, *pt_A_q_fx; - - pt_A_fx = A_fx; - pt_A_q_fx = A_q_fx; - pt_A = dct_mtx; - - FOR( i = 0; i < NB_MEL_COEF; i++ ) - { - pt_x = melS; - pt_x_fx = x_fx; - pt_x_q_fx = x_q_fx; - FOR( j = 0; j < NB_MEL_BANDS; j++ ) - { - IF( EQ_16( i, 0 ) ) - { - *pt_x_q_fx = sub( Q_factor_L( *pt_x ), 3 ); - *pt_x_fx++ = (Word32) ( *pt_x++ * ( W_shl( 1, *pt_x_q_fx++ ) ) ); - } - *pt_A_q_fx = sub( Q_factor_L( *pt_A ), 3 ); - *pt_A_fx++ = (Word32) ( *pt_A++ * ( W_shl( 1, *pt_A_q_fx++ ) ) ); - } - } - - v_mult_mat_fx( y_fx, y_q_fx, (const Word32 *) x_fx, x_q_fx, (const Word32 *) A_fx, A_q_fx, NB_MEL_BANDS, NB_MEL_COEF ); - - ////////////////////////////// to be removed //////////////////////// - FOR( i = 0; i < NB_MEL_COEF; i++ ) - { - IF( LT_16( y_q_fx[i], 0 ) ) - { - mfcc[i] = (Float32) y_fx[i] * W_shl( 1, -y_q_fx[i] ); - } - ELSE - { - mfcc[i] = (Float32) y_fx[i] / W_shl( 1, y_q_fx[i] ); - } - } - //////////////////////////////////////////////////////////////////// -#else - v_mult_mat( mfcc, melS, dct_mtx, NB_MEL_BANDS, NB_MEL_COEF ); -#endif - - *pFV++ = mfcc[2]; - *pFV++ = mfcc[6]; - *pFV++ = mfcc[12]; - - /* calculation of differential normalized power spectrum */ - sum_PS = 1e-5f; - for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) - { - sum_PS += PS[i]; - } - - for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) - { - PS_norm[i] = PS[i] / sum_PS; - dPS[i] = fabsf( PS_norm[i] - hSpMusClas->past_PS[i - LOWEST_FBIN] ); - } - - /* [13] ps_diff (spectral difference) */ - ps_diff = 0; - for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) - { - ps_diff += dPS[i]; - } - - *pFV++ = ps_diff; - - /* [14] ps_sta (spectral stationarity) */ - ps_sta = 0; - for ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) - { - if ( PS_norm[i] > hSpMusClas->past_PS[i - LOWEST_FBIN] ) - { - ps_sta += PS_norm[i] / ( dPS[i] + 1e-5f ); - } - else - { - ps_sta += hSpMusClas->past_PS[i - LOWEST_FBIN] / ( dPS[i] + 1e-5f ); - } - } - - *pFV++ = logf( ps_sta + 1e-5f ); - mvr2r( &PS_norm[LOWEST_FBIN], hSpMusClas->past_PS, HIGHEST_FBIN - LOWEST_FBIN ); - - /* save ps_diff and ps_sta features for XTALK and UNCLR classifier */ - if ( hStereoClassif != NULL ) - { - if ( st->idchan == 0 ) - { - hStereoClassif->ps_diff_ch1 = ps_diff; - hStereoClassif->ps_sta_ch1 = logf( ps_sta + 1e-5f ); - } - else - { - hStereoClassif->ps_diff_ch2 = ps_diff; - hStereoClassif->ps_sta_ch2 = logf( ps_sta + 1e-5f ); - } - } - - /*------------------------------------------------------------------* - * Outlier detection based on feature histograms - *------------------------------------------------------------------*/ - - flag_odv = 0; - if ( localVAD_HE_SAD ) - { - pFV = FV; - pODV = hout_intervals; - p_out = i_out; - odv_cnt = 0; - for ( i = 0; i < N_SMC_FEATURES; i++ ) - { - if ( *pFV < pODV[0] || *pFV > pODV[1] ) - { - *p_out++ = i; - odv_cnt++; - } - - pFV++; - pODV += 2; - } - - /* set outlier flag */ - if ( odv_cnt >= 2 ) - { - flag_odv = 1; - - /* replace outlying features with values from the previous frame */ - for ( i = 0; i < odv_cnt; i++ ) - { - FV[i_out[i]] = hSpMusClas->prev_FV[i_out[i]]; - } - } - } - - /*------------------------------------------------------------------* - * Adaptive short-term mean filter on feature vector - *------------------------------------------------------------------*/ - - pFV = FV; - pFV_st = hSpMusClas->FV_st; - smc_st_mean_fact = SMC_ST_MEAN_FACT; - for ( i = 0; i < N_SMC_FEATURES; i++ ) - { - *pFV_st = smc_st_mean_fact * ( *pFV_st ) + ( 1 - smc_st_mean_fact ) * ( *pFV ); - - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && ( relE_attack_flag || flag_odv ) ) - { - /* strong attack or outlier frame during entry state -> features cannot be trusted but there is also no useful past info -> */ - /* -> do whatever you want because dlp will be reset to 0 anyway */ - pFV++; - pFV_st++; - } - else if ( hSpMusClas->sp_mus_state == HANG_LEN && ( st->tc_cnt == 1 || st->tc_cnt == 2 ) ) - { - /* energy attack in stable state -> use current features intead of the long-term average */ - pFV++; - pFV_st++; - } - else - { - *pFV++ = *pFV_st++; - } - } - - /* update */ - mvr2r( FV, hSpMusClas->prev_FV, N_SMC_FEATURES ); - - /*------------------------------------------------------------------* - * Non-linear power transformation (boxcox) on certain features - *------------------------------------------------------------------*/ - - pFV = FV; - for ( i = 0; i < N_SMC_FEATURES; i++ ) - { - if ( bcox_lmbd[i] != 0 ) - { - *pFV -= bcox_add_cnst[i]; - if ( *pFV < 1 ) - { - *pFV = 1; - } - *pFV = ( powf( *pFV, bcox_lmbd[i] ) - 1 ) / bcox_lmbd[i]; - } - - pFV++; - } - - /*------------------------------------------------------------------* - * Scaling of the feature vector - * PCA - *------------------------------------------------------------------*/ - - pFV = FV; - for ( i = 0; i < N_SMC_FEATURES; i++ ) - { - /* Standard scaler - mean and variance normalization */ - *pFV = ( *pFV - sm_means[i] ) / sm_scale[i]; - pFV++; - - /* MinMax sclaer - mean and variance normalization */ - /**pFV = *pFV * sm_scale[i] + sm_min[i];*/ - /*pFV++;*/ - } - - /* PCA */ - v_sub( FV, pca_mean_, FV, N_SMC_FEATURES ); - v_mult_mat( FV, FV, pca_components_, N_SMC_FEATURES, N_PCA_COEF ); - - /*------------------------------------------------------------------* - * Calculation of posterior probability - * Log-probability - *------------------------------------------------------------------*/ - -#ifdef IVAS_FLOAT_FIXED - Word32 fvm_fx[N_PCA_COEF], lprob_fx; - Word16 fvm_q, guard_bits; - guard_bits = find_guarded_bits_fx( N_PCA_COEF ); // 12! 479001600 -#endif - /* run loop for all mixtures (for each mixture, calculate the probability of speech, music and noise) */ - lps = lpm = lpn = 0; - for ( m = 0; m < N_SMC_MIXTURES; m++ ) - { - v_sub( FV, &means_speech[m * N_PCA_COEF], fvm, N_PCA_COEF ); - -#ifdef IVAS_FLOAT_FIXED - f2me_buf( fvm, fvm_fx, &fvm_q, N_PCA_COEF ); - fvm_q = sub( 31, fvm_q ); - scale_sig32( fvm_fx, N_PCA_COEF, sub( sub( fvm_q, guard_bits ), fvm_q ) ); - fvm_q = sub( fvm_q, guard_bits ); - - lprob_fx = dot_product_cholesky_fx( fvm_fx, &prec_chol_speech_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); - lprob = fixedToFloat( lprob_fx, sub( 2 * fvm_q, 37 ) ); -#else - lprob = dot_product_cholesky( fvm, &prec_chol_speech[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); -#endif - ps[m] = logf( weights_speech[m] ) + log_det_chol_speech[m] - 0.5f * N_PCA_COEF * logf( PI2 ) - 0.5f * lprob; - - v_sub( FV, &means_music[m * N_PCA_COEF], fvm, N_PCA_COEF ); -#ifdef IVAS_FLOAT_FIXED - f2me_buf( fvm, fvm_fx, &fvm_q, N_PCA_COEF ); - fvm_q = sub( 31, fvm_q ); - scale_sig32( fvm_fx, N_PCA_COEF, sub( sub( fvm_q, guard_bits ), fvm_q ) ); - fvm_q = sub( fvm_q, guard_bits ); - lprob_fx = dot_product_cholesky_fx( fvm_fx, &prec_chol_music_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); - lprob = fixedToFloat( lprob_fx, sub( 2 * fvm_q, 37 ) ); -#else - lprob = dot_product_cholesky( fvm, &prec_chol_music[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); -#endif - pm[m] = logf( weights_music[m] ) + log_det_chol_music[m] - 0.5f * N_PCA_COEF * logf( PI2 ) - 0.5f * lprob; - - v_sub( FV, &means_noise[m * N_PCA_COEF], fvm, N_PCA_COEF ); -#ifdef IVAS_FLOAT_FIXED - f2me_buf( fvm, fvm_fx, &fvm_q, N_PCA_COEF ); - fvm_q = sub( 31, fvm_q ); - scale_sig32( fvm_fx, N_PCA_COEF, sub( sub( fvm_q, guard_bits ), fvm_q ) ); - fvm_q = sub( fvm_q, guard_bits ); - lprob_fx = dot_product_cholesky_fx( fvm_fx, &prec_chol_noise_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); - lprob = fixedToFloat( lprob_fx, sub( 2 * fvm_q, 37 ) ); -#else - lprob = dot_product_cholesky( fvm, &prec_chol_noise[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF ); -#endif - pn[m] = logf( weights_noise[m] ) + log_det_chol_noise[m] - 0.5f * N_PCA_COEF * logf( PI2 ) - 0.5f * lprob; - } - - lps = logsumexp( ps, N_SMC_MIXTURES ); - lpm = logsumexp( pm, N_SMC_MIXTURES ); - lpn = logsumexp( pn, N_SMC_MIXTURES ); - - *high_lpn_flag = 0; - if ( lpn > lps && lpn > lpm ) - { - *high_lpn_flag = 1; - } - - hSpMusClas->lpm = lpm; - hSpMusClas->lps = lps; - hSpMusClas->lpn = lpn; - - /* determine HQ Generic speech class */ - if ( st->hHQ_core != NULL ) - { - if ( lps > lpm + 0.5f ) - { - st->hHQ_core->hq_generic_speech_class = 1; - } - else - { - st->hHQ_core->hq_generic_speech_class = 0; - } - } - - /*------------------------------------------------------------------* - * Decision without hangover - * Weighted decision - *------------------------------------------------------------------*/ - - /* decision without hangover (0 - speech/noise, 1 - music) */ - if ( !localVAD_HE_SAD || Etot < 10 || ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && ( relE_attack_flag || flag_odv ) ) ) - { - dlp = 0; - } - else - { - dlp = lpm - lps + DLP_BIAS; - - if ( dlp > 30.0f ) - { - dlp = 30.0f; - } - else if ( dlp < -30.0f ) - { - dlp = -30.0f; - } - } - - dec = dlp > 0; - - /* calculate weight based on relE (higher relE -> lower weight, lower relE -> higher weight) */ - wrelE = lin_interp( relE, 15.0f, 0.9f, -15.0f, 0.99f, 1 ); - - /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ - hSpMusClas->dlp_mean_ST = 0.8f * hSpMusClas->dlp_mean_ST + 0.2f * dlp; - hSpMusClas->lt_dec_thres = hSpMusClas->dlp_mean_ST; - - if ( dlp < 0 && dlp < hSpMusClas->dlp_mean_ST ) - { - if ( hSpMusClas->dlp_mean_ST > 0 ) - { - hSpMusClas->wdrop = -dlp; - } - else if ( hSpMusClas->wdrop > 0 ) - { - hSpMusClas->wdrop += hSpMusClas->dlp_mean_ST - dlp; - } - } - else - { - hSpMusClas->wdrop = 0; - } - - wdrop = lin_interp( hSpMusClas->wdrop, 15.0f, 0.7f, 0.0f, 1.0f, 1 ); - - /* calculate weight based on rises of dlp (close to 1 during sudden rise of dlp, close to 0 otherwise) */ - if ( hSpMusClas->sp_mus_state == HANG_LEN && hSpMusClas->dlp_mean_ST > 0 && hSpMusClas->dlp_mean_ST > hSpMusClas->past_dlp_mean_ST[0] ) - { - if ( hSpMusClas->past_dlp_mean_ST[0] < 0 ) - { - hSpMusClas->wrise = hSpMusClas->dlp_mean_ST; - } - else if ( hSpMusClas->wrise > 0 ) - { - hSpMusClas->wrise += hSpMusClas->dlp_mean_ST - hSpMusClas->past_dlp_mean_ST[0]; - } - } - else - { - hSpMusClas->wrise = 0; - } - - wrise = lin_interp( hSpMusClas->wrise, 5.0f, 0.95f, 0.0f, 1.0f, 1 ); - - /* combine weights into one */ - wght = wrelE * wdrop * wrise; - - /* ratio of delta means vs. delta variances */ - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) - { - hSpMusClas->dlp_mean_LT = dlp; - hSpMusClas->dlp_var_LT = 0; - } - - hSpMusClas->dlp_mean_LT = 0.9f * hSpMusClas->dlp_mean_LT + 0.1f * dlp; - ftmp = dlp - hSpMusClas->dlp_mean_LT; - hSpMusClas->dlp_var_LT = 0.9f * hSpMusClas->dlp_var_LT + 0.1f * ( ftmp * ftmp ); + S_mass = *tod_S_mass_lt; - if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) + /* updating adaptive decision threshold */ + if ( S_mass > *tod_thr_lt ) { - dlp_mean2var = 0; + *tod_thr_lt -= THR_MASS_STEP_DN; } else { - dlp_mean2var = fabsf( hSpMusClas->dlp_mean_LT ) / ( sqrtf( fabsf( hSpMusClas->dlp_var_LT ) ) + 1.0f ); + *tod_thr_lt += THR_MASS_STEP_UP; } - if ( dlp_mean2var > 15.0f ) + if ( *tod_thr_lt > THR_MASS_MAX ) { - /* decrease the weight little bit when the classifier indicates "strong speech" or "strong music" */ - wght *= 0.9f; + *tod_thr_lt = THR_MASS_MAX; } - if ( wght > 1.0f ) - { - wght = 1.0f; - } - else if ( wght < 0.01f ) + if ( *tod_thr_lt < THR_MASS_MIN ) { - wght = 0.01f; + *tod_thr_lt = THR_MASS_MIN; } - if ( Etot < 10 ) - { - /* silence */ - wght = 0.92f; - } + return S_mass; +} - /* 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 ); +/*---------------------------------------------------------------------* + * var_cor_calc() + * + * Calculate variance of correlation + *---------------------------------------------------------------------*/ - /* xtalk classifier: apply long hysteresis to prevent LRTD on music */ - hSpMusClas->wdlp_xtalk = 0.995f * hSpMusClas->wdlp_xtalk + 0.005f * dlp; +static void var_cor_calc( + const float old_corr, + float *mold_corr, + float var_cor_t[], + int16_t *high_stable_cor ) +{ + int16_t i; + float var_cor; - /*------------------------------------------------------------------* - * Final speech/music decision - *------------------------------------------------------------------*/ + /* update buffer of old correlation values */ + for ( i = VAR_COR_LEN - 1; i > 0; i-- ) + { + var_cor_t[i] = var_cor_t[i - 1]; + } + var_cor_t[i] = old_corr; - if ( flag_spitch ) + /* calculate variance of correlation */ + var_cor = var( var_cor_t, VAR_COR_LEN ); + + /* set flag in case of highly-correlated stable signal */ + if ( *mold_corr > 0.8f && var_cor < 5e-4f ) { - hSpMusClas->flag_spitch_cnt = 5; + *high_stable_cor = 1; } - else if ( hSpMusClas->flag_spitch_cnt > 0 ) + else { - hSpMusClas->flag_spitch_cnt--; + *high_stable_cor = 0; } - if ( Etot < 10 ) + /* update average correlation */ + *mold_corr = 0.1f * old_corr + 0.9f * *mold_corr; + + return; +} + +/*---------------------------------------------------------------------* + * attack_det() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static int16_t attack_det( + const float *inp, /* i : input signal */ + const int16_t last_clas, /* i : last signal clas */ + const int16_t localVAD, /* i : local VAD flag */ + const int16_t coder_type, /* i : coder type */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t element_mode, /* i : IVAS element mode */ + const int16_t clas, /* i : signal class */ + float finc_prev[], /* i/o: previous finc */ + float *lt_finc, /* i/o: long-term mean finc */ + int16_t *last_strong_attack /* i/o: last strong attack flag */ +) +{ + int16_t i, attack; + float etmp, etmp2, finc[ATT_NSEG]; + int16_t att_3lsub_pos; + int16_t attack1; + + att_3lsub_pos = ATT_3LSUB_POS; + if ( total_brate >= ACELP_24k40 ) { - /* silence */ - dec = 0; + att_3lsub_pos = ATT_3LSUB_POS_16k; } - else if ( hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN ) + + /* compute energy per section */ + for ( i = 0; i < ATT_NSEG; i++ ) { - /* entry state -> final decision is calculated based on weighted average of past non-binary decisions */ - ftmp = w_spmus[hSpMusClas->sp_mus_state - 1][0] * dlp; - ftmp += dotp( &w_spmus[hSpMusClas->sp_mus_state - 1][1], hSpMusClas->past_dlp, HANG_LEN - 1 ); - if ( ftmp > 2.0f ) - { - if ( dlp > 2.0f ) - { - dec = 2; - } - else - { - dec = 1; - } - } - else - { - dec = 0; - } + finc[i] = sum2_f( inp + i * ATT_SEG_LEN, ATT_SEG_LEN ); } - else + + attack = maximum( finc, ATT_NSEG, &etmp ); + attack1 = attack; + + if ( localVAD == 1 && coder_type == GENERIC ) { - /* stable active state */ - if ( hSpMusClas->past_dec[0] == 0 && hSpMusClas->past_dec[1] == 0 && hSpMusClas->past_dec[2] == 0 && - ( ( hSpMusClas->flag_spitch_cnt > 0 && hSpMusClas->wdlp_0_95_sp > 3.4f ) || ( hSpMusClas->flag_spitch_cnt == 0 && hSpMusClas->wdlp_0_95_sp > 2.1f ) ) ) - { - /* switching from speech to unclear */ - dec = 1; - } - else if ( hSpMusClas->past_dec[0] == 0 && hSpMusClas->vad_0_1_cnt < 50 && hSpMusClas->relE_attack_sum == 0.0f && hSpMusClas->wdlp_0_95_sp > 1.0f ) - { - /* switch from speech to unclear also during slowly rising weak music onsets */ - dec = 1; - } - else if ( hSpMusClas->past_dec[0] == 1 && hSpMusClas->wdlp_0_95_sp > 2.5f ) + /* compute mean energy in the first three subframes */ + etmp = mean( finc, att_3lsub_pos ); + + /* compute mean energy after the attack */ + etmp2 = mean( finc + attack, ATT_NSEG - attack ); + + /* and compare them */ + if ( etmp * 8 > etmp2 ) { - /* switching from unclear to music */ - dec = 2; + /* stop, if the attack is not sufficiently strong */ + attack = 0; } - else if ( hSpMusClas->past_dec[0] == 2 && hSpMusClas->past_dec[1] == 2 && hSpMusClas->past_dec[2] == 2 && hSpMusClas->wdlp_0_95_sp < -1.0f ) + + if ( last_clas == VOICED_CLAS && etmp * 20 > etmp2 ) { - /* switching from music to unclear */ - dec = 1; + /* stop, if the signal was voiced and the attack is not sufficiently strong */ + attack = 0; } - else if ( hSpMusClas->past_dec[0] == 1 && hSpMusClas->wdlp_0_95_sp < -2.5f ) + + /* compare wrt. other sections (reduces miss-classification) */ + if ( attack > 0 ) { - /* switching from unclear to speech */ - dec = 0; + etmp2 = finc[attack]; + + for ( i = 2; i < att_3lsub_pos - 2; i++ ) + { + if ( finc[i] * 2.0f > etmp2 ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + break; + } + } } - else + + if ( attack == 0 && element_mode > EVS_MONO && ( clas < VOICED_TRANSITION || clas == ONSET ) ) { - dec = hSpMusClas->past_dec[0]; - } - } + mvr2r( finc, finc_prev, attack1 ); - /*------------------------------------------------------------------* - * raw S/M decision based on smoothed GMM score - *------------------------------------------------------------------*/ + /* compute mean energy before the attack */ + etmp = mean( finc_prev, ATT_NSEG ); - if ( dec == 0 || st->hSpMusClas->wdlp_0_95_sp <= 0 ) - { - st->sp_aud_decision0 = 0; - st->sp_aud_decision1 = 0; - } - else - { - st->sp_aud_decision0 = 1; - st->sp_aud_decision1 = 1; - } + etmp2 = finc[attack1]; - /*------------------------------------------------------------------* - * Updates - *------------------------------------------------------------------*/ + if ( ( etmp * 16 < etmp2 ) || ( etmp * 12 < etmp2 && last_clas == UNVOICED_CLAS ) ) + { + attack = attack1; + } - /* update buffer of past non-binary decisions */ - mvr2r( &hSpMusClas->past_dlp[0], &hSpMusClas->past_dlp[1], HANG_LEN - 2 ); - hSpMusClas->past_dlp[0] = dlp; + if ( 20 * *lt_finc > etmp2 || *last_strong_attack ) + { + attack = 0; + } + } - mvr2r( &hSpMusClas->past_dlp_mean_ST[0], &hSpMusClas->past_dlp_mean_ST[1], HANG_LEN - 2 ); - hSpMusClas->past_dlp_mean_ST[0] = hSpMusClas->dlp_mean_ST; + *last_strong_attack = attack; + } - /* update buffer of past binary decisions */ - mvs2s( &hSpMusClas->past_dec[0], &hSpMusClas->past_dec[1], HANG_LEN - 2 ); - hSpMusClas->past_dec[0] = dec; + /* compare wrt. other sections (reduces miss-classification) */ + else if ( attack > 0 ) + { + for ( i = 2; i < att_3lsub_pos - 2; i++ ) + { + if ( i != attack && finc[i] * 1.3f > finc[attack] ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + break; + } + } + *last_strong_attack = 0; + } + /* updates */ + mvr2r( finc, finc_prev, ATT_NSEG ); + *lt_finc = 0.95f * *lt_finc + 0.05f * mean( finc, ATT_NSEG ); - return dec; + return attack; } -#else + +/*---------------------------------------------------------------------* + * ivas_smc_gmm() + * + * 1st stage of the speech/music classification (based on the GMM model) + *---------------------------------------------------------------------*/ +/*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ + int16_t ivas_smc_gmm( Encoder_State *st, /* i/o: state structure */ STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ @@ -2557,7 +1846,6 @@ int16_t ivas_smc_gmm( return dec; } -#endif /*---------------------------------------------------------------------* * ivas_smc_mode_selection() @@ -2769,7 +2057,6 @@ void ivas_smc_mode_selection( return; } - /*------------------------------------------------------------------------* * music_mixed_classif_improv() * @@ -3820,3 +3107,4 @@ static void order_spectrum( return; } +#endif diff --git a/lib_enc/speech_music_classif_fx.c b/lib_enc/speech_music_classif_fx.c index b9d4237a86dfb5152f5dc4d40f1d856b6120de66..ee1edb1b23634ff50a1ef076722a52fe05979d0b 100644 --- a/lib_enc/speech_music_classif_fx.c +++ b/lib_enc/speech_music_classif_fx.c @@ -19,6 +19,7 @@ #ifdef IVAS_FLOAT_FIXED #include #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "prot.h" #endif @@ -34,6 +35,13 @@ #define LOG_PROB_CONST 11292 /*0.5f * N_FEATURES * LOG_PI2 in Q10 */ #define DLP_BIAS 0.138121f #define DLP_BIAS_FX 72415 /*Q19*/ + +#define TON_ALPHA_FX 31130 /* 0.95f in Q15 */ +#define THR_MASS_MAX_FX 3565158 /* 0.85f in Q22 */ +#define THR_MASS_MIN_FX 3145728 /* 0.75f in Q22 */ +#define THR_MASS_STEP_UP_FX 41943 /* 0.01f in Q22 */ +#define THR_MASS_STEP_DN_FX 83886 /* 0.02f in Q22 */ + /*---------------------------------------------------------------------* * Local functions *---------------------------------------------------------------------*/ @@ -277,6 +285,220 @@ void speech_music_clas_init_fx( return; } +void speech_music_clas_init_ivas_fx( + SP_MUS_CLAS_HANDLE hSpMusClas /* i/o: speech/music classifier handle */ +) +{ + Word16 i; + + set32_fx( hSpMusClas->FV_st_fx, 0, N_SMC_FEATURES ); //?? + + hSpMusClas->inact_cnt = 0; + move16(); + set16_fx( hSpMusClas->past_dec, 0, HANG_LEN - 1 ); + set16_fx( hSpMusClas->past_dlp_fx, 0, HANG_LEN - 1 ); + + set32_fx( hSpMusClas->past_dlp_mean_ST_fx, 0, HANG_LEN - 1 ); + hSpMusClas->dlp_mean_ST_fx = 0; + move32(); + hSpMusClas->dlp_mean_LT_fx = 0; + move32(); + hSpMusClas->dlp_var_LT_fx = 0; + move32(); + + FOR( i = 0; i < N_SMC_FEATURES; i++ ) + { + hSpMusClas->prev_FV_fx[i] = L_add( L_shr( hout_intervals_fx[2 * i], 1 ), L_shr( hout_intervals_fx[2 * i + 1], 1 ) ); + move32(); + } + + FOR( i = 0; i < NB_BANDS_SPMUS; i++ ) + { + hSpMusClas->past_log_enr_fx[i] = -1448; /* log(E_MIN) in Q8 */ + move16(); + } + + hSpMusClas->sp_mus_state = -8; + move16(); + hSpMusClas->wdrop_fx = 0; + move16(); + hSpMusClas->wrise_fx = 0; + move16(); + hSpMusClas->wdlp_0_95_sp_fx = 0; + move16(); + hSpMusClas->wdlp_xtalk_fx = 0; + move16(); + set16_fx( hSpMusClas->last_lsp_fx, 0, M_LSP_SPMUS ); + hSpMusClas->last_cor_map_sum_fx = 0; + move16(); + hSpMusClas->last_non_sta_fx = 0; + move16(); + set32_fx( hSpMusClas->past_PS_fx, 0, HIGHEST_FBIN - LOWEST_FBIN ); + hSpMusClas->past_ps_diff_fx = 0; + move16(); + hSpMusClas->past_epsP2_fx = 1024; /* 1.0f in Q10 */ + move16(); + hSpMusClas->past_epsP_fx = 0; + move16(); + hSpMusClas->flag_spitch_cnt = 0; + move16(); + + + hSpMusClas->gsc_thres_fx[0] = TH_0_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[1] = TH_1_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[2] = TH_2_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[3] = TH_3_MIN_FX; + move16(); + set16_fx( hSpMusClas->gsc_lt_diff_etot_fx, 0, 40 ); + hSpMusClas->gsc_mem_etot_fx = 0; + move16(); + hSpMusClas->gsc_last_music_flag = 0; + move16(); + hSpMusClas->gsc_nb_thr_1 = 0; + move16(); + hSpMusClas->gsc_nb_thr_3 = 0; + move16(); + hSpMusClas->mold_corr_fx = 29491; /* 0.9f in Q15 */ + move16(); + hSpMusClas->mean_avr_dyn_fx = 64; /* 0.5f in Q7 */ + move16(); + hSpMusClas->last_sw_dyn_fx = 2560; /* 10.0f in Q7 */ + move16(); + + hSpMusClas->relE_attack_cnt = 0; + move16(); + hSpMusClas->prev_relE_fx = 0; + move16(); + hSpMusClas->prev_Etot_fx = 0; + move16(); + hSpMusClas->prev_vad = 0; + move16(); + hSpMusClas->vad_0_1_cnt = 0; + move16(); + hSpMusClas->relE_attack_sum_fx = 0; + move16(); + + /* speech/music classifier improvement */ + FOR( i = 0; i < BUF_LEN; i++ ) + { + hSpMusClas->buf_flux_fx[i] = -12800; /*-100.0f in Q7 */ + move16(); + hSpMusClas->buf_pkh_fx[i] = 0; + move16(); + hSpMusClas->buf_epsP_tilt_fx[i] = 0; + move16(); + hSpMusClas->buf_cor_map_sum_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal2_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal_lf_fx[i] = 0; + move16(); + } + + set16_fx( hSpMusClas->lpe_buf_fx, 0, HANG_LEN_INIT ); + set16_fx( hSpMusClas->voicing_buf_fx, 0, HANG_LEN_INIT ); + hSpMusClas->gsc_hangover = 0; + move16(); + set16_fx( hSpMusClas->sparse_buf_fx, 0, HANG_LEN_INIT ); + set16_fx( hSpMusClas->hf_spar_buf_fx, 0, HANG_LEN_INIT ); + hSpMusClas->LT_sparse_fx = 0; + move16(); + hSpMusClas->gsc_cnt = 0; + move16(); + hSpMusClas->last_vad_spa = 0; + move16(); + + set16_fx( hSpMusClas->old_Bin_E_fx, 0, 3 * N_OLD_BIN_E ); + set16_fx( hSpMusClas->buf_etot_fx, 0, 4 ); + set16_fx( hSpMusClas->buf_dlp_fx, 0, 10 ); + + hSpMusClas->UV_cnt1 = 300; + move16(); + hSpMusClas->LT_UV_cnt1_fx = 16000; /* 250.0f in Q6 */ + move16(); + hSpMusClas->onset_cnt = 0; + move16(); + hSpMusClas->attack_hangover = 0; + move16(); + hSpMusClas->dec_mov_fx = 0; + move16(); + hSpMusClas->dec_mov1_fx = 0; + move16(); + hSpMusClas->mov_log_max_spl_fx = 25600; /* 200.0 in Q7 */ + move16(); + hSpMusClas->old_lt_diff_fx[0] = 0; + move16(); + hSpMusClas->old_lt_diff_fx[1] = 0; + move16(); + + set32_fx( hSpMusClas->finc_prev_fx, 0, ATT_NSEG ); + hSpMusClas->lt_finc_fx = 0; + move32(); + hSpMusClas->last_strong_attack = 0; + move16(); + hSpMusClas->tdm_lt_Etot_fx = 3; /* 0.01f in Q8 */ + move16(); + set32_fx( hSpMusClas->tod_lt_Bin_E_fx, 0, TOD_NSPEC ); + set32_fx( hSpMusClas->tod_S_map_lt_fx, 0, TOD_NSPEC ); + hSpMusClas->tod_thr_lt_fx = TOD_THR_MASS_FX_Q22; + move32(); + hSpMusClas->tod_weight_fx = 0; + move16(); + hSpMusClas->tod_S_mass_prev_fx = 0; + move32(); + hSpMusClas->tod_S_mass_lt_fx = 0; + move32(); + + /* speech/music classification */ + set16_fx( hSpMusClas->lt_old_mode, 1, 3 ); + hSpMusClas->lt_voicing = 16384; /* 0.5f in Q15 */ + move16(); + hSpMusClas->lt_corr = 16384; /* 0.5f in Q15 */ + move16(); + hSpMusClas->lt_tonality = 0; + move32(); + set16_fx( hSpMusClas->lt_corr_pitch, 0, 3 ); + hSpMusClas->lt_hangover = 0; + move16(); + hSpMusClas->lowrate_pitchGain = 0; + move16(); + + hSpMusClas->lt_music_hangover = 0; + move16(); + set16_fx( hSpMusClas->tonality2_buf_fx, 0, HANG_LEN_INIT ); + set16_fx( hSpMusClas->tonality3_buf_fx, 0, HANG_LEN_INIT ); + set16_fx( hSpMusClas->LPCErr_buf_fx, 0, HANG_LEN_INIT ); + hSpMusClas->lt_music_state = 0; + move16(); + hSpMusClas->lt_speech_state = 0; + move16(); + hSpMusClas->lt_speech_hangover = 0; + move16(); + + hSpMusClas->lt_dec_thres_fx = 5120; /* 10.0f in Q9 */ + move16(); + hSpMusClas->ener_RAT_fx = 0; + move16(); + + hSpMusClas->high_stable_cor = 0; + move16(); + set16_fx( hSpMusClas->var_cor_t_fx, 0, VAR_COR_LEN ); + + hSpMusClas->lps_fx = 0; + move16(); + hSpMusClas->lpm_fx = 0; + move16(); + hSpMusClas->lpn_fx = 0; + move16(); + + return; +} + /*---------------------------------------------------------------------* * speech_music_classif() * @@ -1503,6 +1725,7 @@ static Word16 attack_det_fx( /* o : attack flag return attack; } + #ifdef IVAS_FLOAT_FIXED /* -------------------------------------------------------------------- - * *ivas_smc_gmm() @@ -1571,7 +1794,7 @@ Word16 ivas_smc_gmm_fx( IF( localVAD_HE_SAD ) { test(); - IF( LT_16( relE_fx, -10240 ) ) + IF( LT_16( relE_fx, -5120 /*20 q8*/ ) ) { IF( hSpMusClas->sp_mus_state > 0 ) { @@ -1655,11 +1878,12 @@ Word16 ivas_smc_gmm_fx( /* detect attacks based on relE */ IF( GT_16( relE_fx, hSpMusClas->prev_relE_fx ) ) { - hSpMusClas->relE_attack_sum_fx = add_sat( sub_sat( relE_fx, hSpMusClas->prev_relE_fx ), hSpMusClas->relE_attack_sum_fx ); + hSpMusClas->relE_attack_sum_fx = add_sat( sub_sat( relE_fx, hSpMusClas->prev_relE_fx ), hSpMusClas->relE_attack_sum_fx ); /*q8*/ + move16(); } ELSE { - hSpMusClas->relE_attack_sum_fx = 0; + hSpMusClas->relE_attack_sum_fx = 0; /*q8*/ move16(); } hSpMusClas->prev_relE_fx = relE_fx; @@ -1686,7 +1910,7 @@ Word16 ivas_smc_gmm_fx( move16(); test(); test(); - IF( hSpMusClas->sp_mus_state > 0 && LT_16( hSpMusClas->sp_mus_state, HANG_LEN ) && GT_16( hSpMusClas->relE_attack_sum_fx, 2560 ) ) + IF( hSpMusClas->sp_mus_state > 0 && LT_16( hSpMusClas->sp_mus_state, HANG_LEN ) && GT_16( hSpMusClas->relE_attack_sum_fx, 1280 /*q8*/ ) ) { hSpMusClas->relE_attack_cnt = add( hSpMusClas->relE_attack_cnt, 1 ); @@ -1710,6 +1934,7 @@ Word16 ivas_smc_gmm_fx( } hSpMusClas->prev_Etot_fx = Etot_fx; + move16(); /*------------------------------------------------------------------* * Preparation of the feature vector @@ -1728,18 +1953,21 @@ Word16 ivas_smc_gmm_fx( // *pFV_fx++ = (float) ( st->pitch[0] + st->pitch[1] + st->pitch[2] ) / 3.0f; *pFV_fx++ = Mpy_32_32( L_shl( add( add( st->pitch[0], st->pitch[1] ), st->pitch[2] ), Q20 ), 715827883 ); } + move32(); + test(); test(); /* [1] voicing */ IF( relE_attack_flag || EQ_16( st->tc_cnt, 1 ) || EQ_16( st->tc_cnt, 2 ) ) { - *pFV_fx++ = st->voicing_fx[2]; + *pFV_fx++ = L_shl( st->voicing_fx[2], 5 ); /*q20*/ } ELSE { // *pFV++ = ( st->voicing[0] + st->voicing[1] + st->voicing[2] ) / 3.0f; - *pFV_fx++ = Mpy_32_32( L_shl( L_add( L_add( st->voicing_fx[0], st->voicing_fx[1] ), st->voicing_fx[2] ), Q5 ), 715827883 ); + *pFV_fx++ = Mpy_32_32( L_shl( L_add( L_add( st->voicing_fx[0], st->voicing_fx[1] ), st->voicing_fx[2] ), Q5 ), 715827883 ); /*q20*/ } + move32(); temp_exp = 1; move16(); @@ -1791,22 +2019,25 @@ Word16 ivas_smc_gmm_fx( /* [7] cor_map_sum */ *pFV_fx++ = L_shl( cor_map_sum_fx, Q12 ); + move32(); /* [8] non_sta */ - *pFV_fx++ = L_shl( non_sta_fx, Q12 ); + *pFV_fx++ = L_shl( non_sta_fx, Q14 ); /*scaling from 6 to 20*/ + move32(); /* [9] epsP */ - temp32 = epsP_fx[14]; + temp32 = L_add( epsP_fx[14], L_shr( 21475, sub( 31, Q_esp ) ) ); move32(); temp32_log = L_add( BASOP_Util_Log2( temp32 ), L_shl( sub( Q31, Q_esp ), Q25 ) ); temp32_log1 = Mpy_32_32( temp32_log, 1488522239 ); /*logf(x) = log2(x)*logf(2)*/ - temp32 = epsP_fx[0]; + temp32 = L_add( epsP_fx[0], L_shr( 21475, sub( 31, Q_esp ) ) ); move32(); temp32_log = L_add( BASOP_Util_Log2( temp32 ), L_shl( sub( Q31, Q_esp ), Q25 ) ); temp32_log2 = Mpy_32_32( temp32_log, 1488522239 ); /*logf(x) = log2(x)*logf(2)*/ - *pFV_fx++ = L_shr( L_add( temp32_log1, temp32_log2 ), Q5 ); + *pFV_fx++ = L_shr( L_sub( temp32_log1, temp32_log2 ), Q5 ); + move32(); //*pFV++ = logf( epsP[14] + 1e-5f ) - logf( epsP[0] + 1e-5f ); /* [10,11,12] MFCCs */ @@ -1822,7 +2053,13 @@ Word16 ivas_smc_gmm_fx( len = mel_fb_len[i]; move16(); temp32 = dotp_me_fx( &PS_fx[j], pt_mel_fb_fx, len, 31 - Qfact_PS, Q1, &dotp_exp ); - temp32_log = L_add( BASOP_Util_Log2( temp32 ), L_shl( dotp_exp, Q25 ) ); + IF( LT_16( dotp_exp, -17 ) ) /*-18 is exponent of 10737:to avoid overflow when left shifting 10737*/ + { + temp32 = L_shr( temp32, sub( -17, dotp_exp ) ); + dotp_exp = -17; + move16(); + } + temp32_log = L_add( BASOP_Util_Log2( L_add( L_shr( temp32, 1 ), L_shr( 10737 /*1e-5f q30*/, dotp_exp ) ) ), L_shl( add( dotp_exp, 1 ), Q25 ) ); temp32_log = Mpy_32_32( temp32_log, 1488522239 ); /*logf(x) = log2(x)*logf(2)*/ melS_fx[i] = temp32_log; move32(); @@ -1867,6 +2104,7 @@ Word16 ivas_smc_gmm_fx( } *pFV_fx++ = L_shr( ps_diff_fx, sub( sub( Qfact_PS_past, Q7 ), Q20 ) ); /// ps_diff; + move32(); /* [14] ps_sta (spectral stationarity) */ ps_sta_fx = 0; @@ -1877,20 +2115,22 @@ Word16 ivas_smc_gmm_fx( { IF( GT_32( PS_norm_fx[i], hSpMusClas->past_PS_fx[i - LOWEST_FBIN] ) ) { - temp32 = L_deposit_h( BASOP_Util_Divide3232_Scale( PS_norm_fx[i], ( dPS_fx[i] + 1 ), &temp_exp ) ); // 31-temp_exp + temp32 = BASOP_Util_Divide3232_Scale_cadence( PS_norm_fx[i], ( L_add( dPS_fx[i], L_shr( 21475, sub( 31, Qfact_PS_past ) ) ) ), &temp_exp ); // 31-temp_exp ps_sta_fx = BASOP_Util_Add_Mant32Exp( temp32, temp_exp, ps_sta_fx, ps_sta_exp, &ps_sta_exp ); } ELSE { // ps_sta += hSpMusClas->past_PS[i - LOWEST_FBIN] / ( dPS[i] + 1e-5f ); - temp32 = L_deposit_h( BASOP_Util_Divide3232_Scale( hSpMusClas->past_PS_fx[i - LOWEST_FBIN], ( dPS_fx[i] + 1 ), &temp_exp ) ); // 31-temp_exp + temp32 = BASOP_Util_Divide3232_Scale_cadence( hSpMusClas->past_PS_fx[i - LOWEST_FBIN], ( L_add( dPS_fx[i], L_shr( 21475, sub( 31, Qfact_PS_past ) ) ) ), &temp_exp ); // 31-temp_exp move32(); ps_sta_fx = BASOP_Util_Add_Mant32Exp( temp32, temp_exp, ps_sta_fx, ps_sta_exp, &ps_sta_exp ); } } - temp32_log = L_add( BASOP_Util_Log2( ps_sta_fx ), L_shl( ps_sta_exp, Q25 ) ); + // temp32_log = L_add( BASOP_Util_Log2( L_add( ps_sta_fx, L_shr( 21475, ps_sta_exp ) ) ), L_shl( ps_sta_exp, Q25 ) ); + temp32_log = L_add( BASOP_Util_Log2( L_add_sat( ps_sta_fx, L_shr( 21475, ps_sta_exp ) ) ), L_shl( ps_sta_exp, Q25 ) ); temp32_log = Mpy_32_32( temp32_log, 1488522239 ); /*logf(x) = log2(x)*logf(2)*/ *pFV_fx++ = L_shr( temp32_log, Q5 ); // logf( ps_sta + 1e-5f ); + move32(); MVR2R_WORD32( &PS_norm_fx[LOWEST_FBIN], hSpMusClas->past_PS_fx, HIGHEST_FBIN - LOWEST_FBIN ); /* save ps_diff and ps_sta features for XTALK and UNCLR classifier */ @@ -1898,16 +2138,22 @@ Word16 ivas_smc_gmm_fx( { IF( st->idchan == 0 ) { - hStereoClassif->ps_diff_ch1_fx = ps_diff_fx; // Qfact_PS_past - 7 - hStereoClassif->ps_sta_ch1_fx = temp32_log; // logf( ps_sta + 1e-5f );Q25 + hStereoClassif->ps_diff_ch1_fx = ps_diff_fx; // Qfact_PS_past - 7 + hStereoClassif->ps_diff_ch1_e = sub( 38, Qfact_PS_past ); // Qfact_PS_past - 7 + hStereoClassif->ps_sta_ch1_fx = temp32_log; // logf( ps_sta + 1e-5f );Q25 + hStereoClassif->ps_sta_ch1_e = 6; // logf( ps_sta + 1e-5f );Q25 } ELSE { hStereoClassif->ps_diff_ch2_fx = ps_diff_fx; + hStereoClassif->ps_diff_ch2_e = sub( 38, Qfact_PS_past ); hStereoClassif->ps_sta_ch2_fx = temp32_log; // logf( ps_sta + 1e-5f );Q25 + hStereoClassif->ps_sta_ch2_e = 6; // logf( ps_sta + 1e-5f );Q25 } move32(); move32(); + move16(); + move16(); } /*------------------------------------------------------------------* @@ -2056,25 +2302,41 @@ Word16 ivas_smc_gmm_fx( move32(); FOR( m = 0; m < N_SMC_MIXTURES; m++ ) { - v_sub32_fx( FV_fx, &means_speech_fx[m * N_PCA_COEF], fvm_fx, N_PCA_COEF ); + Word32 temp[N_PCA_COEF]; + FOR( Word16 ind = 0; ind < N_PCA_COEF; ind++ ) + { + temp[ind] = L_shr( means_speech_fx[m * N_PCA_COEF + ind], sub( 27, Qfact_FV ) ); + move32(); + } + v_sub32_fx( FV_fx, temp, fvm_fx, N_PCA_COEF ); fvm_exp = sub( 31, Qfact_FV ); lprob_exp = 0; move16(); lprob_fx = dot_product_cholesky_fixed( fvm_fx, &prec_chol_speech_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF, fvm_exp, 31 - 28, &lprob_exp ); - ps_fx[m] = L_sub( log_weights_speech_compute[m], L_shr( L_shl_sat( lprob_fx, sub( Q19, sub( Q31, lprob_exp ) ) ), 1 ) ); + ps_fx[m] = L_sub( log_weights_speech_compute[m], L_shl( lprob_fx, sub( Q19 - 1, sub( Q31, lprob_exp ) ) ) ); move32(); - v_sub32_fx( FV_fx, &means_music_fx[m * N_PCA_COEF], fvm_fx, N_PCA_COEF ); + FOR( Word16 ind = 0; ind < N_PCA_COEF; ind++ ) + { + temp[ind] = L_shr( means_music_fx[m * N_PCA_COEF + ind], sub( 27, Qfact_FV ) ); + move32(); + } + v_sub32_fx( FV_fx, temp, fvm_fx, N_PCA_COEF ); lprob_exp = 0; move16(); lprob_fx = dot_product_cholesky_fixed( fvm_fx, &prec_chol_music_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF, fvm_exp, 31 - 28, &lprob_exp ); - pm_fx[m] = L_sub( log_weights_music_compute[m], L_shr( L_shl_sat( lprob_fx, sub( Q19, sub( Q31, lprob_exp ) ) ), 1 ) ); + pm_fx[m] = L_sub( log_weights_music_compute[m], L_shl( lprob_fx, sub( Q19 - 1, sub( Q31, lprob_exp ) ) ) ); move32(); - v_sub32_fx( FV_fx, &means_noise_fx[m * N_PCA_COEF], fvm_fx, N_PCA_COEF ); + FOR( Word16 ind = 0; ind < N_PCA_COEF; ind++ ) + { + temp[ind] = L_shr( means_noise_fx[m * N_PCA_COEF + ind], sub( 27, Qfact_FV ) ); + move32(); + } + v_sub32_fx( FV_fx, temp, fvm_fx, N_PCA_COEF ); lprob_exp = 0; move16(); lprob_fx = dot_product_cholesky_fixed( fvm_fx, &prec_chol_noise_fx[m * ( N_PCA_COEF * N_PCA_COEF + N_PCA_COEF ) / 2], N_PCA_COEF, fvm_exp, 31 - 28, &lprob_exp ); - pn_fx[m] = L_sub( log_weights_music_compute[m], L_shr( L_shl_sat( lprob_fx, sub( Q19, sub( Q31, lprob_exp ) ) ), 1 ) ); + pn_fx[m] = L_sub( log_weights_noise_compute[m], L_shl( lprob_fx, sub( Q19 - 1, sub( Q31, lprob_exp ) ) ) ); move32(); } @@ -2089,9 +2351,9 @@ Word16 ivas_smc_gmm_fx( move32(); } - hSpMusClas->lpm_fx = extract_l( L_shr( lpm_fx, 11 ) ); // Q8 - hSpMusClas->lps_fx = extract_l( L_shr( lps_fx, 11 ) ); // Q8 - hSpMusClas->lpn_fx = extract_l( L_shr( lpn_fx, 11 ) ); // Q8 + hSpMusClas->lpm_fx = extract_l( L_shr( lpm_fx, 12 ) ); // Q7 + hSpMusClas->lps_fx = extract_l( L_shr( lps_fx, 12 ) ); // Q7 + hSpMusClas->lpn_fx = extract_l( L_shr( lpn_fx, 12 ) ); // Q7 /* determine HQ Generic speech class */ IF( st->hHQ_core != NULL ) @@ -2140,13 +2402,13 @@ Word16 ivas_smc_gmm_fx( dec = (Word16) GT_32( dlp_fx, 0 ); /* calculate weight based on relE (higher relE -> lower weight, lower relE -> higher weight) */ - Word16 Qio = Q25; + Word16 Qio = Q24; move16(); - wrelE_fx = lin_interp32_fx( L_deposit_h( relE_fx ), 503316480, 30198989, -503316480, 33218888, 1, &Qio ); // Q25 + wrelE_fx = lin_interp32_fx( L_deposit_h( relE_fx ), 15 << 24, 15099494 /*0.9 q24*/, -( 15 << 24 ), 16609443 /*0.99 q24*/, 1, &Qio ); // Q25 wrelE_fx = L_shr( wrelE_fx, sub( Qio, 25 ) ); /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ // hSpMusClas->dlp_mean_ST = 0.8f * hSpMusClas->dlp_mean_ST + 0.2f * dlp; - hSpMusClas->dlp_mean_ST_fx = L_add( Mpy_32_32( 419430, hSpMusClas->dlp_mean_ST_fx ), Mpy_32_32( 104858, dlp_fx ) ); + hSpMusClas->dlp_mean_ST_fx = L_add( Mpy_32_32( 1717986918, hSpMusClas->dlp_mean_ST_fx ), Mpy_32_32( 429496729, dlp_fx ) ); hSpMusClas->lt_dec_thres_fx = extract_l( L_shr( hSpMusClas->dlp_mean_ST_fx, 10 ) ); test(); IF( dlp_fx < 0 && LT_32( dlp_fx, hSpMusClas->dlp_mean_ST_fx ) ) @@ -2199,7 +2461,7 @@ Word16 ivas_smc_gmm_fx( wght_fx = Mpy_32_32( Mpy_32_32( wrelE_fx, wdrop_fx ), wrise_fx ); // Q13 test(); /* ratio of delta means vs. delta variances */ - if ( hSpMusClas->sp_mus_state > 0 && LT_16( hSpMusClas->sp_mus_state, HANG_LEN ) ) + IF( hSpMusClas->sp_mus_state > 0 && LT_16( hSpMusClas->sp_mus_state, HANG_LEN ) ) { hSpMusClas->dlp_mean_LT_fx = dlp_fx; @@ -2211,6 +2473,7 @@ Word16 ivas_smc_gmm_fx( hSpMusClas->dlp_mean_LT_fx = L_add( Mpy_32_32( 1932735283, hSpMusClas->dlp_mean_LT_fx ), Mpy_32_32( 214748365, dlp_fx ) ); // Q19 temp32 = L_sub( dlp_fx, hSpMusClas->dlp_mean_LT_fx ); + temp32 = W_extract_l( W_shr( W_mult0_32_32( temp32, temp32 ), 19 ) ); /*q19*/ hSpMusClas->dlp_var_LT_fx = L_add( Mpy_32_32( 1932735283, hSpMusClas->dlp_var_LT_fx ), Mpy_32_32( 214748365, temp32 ) ); test(); @@ -2226,13 +2489,27 @@ Word16 ivas_smc_gmm_fx( temp_exp = sub( Q31, Q19 ); Word16 div_e = 0; move16(); - temp32 = Sqrt32( L_abs( hSpMusClas->dlp_var_LT_fx ), &temp_exp ); - temp_sqrt = L_add( Sqrt32( L_abs( hSpMusClas->dlp_var_LT_fx ), &temp_exp ), 1 ); + temp_sqrt = Sqrt32( L_abs( hSpMusClas->dlp_var_LT_fx ), &temp_exp ); + IF( temp_exp < 0 ) + { + temp_sqrt = L_shl( temp_sqrt, temp_exp ); + temp_exp = 0; + move16(); + } + temp_sqrt = L_shr( temp_sqrt, 1 ); /*adding 1 as guard bit to avoid overflow in addition*/ + temp_exp = add( temp_exp, 1 ); + temp_sqrt = L_add( temp_sqrt, L_shl( 1, sub( 31, temp_exp ) ) ); dlp_mean2var_fx = BASOP_Util_Divide3232_Scale( L_abs( hSpMusClas->dlp_mean_LT_fx ), temp_sqrt, &div_e ); dlp_mean2var_q = sub( add( Q3, temp_exp ), div_e ); // 15-div_e+Q19 -(31-temp_exp) + IF( GT_16( dlp_mean2var_q, 26 ) ) + { + dlp_mean2var_fx = shl( dlp_mean2var_fx, sub( 26, dlp_mean2var_q ) ); + dlp_mean2var_q = 26; + move16(); + } } - if ( GT_32( L_deposit_l( dlp_mean2var_fx ), L_shl( 15, dlp_mean2var_q ) ) ) + IF( GT_32( L_deposit_l( dlp_mean2var_fx ), L_shl( 15, dlp_mean2var_q ) ) ) { /* decrease the weight little bit when the classifier indicates "strong speech" or "strong music" */ // wght *= 0.9f; @@ -2248,7 +2525,7 @@ Word16 ivas_smc_gmm_fx( wght_fx = 82; } move32(); - if ( LT_16( Etot_fx, 256 ) ) + if ( LT_16( Etot_fx, 2560 ) ) { /* silence */ wght_fx = 7537; @@ -2257,8 +2534,8 @@ Word16 ivas_smc_gmm_fx( /* calculate weighted decision */ // hSpMusClas->wdlp_0_95_sp = wght * hSpMusClas->wdlp_0_95_sp + ( 1 - wght ) * dlp; - - hSpMusClas->wdlp_0_95_sp_fx = (Word16) L_add( L_shl( Mpy_32_16_1( wght_fx, hSpMusClas->wdlp_0_95_sp_fx ), Q2 ), L_shl( Mpy_32_32( L_sub( ONE_IN_Q13, wght_fx ), dlp_fx ), Q5 ) ); // Q8 + hSpMusClas->wdlp_0_95_sp_32fx = L_add( Mpy_32_32( L_shl( wght_fx /*q13*/, 18 ), hSpMusClas->wdlp_0_95_sp_32fx /*q24*/ ), Mpy_32_32( L_shl( L_sub( ONE_IN_Q13, wght_fx /*q13*/ ), Q18 ), L_shl( dlp_fx /*q19*/, 5 ) ) ); // Q24 + move32(); /* xtalk classifier: apply long hysteresis to prevent LRTD on music */ @@ -2325,27 +2602,27 @@ Word16 ivas_smc_gmm_fx( test(); /* stable active state */ IF( hSpMusClas->past_dec[0] == 0 && hSpMusClas->past_dec[1] == 0 && hSpMusClas->past_dec[2] == 0 && - ( ( hSpMusClas->flag_spitch_cnt > 0 && GT_16( hSpMusClas->wdlp_0_95_sp_fx, 870 ) ) || ( hSpMusClas->flag_spitch_cnt == 0 && GT_16( hSpMusClas->wdlp_0_95_sp_fx, 538 ) ) ) ) + ( ( hSpMusClas->flag_spitch_cnt > 0 && GT_32( hSpMusClas->wdlp_0_95_sp_32fx, 57042534 /*3.4*(2^24)*/ ) ) || ( hSpMusClas->flag_spitch_cnt == 0 && GT_32( hSpMusClas->wdlp_0_95_sp_32fx, 35232154 /*2.1*(2^24)*/ ) ) ) ) { /* switching from speech to unclear */ dec = 1; } - ELSE IF( hSpMusClas->past_dec[0] == 0 && LT_16( hSpMusClas->vad_0_1_cnt, 50 ) && hSpMusClas->relE_attack_sum_fx == 0 && GT_16( hSpMusClas->wdlp_0_95_sp_fx, 256 ) ) + ELSE IF( hSpMusClas->past_dec[0] == 0 && LT_16( hSpMusClas->vad_0_1_cnt, 50 ) && hSpMusClas->relE_attack_sum_fx == 0 && GT_32( hSpMusClas->wdlp_0_95_sp_32fx, 1 << 24 ) ) { /* switch from speech to unclear also during slowly rising weak music onsets */ dec = 1; } - ELSE IF( EQ_16( hSpMusClas->past_dec[0], 1 ) && GT_16( hSpMusClas->wdlp_0_95_sp_fx, 640 ) ) + ELSE IF( EQ_16( hSpMusClas->past_dec[0], 1 ) && GT_32( hSpMusClas->wdlp_0_95_sp_32fx, 41943040 /*2.5*2^24*/ ) ) { /* switching from unclear to music */ dec = 2; } - ELSE IF( EQ_16( hSpMusClas->past_dec[0], 2 ) && EQ_16( hSpMusClas->past_dec[1], 2 ) && EQ_16( hSpMusClas->past_dec[2], 2 ) && LT_16( hSpMusClas->wdlp_0_95_sp_fx, -256 ) ) + ELSE IF( EQ_16( hSpMusClas->past_dec[0], 2 ) && EQ_16( hSpMusClas->past_dec[1], 2 ) && EQ_16( hSpMusClas->past_dec[2], 2 ) && LT_32( hSpMusClas->wdlp_0_95_sp_32fx, -( 1 << 24 ) ) ) { /* switching from music to unclear */ dec = 1; } - ELSE IF( EQ_16( hSpMusClas->past_dec[0], 1 ) && LT_16( hSpMusClas->wdlp_0_95_sp_fx, -640 ) ) + ELSE IF( EQ_16( hSpMusClas->past_dec[0], 1 ) && LT_32( hSpMusClas->wdlp_0_95_sp_32fx, -( 41943040 /*2.5*2^24*/ ) ) ) { /* switching from unclear to speech */ dec = 0; @@ -2394,248 +2671,628 @@ Word16 ivas_smc_gmm_fx( return dec; } + #endif -#ifdef IVAS_CODE +#ifdef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* - * ivas_smc_mode_selection() + * var_cor_calc_ivas_fx() * - * 2nd stage speech/music classifier (select coding mode (ACELP, GSC and TCX) based on S/M classification) - * output (sp_aud_decision1 - sp_aud_decision2 -> coding mode): - * 0 - 0 -> ACELP - * 1 - 0 -> GSC - * 1 - 1 -> TCX + * Calculate variance of correlation *---------------------------------------------------------------------*/ -void ivas_smc_mode_selection( - Encoder_State *st, /* i/o: encoder state structure */ - const int32_t element_brate, /* i : element bitrate */ - int16_t smc_dec, /* i : raw decision of the 1st stage classifier*/ - const float relE, /* i : relative frame energy */ - const float Etot, /* i : total frame energy */ - int16_t *attack_flag, /* i/o: attack flag (GSC or TC) */ - const float *inp, /* i : input signal */ - const float S_map[], /* i : short-term correlation map */ - const int16_t flag_spitch /* i : flag to indicate very short stable pitch*/ -) +static void var_cor_calc_ivas_fx( + const Word16 old_corr, /* Q15 */ + Word16 *mold_corr, /* Q15 */ + Word16 var_cor_t[], /* Q11 */ + Word16 *high_stable_cor ) { - int16_t attack; - float ton; - int16_t i; - float S_p2a, S_max, S_ave; - float thr_sp2a; - - SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; - - /* initialization */ - *attack_flag = 0; - st->sp_aud_decision2 = 0; + Word16 i, var_cor; - /* signal stability estimation */ - stab_est( Etot, hSpMusClas->gsc_lt_diff_etot, &hSpMusClas->gsc_mem_etot, &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres, &hSpMusClas->gsc_last_music_flag, st->vad_flag ); + /* update buffer of old correlation values */ + FOR( i = VAR_COR_LEN - 1; i > 0; i-- ) + { + var_cor_t[i] = var_cor_t[i - 1]; /*Q11*/ + move16(); + } + var_cor_t[i] = shr( old_corr, 4 ); /* Q11 */ + move16(); /* calculate variance of correlation */ - var_cor_calc( st->old_corr, &hSpMusClas->mold_corr, hSpMusClas->var_cor_t, &hSpMusClas->high_stable_cor ); - - /* attack detection */ - attack = attack_det( inp, st->clas, st->localVAD, st->coder_type, 0, st->element_mode, st->clas, hSpMusClas->finc_prev, &hSpMusClas->lt_finc, &hSpMusClas->last_strong_attack ); - - /* tonal detector */ - ton = tonal_det( S_map, st->vad_flag, hSpMusClas->tod_S_map_lt, &hSpMusClas->tod_thr_lt, &hSpMusClas->tod_weight, &hSpMusClas->tod_S_mass_prev, &hSpMusClas->tod_S_mass_lt ); - + var_cor = var_fx( var_cor_t, 11, VAR_COR_LEN ); - /* calculate spectral peak-to-average ratio */ - for ( i = 0; i < TOD_NSPEC; i++ ) + *high_stable_cor = 0; + move16(); + test(); + IF( GT_16( *mold_corr, 26214 ) && LT_16( var_cor, 1 ) ) { - st->hSpMusClas->tod_lt_Bin_E[i] = P2A_FACT * st->hSpMusClas->tod_lt_Bin_E[i] + ( 1 - P2A_FACT ) * st->Bin_E[i]; + *high_stable_cor = 1; + move16(); } - maximum( st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC, &S_max ); - S_ave = sum_f( st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC ) / TOD_NSPEC; - S_p2a = S_max - S_ave; - - - thr_sp2a = THR_P2A; - if ( element_brate <= IVAS_16k4 ) + /* update average correlation */ + /*st->mold_corr = 0.1f * st->old_corr + 0.9f * st->mold_corr;*/ + *mold_corr = mac_r( L_mult( 3277, old_corr ), 29491, *mold_corr ); /*Q15 */ + move16(); + + return; +} + +/*---------------------------------------------------------------------* + * attack_det_fx() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static Word16 attack_det_ivas_fx( /* o : attack flag */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx, + const Word16 last_clas, /* i : last signal clas */ + const Word16 localVAD, /* i : local VAD flag */ + const Word16 coder_type, /* i : coder type */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 clas, /* i : signal class */ + Word32 finc_prev[], /* i/o: previous finc, (2 * Qx) */ + Word32 *lt_finc, /* i/o: long-term mean finc, (2 * Qx) */ + Word16 *last_strong_attack /* i/o: last strong attack flag */ +) +{ + Word16 i, j, tmp, tmp1, attack, exp1; + Word32 L_tmp, etmp, etmp2, finc[ATT_NSEG], mean_finc; + Word16 att_3lsub_pos; + Word16 attack1; + Word64 W_tmp = 0; + move64(); + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + att_3lsub_pos = ATT_3LSUB_POS; + move16(); + if ( GE_32( total_brate, ACELP_24k40 ) ) + { + att_3lsub_pos = ATT_3LSUB_POS_16k; + move16(); + } + + /* compute energy per section */ + FOR( i = 0; i < ATT_NSEG; i++ ) { - thr_sp2a = THR_P2A_HIGH; + L_tmp = L_mult0( inp[i * ATT_SEG_LEN], inp[i * ATT_SEG_LEN] ); /*2*Qx */ + + FOR( j = 1; j < ATT_SEG_LEN; j++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_mac0_o( L_tmp, inp[i * ATT_SEG_LEN + j], inp[i * ATT_SEG_LEN + j], &Overflow ); /*2*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_mac0( L_tmp, inp[i * ATT_SEG_LEN + j], inp[i * ATT_SEG_LEN + j] ); /*2*Qx */ +#endif /* BASOP_NOGLOB */ + } + + finc[i] = L_tmp; + move32(); + } + + attack = maximum_32_fx( finc, ATT_NSEG, &etmp ); + attack1 = attack; + move16(); + + test(); + IF( EQ_16( localVAD, 1 ) && EQ_16( coder_type, GENERIC ) ) + { + /*----------------------------------------------------------------------* + * Detect if there is a strong onset in the last subframe + * - if detected, TC is used to better code the onset + *----------------------------------------------------------------------*/ + + /* compute mean energy in the first three subframes */ + exp1 = norm_s( att_3lsub_pos ); + tmp = div_s( shl( 1, sub( 14, exp1 ) ), att_3lsub_pos ); /*Q(29-exp1) */ + +#ifdef BASOP_NOGLOB + L_tmp = L_shr_o( finc[0], Qx, &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shr( finc[0], Qx ); /*Qx */ +#endif /* BASOP_NOGLOB */ + + FOR( i = 1; i < att_3lsub_pos; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_add_o( L_tmp, L_shr_o( finc[i], Qx, &Overflow ), &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_add( L_tmp, L_shr( finc[i], Qx ) ); /*Qx */ +#endif /* BASOP_NOGLOB */ + } + L_tmp = Mult_32_16( L_tmp, tmp ); /*Q(14-exp1+Qx) */ + etmp = L_shl( L_tmp, sub( exp1, 14 ) ); /*Qx */ + + tmp1 = sub( ATT_NSEG, attack ); + exp1 = norm_s( tmp1 ); + tmp = div_s( shl( 1, sub( 14, exp1 ) ), tmp1 ); /*Q(29-exp1) */ + +#ifdef BASOP_NOGLOB + L_tmp = L_shr_o( finc[attack], Qx, &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shr( finc[attack], Qx ); /*Qx */ +#endif /* BASOP_NOGLOB */ + FOR( i = 1; i < tmp1; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_add_o( L_tmp, L_shr_o( finc[i + attack], Qx, &Overflow ), &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_add( L_tmp, L_shr( finc[i + attack], Qx ) ); /*Qx */ +#endif /* BASOP_NOGLOB */ + } + L_tmp = Mult_32_16( L_tmp, tmp ); /*Q(14-exp1+Qx) */ + etmp2 = L_shl( L_tmp, sub( exp1, 14 ) ); /*Qx */ + + /* and compare them */ + if ( GT_32( etmp, L_shr( etmp2, 3 ) ) ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + move16(); + } + + test(); + if ( EQ_16( last_clas, VOICED_CLAS ) && GT_32( L_add( L_shl( etmp, 4 ), L_shl( etmp, 2 ) ), etmp2 ) ) + { + /* stop, if the signal was voiced and the attack is not sufficiently strong */ + attack = 0; + move16(); + } + + /* compare also wrt. other sections (reduces a misclassification) */ + IF( attack > 0 ) + { + etmp2 = L_add( finc[attack], 0 ); + etmp = Mult_32_16( etmp2, 16384 ); /* etmp2 / 2.0 = (etmp2*0.5) */ + FOR( i = 2; i < ATT_3LSUB_POS - 2; i++ ) + { + IF( GT_32( finc[i], etmp ) ) + { + attack = 0; + move16(); + BREAK; + } + } + } + + test(); + test(); + test(); + IF( attack == 0 && GT_16( element_mode, EVS_MONO ) && ( LT_16( clas, VOICED_TRANSITION ) || EQ_16( clas, ONSET ) ) ) + { + Copy32( finc, finc_prev, attack1 ); + + /* compute mean energy before the attack */ + etmp = L_shr( sum32_fx( finc_prev, ATT_NSEG ), 5 ); /*ATT_NSEG == 32*/ + + etmp2 = finc[attack1]; + move32(); + test(); + test(); + if ( ( LT_32( L_shl( etmp, 4 ), etmp2 ) ) || ( LT_32( L_add( L_shl( etmp, 3 ), L_shl( etmp, 2 ) ), etmp2 ) && EQ_16( last_clas, UNVOICED_CLAS ) ) ) + { + attack = attack1; + move16(); + } + test(); + if ( GT_32( *lt_finc, Mpy_32_32( etmp2, 107374182 /* 1.f/20 in Q31 */ ) ) || *last_strong_attack ) + { + attack = 0; + move16(); + } + } + *last_strong_attack = attack; + move16(); + } + ELSE IF( attack > 0 ) + { + etmp2 = L_add( finc[attack], 0 ); + etmp = Mult_32_16( etmp2, 25206 ); /* etmp2 / 1.3 = (etmp2*0.76923) */ + FOR( i = 2; i < att_3lsub_pos - 2; i++ ) + { + /*if( i != attack && finc[i] * 1.3f > etmp2 ) -> finc[i] > (etmp2*0.76923) */ + test(); + IF( NE_16( i, attack ) && GT_32( finc[i], etmp ) ) + { + attack = 0; + move16(); + BREAK; + } + } + *last_strong_attack = 0; + move16(); + } + + /* updates */ + Copy32( finc, finc_prev, ATT_NSEG ); + + /* Calculating mean of finc */ + FOR( i = 0; i < ATT_NSEG; i++ ) + { + W_tmp = W_add( W_tmp, (Word64) finc[i] ); + } + mean_finc = W_extract_l( W_shr( W_tmp, 5 ) ); + + //*lt_finc = 0.95f * *lt_finc + 0.05f * mean( finc, ATT_NSEG ); + *lt_finc = L_add( Mpy_32_32( *lt_finc, 2040109466 /* 0.95 in Q31 */ ), Mpy_32_32( mean_finc, 107374182 /* 0.05f in Q31 */ ) ); + move32(); + + return attack; +} + +/*---------------------------------------------------------------------* + * tonal_det() + * + * Tonal detector based on spectral stability and harmonicity + *---------------------------------------------------------------------*/ + +static Word32 tonal_det_fx( + const Word16 S[], // Q7 + Word16 vad_flag, + Word32 tod_S_map_lt[], // Q22 + Word32 *tod_thr_lt, // Q22 + Word16 *tod_weight, // Q15 + Word32 *tod_S_mass_prev, // Q22 + Word32 *tod_S_mass_lt // Q22 +) +{ + Word16 i; + Word32 S_mass, alpha; + Word32 L_tmp; + Word64 W_tmp; + + /* update the adaptive weight */ + *tod_weight = add( mult( TON_ALPHA_FX, *tod_weight ), imult1616( ( 32767 - TON_ALPHA_FX ), vad_flag ) ); + move16(); + IF( GT_16( *tod_weight, TON_ALPHA_FX ) ) + { + *tod_weight = TON_ALPHA_FX; + move16(); + } + ELSE IF( LT_16( *tod_weight, ( 32767 - TON_ALPHA_FX ) ) ) + { + *tod_weight = 32767 - TON_ALPHA_FX; + move16(); + } + + /* calculate LT spectral correlation in each band up to 4KHz */ + W_tmp = 0; + move64(); + FOR( i = 0; i < TOD_NSPEC; i++ ) + { + tod_S_map_lt[i] = L_add( Mpy_32_16_1( tod_S_map_lt[i], *tod_weight ), L_mult0( sub( 32767, *tod_weight ), S[i] ) ); // Q22 + move16(); + + W_tmp = W_add( W_tmp, (Word64) ( tod_S_map_lt[i] ) ); // Q22 + } + // S_mass /= TOD_NSPEC; + L_tmp = W_extract_l( W_tmp ); // Q22 + S_mass = ( Mpy_32_32( L_tmp, TOD_NSPEC_INV_Q31 ) ); // Q22 + + IF( GT_32( S_mass, *tod_S_mass_prev ) ) + { + alpha = 1503238554; /* 0.7f in Q31 */ + move16(); + } + ELSE + { + alpha = 644245094; /* 0.3f in Q31 */ + move16(); + } + *tod_S_mass_prev = S_mass; + *tod_S_mass_lt = L_add( Mpy_32_32( alpha, *tod_S_mass_lt ), Mpy_32_32( L_sub( ONE_IN_Q31, alpha ), S_mass ) ); // Q22 + S_mass = *tod_S_mass_lt; + move16(); + move16(); + move16(); + + /* updating adaptive decision threshold */ + IF( GT_32( S_mass, *tod_thr_lt ) ) + { + *tod_thr_lt = L_sub( *tod_thr_lt, THR_MASS_STEP_DN_FX ); + move16(); + } + ELSE + { + *tod_thr_lt = L_add( *tod_thr_lt, THR_MASS_STEP_UP_FX ); + move16(); + } + + if ( GT_32( *tod_thr_lt, THR_MASS_MAX_FX ) ) + { + *tod_thr_lt = THR_MASS_MAX_FX; + move16(); + } + + if ( LT_32( *tod_thr_lt, THR_MASS_MIN_FX ) ) + { + *tod_thr_lt = THR_MASS_MIN_FX; + move16(); + } + + return S_mass; /* Q22 */ +} + + +/*---------------------------------------------------------------------* + * ivas_smc_mode_selection() + * + * 2nd stage speech/music classifier (select coding mode (ACELP, GSC and TCX) based on S/M classification) + * output (sp_aud_decision1 - sp_aud_decision2 -> coding mode): + * 0 - 0 -> ACELP + * 1 - 0 -> GSC + * 1 - 1 -> TCX + *---------------------------------------------------------------------*/ + +void ivas_smc_mode_selection_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + Word16 smc_dec, /* i : raw decision of the 1st stage classifier*/ + const Word16 relE, /* i : relative frame energy, Q8 */ + const Word16 Etot, /* i : total frame energy, Q8 */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Q_new, /* i : Q of input signal */ + const Word16 S_map[], /* i : short-term correlation map, Q7 */ + const Word16 flag_spitch /* i : flag to indicate very short stable pitch*/ +) +{ + Word16 attack; + Word32 ton; + Word16 i; + Word32 S_p2a, S_max, S_ave = 0; + Word32 thr_sp2a; + move32(); + + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; + + /* initialization */ + *attack_flag = 0; + st->sp_aud_decision2 = 0; + move16(); + move16(); + + /* signal stability estimation */ + stab_est_fx( Etot, hSpMusClas->gsc_lt_diff_etot_fx, &hSpMusClas->gsc_mem_etot_fx, &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres_fx, &hSpMusClas->gsc_last_music_flag, st->vad_flag ); + + /* calculate variance of correlation */ + var_cor_calc_ivas_fx( st->old_corr_fx, &hSpMusClas->mold_corr_fx, hSpMusClas->var_cor_t_fx, &hSpMusClas->high_stable_cor ); + + /* attack detection */ + attack = attack_det_ivas_fx( inp, Q_new, st->clas, st->localVAD, st->coder_type, 0, st->element_mode, st->clas, hSpMusClas->finc_prev_fx, &hSpMusClas->lt_finc_fx, &hSpMusClas->last_strong_attack ); + + /* tonal detector */ + ton = tonal_det_fx( S_map, st->vad_flag, hSpMusClas->tod_S_map_lt_fx, &hSpMusClas->tod_thr_lt_fx, &hSpMusClas->tod_weight_fx, &hSpMusClas->tod_S_mass_prev_fx, &hSpMusClas->tod_S_mass_lt_fx ); // Q22 + + /* calculate spectral peak-to-average ratio */ + FOR( i = 0; i < TOD_NSPEC; i++ ) + { + // st->hSpMusClas->tod_lt_Bin_E[i] = P2A_FACT * st->hSpMusClas->tod_lt_Bin_E[i] + ( 1 - P2A_FACT ) * st->Bin_E[i]; + st->hSpMusClas->tod_lt_Bin_E_fx[i] = Madd_32_16( Mpy_32_16_1( st->hSpMusClas->tod_lt_Bin_E_fx[i], P2A_FACT_FX_Q15 ), st->Bin_E_fx[i], ( 32767 - P2A_FACT_FX_Q15 ) ); // Q = Q_new + Q_SCALE - 2 + } + + maximum_32_fx( st->hSpMusClas->tod_lt_Bin_E_fx, TOD_NSPEC, &S_max ); + // S_ave = sum_f( st->hSpMusClas->tod_lt_Bin_E_fx, TOD_NSPEC ) / TOD_NSPEC; + FOR( i = 0; i < TOD_NSPEC; i++ ) + { + S_ave = L_add( S_ave, st->hSpMusClas->tod_lt_Bin_E_fx[i] ); + } + S_ave = Mpy_32_32( S_ave, TOD_NSPEC_INV_Q31 ); + + S_p2a = L_sub( S_max, S_ave ); + + IF( LE_32( element_brate, IVAS_16k4 ) ) + { + thr_sp2a = L_shl( THR_P2A_HIGH_FX, add( Q_new, Q_SCALE - 2 ) ); // Q = Q_new + Q_SCALE - 2 + } + ELSE + { + thr_sp2a = L_shl( THR_P2A_FX, add( Q_new, Q_SCALE - 2 ) ); // Q = Q_new + Q_SCALE - 2 } /* initial 3-way selection of coding modes (ACELP/GSC/TCX) */ - if ( relE > -10.0f && ( S_p2a > thr_sp2a || ton > hSpMusClas->tod_thr_lt ) ) + test(); + test(); + IF( GT_16( relE, -2560 /* -10.0f in Q8 */ ) && ( GT_32( S_p2a, thr_sp2a ) || GT_32( ton, hSpMusClas->tod_thr_lt_fx ) ) ) { /* select TCX to encode extremely peaky signals or strongly tonal signals */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 1; + move16(); + move16(); } - else if ( smc_dec == SPEECH ) + ELSE IF( smc_dec == SPEECH ) { /* select ACELP to encode speech */ st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; + move16(); + move16(); } - else if ( smc_dec == SPEECH_OR_MUSIC ) + ELSE IF( EQ_16( smc_dec, SPEECH_OR_MUSIC ) ) { /* select GSC to encode "unclear" segments (classifier's score on the borderline) */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 0; + move16(); + move16(); } - else + ELSE { /* select TCX to encode music */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 1; + move16(); + move16(); } /* change decision from GSC to ACELP/TCX in some special cases */ - if ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) + test(); + IF( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) { - if ( hSpMusClas->ener_RAT < 0.18f && hSpMusClas->lt_dec_thres > 15.0f ) + test(); + test(); + IF( LT_16( hSpMusClas->ener_RAT_fx, 5898 /* 0.18f in Q15 */ ) && GT_16( hSpMusClas->lt_dec_thres_fx, 7680 /* 15.0f in Q9 */ ) ) { /* prevent GSC on strong music with almost no content below 1kHz */ st->sp_aud_decision2 = 1; + move16(); } - else if ( flag_spitch ) + ELSE IF( flag_spitch ) { /* prevent GSC on signals with very short and stable high pitch period */ - if ( hSpMusClas->wdlp_0_95_sp < 2.5f ) + IF( LT_16( hSpMusClas->wdlp_0_95_sp_fx, 640 /* 2.5f in Q8 */ ) ) { /* select ACELP instead */ st->sp_aud_decision1 = 0; + move16(); } - else + ELSE { /* select TCX instead */ st->sp_aud_decision2 = 1; + move16(); } } - else if ( hSpMusClas->high_stable_cor && st->pitch[0] >= 130 ) + ELSE IF( hSpMusClas->high_stable_cor && GE_16( st->pitch[0], 130 ) ) { /* prevent GSC in highly correlated signal with low energy variation */ /* this is basically a patch against bassoon-type of music */ st->sp_aud_decision2 = 1; + move16(); } } /* change decision from GSC to ACELP TC during attacks/onsets */ - if ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) + test(); + IF( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) { - if ( ( hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] > 4.5f ) && - ( hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] - hSpMusClas->gsc_lt_diff_etot[MAX_LT - 2] > 10.0f ) ) + test(); + IF( GT_16( hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 1], 1152 /*4.5f in Q8*/ ) && + ( GT_16( sub( hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 1], hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 2] ), 2560 /* 10.0f in Q8 */ ) ) ) { - if ( st->tc_cnt == 1 ) + IF( EQ_16( st->tc_cnt, 1 ) ) { /* do ACELP TC coding instead of GC/VC if onset has been already declared before */ st->sp_aud_decision1 = 0; st->coder_type = TRANSITION; + move16(); + move16(); } - else + ELSE { - if ( attack >= ATT_3LSUB_POS ) + IF( GE_16( attack, ATT_3LSUB_POS ) ) { /* do ACELP TC coding also if attack is located in the last subframe */ st->sp_aud_decision1 = 0; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); st->coder_type = TRANSITION; + move16(); + move16(); + move16(); } - else if ( attack >= ATT_SEG_LEN / 2 ) + ELSE IF( GE_16( attack, ATT_SEG_LEN / 2 ) ) { /* do GSC coding if attack is located after the first quarter of the first subframe */ /* (pre-echo will be treated at the decoder side) */ *attack_flag = 31; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); + move16(); + move16(); } } } } - if ( st->localVAD == 1 && st->coder_type == GENERIC && attack > 0 /*&& *attack_flag < 32*/ /*&& st->tc_cnt != 2*/ && !( st->sp_aud_decision2 == 1 && ton > 0.65f ) ) + test(); + test(); + test(); + test(); + IF( EQ_16( st->localVAD, 1 ) && EQ_16( st->coder_type, GENERIC ) && attack > 0 /*&& *attack_flag < 32*/ /*&& st->tc_cnt != 2*/ && !( EQ_16( st->sp_aud_decision2, 1 ) && GT_32( ton, 2726298 /* 0.65f in Q22 */ ) ) ) { /* change ACELP coder_type to TC if attack has been detected */ st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; st->coder_type = TRANSITION; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); + move16(); + move16(); + move16(); + move16(); } -#ifdef DEBUGGING - if ( st->idchan == 0 && st->coder_type != INACTIVE ) - { - if ( st->force == FORCE_GSC && element_brate < IVAS_24k4 ) - { - /* enforce GSC */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 0; - } - else if ( st->force == FORCE_SPEECH && ( st->sp_aud_decision1 == 1 || st->sp_aud_decision2 == 1 ) ) - { - if ( element_brate < IVAS_24k4 ) - { - /* convert TCX to GSC */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 0; - } - else - { - /* convert TCX to ACELP */ - st->sp_aud_decision1 = 0; - st->sp_aud_decision2 = 0; - } - } - else if ( st->force == FORCE_MUSIC ) - { - /* enforce TCX */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 1; - } - } -#endif /* set GSC noisy speech flag on unvoiced SWB segments */ st->GSC_noisy_speech = 0; - if ( st->vad_flag == 1 && element_brate <= IVAS_16k4 && st->lp_noise > 30.0f && st->sp_aud_decision1 == 0 && st->bwidth >= SWB && st->coder_type_raw == UNVOICED ) + move16(); + test(); + test(); + test(); + test(); + test(); + if ( EQ_16( st->vad_flag, 1 ) && LE_32( element_brate, IVAS_16k4 ) && GT_16( st->lp_noise_fx, 7680 /* 30.0f in Q8 */ ) && st->sp_aud_decision1 == 0 && GE_16( st->bwidth, SWB ) && EQ_16( st->coder_type_raw, UNVOICED ) ) { st->GSC_noisy_speech = 1; + move16(); } /* set GSC submode */ - if ( st->element_mode > EVS_MONO && ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) && st->total_brate > STEREO_GSC_BIT_RATE_ALLOC ) /* below STEREO_GSC_BIT_RATE_ALLOC, fall back on normal GSC */ + test(); + test(); + test(); + IF( st->element_mode > EVS_MONO && ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) && GT_32( st->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) ) /* below STEREO_GSC_BIT_RATE_ALLOC, fall back on normal GSC */ { st->GSC_IVAS_mode = 1; - if ( st->hSpMusClas->wdlp_0_95_sp > 0.0f ) + move16(); + IF( st->hSpMusClas->wdlp_0_95_sp_fx > 0 ) { /* music-like content */ st->GSC_IVAS_mode = 3; + move16(); } - else if ( st->tc_cnt > 0 ) + ELSE IF( st->tc_cnt > 0 ) { /* likely presence of an onset, GSC bit allocation will be more focused on LF */ st->GSC_IVAS_mode = 2; + move16(); } - if ( st->coder_type_raw == UNVOICED && st->sp_aud_decision0 == 0 /*&& st->GSC_IVAS_mode < 3*/ ) + test(); + IF( EQ_16( st->coder_type_raw, UNVOICED ) && st->sp_aud_decision0 == 0 /*&& st->GSC_IVAS_mode < 3*/ ) { st->GSC_noisy_speech = 1; + move16(); } - else + ELSE { st->GSC_noisy_speech = 0; + move16(); } } /* set coder_type to AUDIO when GSC is selected (st->core will be set later in the decision matrix) */ - if ( ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) || st->GSC_noisy_speech ) + test(); + test(); + IF( ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) || st->GSC_noisy_speech ) { st->coder_type = AUDIO; + move16(); + test(); if ( st->hGSCEnc != NULL && st->GSC_noisy_speech == 0 ) /* In case of GSC_noisy_speech, NOISE_LEVEL should remain at NOISE_LEVEL_SP3 */ { st->hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); } } return; } - #endif /*---------------------------------------------------------------------* diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 9c25e47114933744f6a482eab23cca3373505dca..fdf3c8cc93328981efbc453c2c5222c7ae29600f 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -90,7 +90,6 @@ typedef struct bitstream_enc_data_structure int16_t *ivas_max_num_indices; /* maximum total number of indices in the list */ Indice **ivas_ind_list_zero; /* beginning of the buffer of indices */ void *st_ivas; /* IVAS encoder structure */ - // Word16 nb_bits_tot_fx; /* total number of bits already written */ // Indice *ind_list_fx; /* list of indices */ Word16 next_ind_fx; /* pointer to the next empty slot in the list of indices */ @@ -128,8 +127,8 @@ typedef struct signal_buffers_enc_data_structure Word16 buf_speech_enc_pe[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; Word16 buf_synth[OLD_SYNTH_SIZE_ENC + L_FRAME32k]; Word16 buf_speech_enc[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; - Word16 buf_wspeech_enc[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k]; /*normally there is a lookahead for 12k8 and 16k but L_FRAME_MAX=L_FRAME_16K+L_NEXT_16k*/ - + Word16 buf_wspeech_enc[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320]; /*normally there is a lookahead for 12k8 and 16k but L_FRAME_MAX=L_FRAME_16K+L_NEXT_16k*/ + /* increased by 320 to avoid memory overlap in ivas_find_wsp() and also to accomodate for the wspeech_enc */ } SIGNAL_BUFFERS_ENC_DATA, *SIGNAL_BUFFERS_ENC_HANDLE; @@ -153,12 +152,14 @@ typedef struct DelayBuffer *pDelayBuffer; /* Delay buffer. */ float subblockNrg_flt[NSUBBLOCKS + MAX_TD_DELAY]; /* Subblock energies with a delay buffering. */ Word32 subblockNrg[NSUBBLOCKS + MAX_TD_DELAY]; + Word16 subblockNrg_e; float accSubblockNrg_flt[NSUBBLOCKS + MAX_TD_DELAY + 1]; /* Recursively accumulated subblock energies with a delay buffering. At index i the value corresponds to the accumulated subblock energy up to i-1, including block i-1 and without block i. */ Word32 accSubblockNrg[NSUBBLOCKS + MAX_TD_DELAY + 1]; + Word16 accSubblockNrg_e; float subblockNrgChange_flt[NSUBBLOCKS + MAX_TD_DELAY]; /* subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ - Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; /* Q(15 - SUBBLOCK_NRG_CHANGE_E) */ + Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; /* Q7(15 - SUBBLOCK_NRG_CHANGE_E) */ int16_t nDelay; /* Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ int16_t nPartialDelay; /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ @@ -225,36 +226,42 @@ typedef struct vad_structure int16_t hangover_cnt_dtx; int16_t hangover_cnt_music; - +#ifndef IVAS_FLOAT_FIXED float bcg_flux; - Word16 bcg_flux_fx; +#endif + Word16 bcg_flux_fx; // Q4 int16_t soft_hangover; int16_t voiced_burst; int16_t bcg_flux_init; int16_t nb_active_frames_he1; int16_t hangover_cnt_he1; - - float prim_act_quick; /* Noise estimator - primary activity quick */ - float prim_act_slow; /* Noise estimator - primary activity slow */ - float prim_act; /* Noise estimator - primary activity slow rise quick fall */ - float prim_act_quick_he; /* Noise estimator - primary activity quick */ - float prim_act_slow_he; /* Noise estimator - primary activity slow */ - float prim_act_he; /* Noise estimator - primary activity slow rise quick fall */ - Word16 prim_act_quick_fx; /* Noise estimator - primary activity quick */ - Word16 prim_act_slow_fx; /* Noise estimator - primary activity slow */ - Word16 prim_act_fx; /* Noise estimator - primary activity slow rise quick fall */ - Word16 prim_act_quick_he_fx; /* Noise estimator - primary activity quick */ - Word16 prim_act_slow_he_fx; /* Noise estimator - primary activity slow */ - Word16 prim_act_he_fx; /* Q15 Noise estimator - primary activity slow rise quick fall */ +#ifndef IVAS_FLOAT_FIXED + float prim_act_quick; /* Noise estimator - primary activity quick */ + float prim_act_slow; /* Noise estimator - primary activity slow */ + float prim_act; /* Noise estimator - primary activity slow rise quick fall */ + float prim_act_quick_he; /* Noise estimator - primary activity quick */ + float prim_act_slow_he; /* Noise estimator - primary activity slow */ + float prim_act_he; /* Noise estimator - primary activity slow rise quick fall */ +#endif + Word16 prim_act_quick_fx; /*Q15 */ /* Noise estimator - primary activity quick */ + Word16 prim_act_slow_fx; /*Q15 */ /* Noise estimator - primary activity slow */ + Word16 prim_act_fx; /*Q15 */ /* Noise estimator - primary activity slow rise quick fall */ + Word16 prim_act_quick_he_fx; /*Q15 */ /* Noise estimator - primary activity quick */ + Word16 prim_act_slow_he_fx; /*Q15 */ /* Noise estimator - primary activity slow */ + Word16 prim_act_he_fx; /*Q15 */ /* Q15 Noise estimator - primary activity slow rise quick fall */ int16_t spectral_tilt_reset; int16_t consec_inactive; +#ifndef IVAS_FLOAT_FIXED float ra_deltasum; +#endif Word16 ra_deltasum_fx; int16_t trigger_SID; +#ifndef IVAS_FLOAT_FIXED float running_avg; float snr_sum_vad; - Word16 snr_sum_vad_fx; +#endif + Word16 snr_sum_vad_fx; /*Q15 */ Word16 running_avg_fx; /*Q15 */ Word32 L_snr_sum_vad_fx; /*Q4*/ @@ -418,18 +425,18 @@ typedef struct td_cng_enc_structure { int16_t lp_cng_mode2; - float lp_ener; /* CNG and DTX - low-pass filtered energy for CNG */ - Word32 lp_ener_fx; /* CNG and DTX - low-pass filtered energy for CNG */ - int16_t cng_seed; /* CNG and DTX - seed for white noise random generator */ - int16_t old_enr_index; /* CNG and DTX - index of last encoded CNG energy */ - float Enew; /* CNG and DTX - CNG target residual energy */ - Word32 Enew_fx; /* CNG and DTX - CNG target residual energy */ - int16_t cng_hist_ptr; /* CNG and DTX - pointer for averaging buffers */ - float cng_lsp_hist[DTX_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ - float cng_ener_hist[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ - Word16 cng_lsp_hist_fx[DTX_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ - Word16 cng_ener_hist_fx[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ - int16_t cng_ener_seed; /* CNG and DTX - seed for random generator for variation of excitation energy */ + float lp_ener; /* CNG and DTX - low-pass filtered energy for CNG */ + Word32 lp_ener_fx; /* CNG and DTX - low-pass filtered energy for CNG */ /*Q6*/ + int16_t cng_seed; /* CNG and DTX - seed for white noise random generator */ + int16_t old_enr_index; /* CNG and DTX - index of last encoded CNG energy */ + float Enew; /* CNG and DTX - CNG target residual energy */ + Word32 Enew_fx; /* CNG and DTX - CNG target residual energy */ /*Q6*/ + int16_t cng_hist_ptr; /* CNG and DTX - pointer for averaging buffers */ + float cng_lsp_hist[DTX_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ + float cng_ener_hist[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ + Word16 cng_lsp_hist_fx[DTX_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ + Word16 cng_ener_hist_fx[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ + int16_t cng_ener_seed; /* CNG and DTX - seed for random generator for variation of excitation energy */ int16_t cng_ener_seed1; float lp_sp_enr; @@ -461,6 +468,7 @@ typedef struct td_cng_enc_structure Word16 cng_Qexc_buf[HO_HIST_SIZE]; /* CNG and DTX - Q_exc buffer for storing */ int32_t cng_brate_buf[HO_HIST_SIZE]; /* CNG and DTX - buffer for storing last_active_brate */ float CNG_att; /* CNG and DTX - attenuation factor for CNG, in dB */ + Word16 CNG_att_fx; /* CNG and DTX - attenuation factor for CNG, in dB (Q7)*/ int16_t ho_16k_lsp[HO_HIST_SIZE]; /* CNG and DTX - 16k LSPs flags */ int16_t act_cnt2; /* CNG and DTX - counter of active frames for CNG_mode switching */ float ho_lsp_circ2[HO_HIST_SIZE * M]; /* CNG and DTX - second buffer of LSPs */ @@ -493,7 +501,6 @@ typedef struct td_cng_enc_structure int16_t shb_cng_ini_cnt; int16_t last_SID_bwidth; int16_t shb_NO_DATA_cnt; - Word16 CNG_att_fx; } TD_CNG_ENC_DATA, *TD_CNG_ENC_HANDLE; @@ -504,8 +511,8 @@ typedef struct td_cng_enc_structure typedef struct fd_cng_enc_structure { HANDLE_FD_CNG_COM hFdCngCom; - float msPeriodog[NPART]; /* Periodogram */ +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msBminWin[NPART]; float msBminSubWin[NPART]; float msPsd[NPART]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ @@ -514,7 +521,7 @@ typedef struct fd_cng_enc_structure float msCurrentMinOut[NPART]; float msCurrentMin[NPART]; float msCurrentMinSubWindow[NPART]; - +#endif Word32 msPeriodog_fx[NPART]; /* Periodogram */ Word16 msPeriodog_fx_exp; /* Common exponent for fft and cldfb energies */ Word16 msPeriodog_fx_exp_fft; @@ -530,16 +537,18 @@ typedef struct fd_cng_enc_structure int16_t msLocalMinFlag[NPART]; int16_t msNewMinFlag[NPART]; - +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msPsdFirstMoment[NPART]; float msPsdSecondMoment[NPART]; float msNoiseFloor[NPART]; /* Estimated noise floor */ - float msNoiseEst[NPART]; /* Estimated noise level */ +#endif + float msNoiseEst[NPART]; /* Estimated noise level */ float energy_ho[NPART]; float msNoiseEst_old[NPART]; +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msLogPeriodog[NPART]; /* Periodogram */ float msLogNoiseEst[NPART]; /* Estimated noise level */ - +#endif Word16 msPsdFirstMoment_fx[NPART]; Word32 msPsdSecondMoment_fx[NPART]; Word16 msNoiseFloor_fx[NPART]; /* Estimated noise floor */ @@ -549,7 +558,6 @@ typedef struct fd_cng_enc_structure Word16 energy_ho_fx_exp; Word32 msNoiseEst_old_fx[NPART]; Word16 msNoiseEst_old_fx_exp; - float msPeriodogBuf[MSBUFLEN * NPART]; Word16 msPeriodogBuf_fx[MSBUFLEN * NPART]; int16_t msPeriodogBufPtr; @@ -562,10 +570,15 @@ typedef struct fd_cng_enc_structure int16_t nFFTpartDec; int16_t partDec[NPART]; + Word16 msLogPeriodog_fx[NPART]; Word16 msLogNoiseEst_fx[NPART]; - +#ifndef IVAS_FLOAT_FIXED float mem_coherence[4]; +#else + Word32 mem_coherence_fx[4]; +#endif + Word16 mem_coherence_exp[4]; } FD_CNG_ENC, *HANDLE_FD_CNG_ENC; // typedef struct @@ -681,6 +694,10 @@ typedef struct igf_enc_private_data_struct IGFSCFENC_INSTANCE hIGFSCFArithEnc; #ifdef IVAS_FLOAT_FIXED Word16 prevSFM_FIR_SFB_TB_fx[IGF_MAX_SFB]; + Word16 prevSFB_FIR_TB_e[IGF_MAX_SFB]; + Word16 prevSFB_IIR_TB_e[IGF_MAX_SFB]; + Word16 prevSFB_FIR_SB_e[IGF_MAX_SFB]; + Word16 prevSFB_IIR_SB_e[IGF_MAX_SFB]; Word16 sfb_sb_e[IGF_MAX_SFB]; Word16 sfb_tb_e[IGF_MAX_SFB]; Word16 prevSFM_IIR_SFB_TB_fx[IGF_MAX_SFB]; @@ -752,13 +769,14 @@ typedef struct noise_estimation_structure float fr_bands2[NB_BANDS]; /* spectrum per critical bands 2 frames ago */ Word32 fr_bands1_fx[NB_BANDS]; /* Q_new + Q_SCALE spectrum per critical bands of the previous frame */ Word32 fr_bands2_fx[NB_BANDS]; /* Q_new + Q_SCALE spectrum per critical bands 2 frames ago */ - - float old_S[L_FFT / 2]; /* Tonal detector - prev. log-energy spectrum with subtracted floor */ - float cor_map[L_FFT / 2]; /* Tonal detector - LT correlation map */ - float noise_char; /* Tonal detector - LT noise character */ +#ifndef IVAS_FLOAT_FIXED + float old_S[L_FFT / 2]; /* Tonal detector - prev. log-energy spectrum with subtracted floor */ + float cor_map[L_FFT / 2]; /* Tonal detector - LT correlation map */ + float noise_char; /* Tonal detector - LT noise character */ + float act_pred; /* Tonal detector - prediction of speech activity from 0 to 1 (0-inactive, 1-active) */ + float multi_harm_limit; /* Tonal detector - adaptive threshold */ +#endif float ave_enr2[NB_BANDS]; /* Tonal detector - LT average E per crit. band (for non_sta2) */ - float act_pred; /* Tonal detector - prediction of speech activity from 0 to 1 (0-inactive, 1-active) */ - float multi_harm_limit; /* Tonal detector - adaptive threshold */ float enrO[NB_BANDS]; /* Noise estimator - previous energy per critical band */ float bckr[NB_BANDS]; /* Noise estimator - background noise estimation per critical band */ float ave_enr[NB_BANDS]; /* Noise estimator - long-term average energy per critical band */ @@ -772,41 +790,47 @@ typedef struct noise_estimation_structure Word32 bckr_fx[NB_BANDS]; /* Q_new + Q_SCALE Noise estimator - background noise estimation per critical band */ Word32 ave_enr_fx[NB_BANDS]; /* Q_new + Q_SCALE Noise estimator - long-term average energy per critical band */ - int16_t aEn; /* Noise estimator - noise estimator adaptation flag */ - float totalNoise; /* Noise estimator - total noise energy */ + int16_t aEn; /* Noise estimator - noise estimator adaptation flag */ +#ifndef IVAS_FLOAT_FIXED + float totalNoise; /* Noise estimator - total noise energy */ +#endif Word16 totalNoise_fx; /* Q8 Noise estimator - total noise energy */ int16_t first_noise_updt; /* Noise estimator - flag used to determine if the first noise update frame */ int16_t first_noise_updt_cnt; /* Noise estimator - counter of frame after first noise update */ int16_t harm_cor_cnt; /* Noise estimator - 1st memory counter of harm or correlation frame */ int16_t bg_cnt; /* Noise estimator - pause length counter */ - float Etot_l; /* Noise estimator - Track energy from below */ - float Etot_h; /* Noise estimator - Track energy from above */ - float Etot_l_lp; /* Noise estimator - Smoothed low energy */ - float Etot_last; /* Noise estimator - Energy of last frame */ - float Etot_lp; /* Noise estimator - Filtered input energy */ - +#ifndef IVAS_FLOAT_FIXED + float Etot_l; /* Noise estimator - Track energy from below */ + float Etot_h; /* Noise estimator - Track energy from above */ +#endif + float Etot_l_lp; /* Noise estimator - Smoothed low energy */ + float Etot_last; /* Noise estimator - Energy of last frame */ + float Etot_lp; /* Noise estimator - Filtered input energy */ +#ifndef IVAS_FLOAT_FIXED float lt_tn_track; float lt_tn_dist; float lt_Ellp_dist; float lt_haco_ev; +#endif Word16 Etot_l_fx; /* Q8 Noise estimator - Track energy from below */ Word16 Etot_h_fx; /* Q8 Noise estimator - Track energy from above */ Word16 Etot_l_lp_fx; /* Q8 Noise estimator - Smoothed low energy */ Word16 Etot_last_fx; /*Q8*/ Word16 Etot_lp_fx; /* Q8 Noise estimator - Filtered input energy */ - Word32 Etot_l_32fx; /* Q8 Noise estimator - Track energy from below */ - Word32 Etot_h_32fx; /* Q8 Noise estimator - Track energy from above */ - Word32 Etot_l_lp_32fx; /* Q8 Noise estimator - Smoothed low energy */ - Word32 Etot_last_32fx; /*Q8*/ - Word32 Etot_lp_32fx; /* Q8 Noise estimator - Filtered input energy */ + Word32 Etot_l_32fx; /* Q24 Noise estimator - Track energy from below */ + Word32 Etot_h_32fx; /* Q24 Noise estimator - Track energy from above */ + Word32 Etot_l_lp_32fx; /* Q24 Noise estimator - Smoothed low energy */ + Word32 Etot_last_32fx; /*Q24*/ + Word32 Etot_lp_32fx; /* Q24 Noise estimator - Filtered input energy */ Word16 lt_tn_track_fx; /* Q15 */ Word16 lt_tn_dist_fx; /* Q8*/ Word16 lt_Ellp_dist_fx; /* Etot low lp same domain as *Etot_l_lp, Q8 */ Word16 lt_haco_ev_fx; /* Q15 */ int16_t low_tn_track_cnt; +#ifndef IVAS_FLOAT_FIXED float epsP_0_2_lp; float epsP_0_2_ad_lp; float epsP_2_16_lp; @@ -814,6 +838,7 @@ typedef struct noise_estimation_structure float epsP_2_16_dlp_lp; float epsP_2_16_dlp_lp2; float lt_aEn_zero; +#endif Word16 epsP_0_2_lp_fx; /* Q12, all epsP quotas , range ]8.0 ..0]*/ Word16 epsP_0_2_ad_lp_fx; Word16 epsP_2_16_lp_fx; @@ -823,8 +848,10 @@ typedef struct noise_estimation_structure float Etot_v_h2; float sign_dyn_lp; +#ifndef IVAS_FLOAT_FIXED float Etot_st_est; /* Noise estimation - short term estimate of E{ Etot } */ float Etot_sq_st_est; /* Noise estimation - short term estimate of E{ Etot^2 } */ +#endif Word16 Etot_v_h2_fx; Word16 sign_dyn_lp_fx; /*Q8*/ @@ -852,9 +879,13 @@ typedef struct sp_mus_clas_structure Word16 past_ps_diff_fx; float prev_FV[N_SMC_FEATURES]; Word32 prev_FV_fx[N_SMC_FEATURES]; +#ifndef IVAS_FLOAT_FIXED float past_epsP; float past_epsP2; - Word16 past_epsP2_fx; +#else + Word16 past_epsP_fx; + Word16 past_epsP2_fx; /* Q10 */ +#endif int16_t inact_cnt; float wdrop; Word16 wdrop_fx; @@ -862,6 +893,7 @@ typedef struct sp_mus_clas_structure Word16 wrise_fx; float wdlp_0_95_sp; Word16 wdlp_0_95_sp_fx; + Word32 wdlp_0_95_sp_32fx; float wdlp_xtalk; Word32 wdlp_xtalk_fx; int16_t sp_mus_state; @@ -896,28 +928,37 @@ typedef struct sp_mus_clas_structure int16_t gsc_nb_thr_1; /* Speech/music classifier - number of consecutives frames of level 1 */ int16_t gsc_nb_thr_3; /* Speech/music classifier - number of consecutives frames of level 3 */ float mold_corr; + Word16 mold_corr_fx; /* Q15 */ +#ifndef IVAS_FLOAT_FIXED float mean_avr_dyn; /* Speech/music classifier - long term average dynamic */ float last_sw_dyn; /* Speech/music classifier - last dynamic */ float lt_dec_thres; /* Speech/music classifier - Long term speech/music thresold values */ float ener_RAT; /* Speech/music classifier - LF/to total energy ratio */ - Word16 mold_corr_fx; - - Word16 mean_avr_dyn_fx; /* Q7 Speech/music classifier - long term average dynamic */ - Word16 last_sw_dyn_fx; /* Q7 Speech/music classifier - last dynamic */ - Word16 lt_dec_thres_fx; /* Speech/music classifier - Long term speech/music thresold values */ - Word16 ener_RAT_fx; /* Q15 Speech/music classifier - LF/to total energy ratio */ +#else + Word16 mean_avr_dyn_fx; /* Speech/music classifier - long term average dynamic Q7 */ + Word16 last_sw_dyn_fx; /* Speech/music classifier - last dynamic Q7 */ + Word16 lt_dec_thres_fx; /* Speech/music classifier - Long term speech/music thresold values Q9 */ + Word16 ener_RAT_fx; /* Speech/music classifier - LF/to total energy ratio Q15 */ +#endif int16_t relE_attack_cnt; +#ifndef IVAS_FLOAT_FIXED float prev_relE; - Word16 prev_relE_fx; float prev_Etot; - Word16 prev_Etot_fx; +#else + Word16 prev_relE_fx; /* Q8 */ + Word16 prev_Etot_fx; /* Q8 */ +#endif int16_t prev_vad; int16_t vad_0_1_cnt; +#ifndef IVAS_FLOAT_FIXED float relE_attack_sum; - Word16 relE_attack_sum_fx; +#else + Word16 relE_attack_sum_fx; /* Q8 */ +#endif /* speech/music classifier improvement parameters */ +#ifndef IVAS_FLOAT_FIXED float old_Bin_E[3 * N_OLD_BIN_E]; float buf_flux[BUF_LEN]; float buf_pkh[BUF_LEN]; @@ -927,91 +968,131 @@ typedef struct sp_mus_clas_structure float buf_Ntonal2[BUF_LEN]; float buf_Ntonal_lf[BUF_LEN]; float buf_dlp[10]; - Word16 old_Bin_E_fx[3 * N_OLD_BIN_E]; - Word16 buf_flux_fx[BUF_LEN]; - Word16 buf_pkh_fx[BUF_LEN]; - Word16 buf_epsP_tilt_fx[BUF_LEN]; - Word16 buf_cor_map_sum_fx[BUF_LEN]; - Word16 buf_Ntonal_fx[BUF_LEN]; - Word16 buf_Ntonal2_fx[BUF_LEN]; - Word16 buf_Ntonal_lf_fx[BUF_LEN]; - Word16 buf_dlp_fx[10]; +#else + Word16 old_Bin_E_fx[3 * N_OLD_BIN_E]; /* Q7 */ + Word16 buf_flux_fx[BUF_LEN]; /* Q7 */ + Word16 buf_pkh_fx[BUF_LEN]; /* Q1 */ + Word16 buf_epsP_tilt_fx[BUF_LEN]; /* Q15 */ + Word16 buf_cor_map_sum_fx[BUF_LEN]; /* Q8 */ + Word16 buf_Ntonal_fx[BUF_LEN]; /* Q0 */ + Word16 buf_Ntonal2_fx[BUF_LEN]; /* Q0 */ + Word16 buf_Ntonal_lf_fx[BUF_LEN]; /* Q0 */ + Word16 buf_dlp_fx[10]; /* Q9 */ +#endif int16_t onset_cnt; +#ifndef IVAS_FLOAT_FIXED float buf_etot[4]; - Word16 buf_etot_fx[4]; +#else + Word16 buf_etot_fx[4]; /* Q8 */ +#endif int16_t attack_hangover; +#ifndef IVAS_FLOAT_FIXED float dec_mov; float dec_mov1; float mov_log_max_spl; float old_lt_diff[2]; - Word16 dec_mov_fx; - Word16 dec_mov1_fx; - Word16 mov_log_max_spl_fx; - Word16 old_lt_diff_fx[2]; +#else + Word16 dec_mov_fx; /* Q15 */ + Word16 dec_mov1_fx; /* Q15 */ + Word16 mov_log_max_spl_fx; /* Q7 */ + Word16 old_lt_diff_fx[2]; /* Q7 */ +#endif int16_t UV_cnt1; +#ifndef IVAS_FLOAT_FIXED float LT_UV_cnt1; - Word16 LT_UV_cnt1_fx; +#else + Word16 LT_UV_cnt1_fx; /* Q6 */ +#endif - float finc_prev[ATT_NSEG]; /* strong attack detection - previous finc */ - float lt_finc; /* strong attack detection - long-term finc energy */ - int16_t last_strong_attack; /* strong attack detection - last strong attack flag */ - float tod_lt_Bin_E[TOD_NSPEC]; /* tonal detector - long-term energy spectrum */ + float finc_prev[ATT_NSEG]; /* strong attack detection - previous finc */ + float lt_finc; /* strong attack detection - long-term finc energy */ + Word32 finc_prev_fx[ATT_NSEG]; /* strong attack detection - previous finc, (Q_new * 2) */ + Word32 lt_finc_fx; /* strong attack detection - long-term finc energy, (Q_new * 2) */ + int16_t last_strong_attack; /* strong attack detection - last strong attack flag */ + float tod_lt_Bin_E[TOD_NSPEC]; /* tonal detector - long-term energy spectrum */ + Word32 tod_lt_Bin_E_fx[TOD_NSPEC]; /* tonal detector - long-term energy spectrum, Q_new + Q_SCALE - 2 */ +#ifndef IVAS_FLOAT_FIXED float tod_S_map_lt[TOD_NSPEC]; /* tonal detector - long-term correlation map */ float tod_thr_lt; /* tonal detector - adaptive threshold */ float tod_weight; /* tonal detector - adaptive weight */ float tod_S_mass_prev; float tod_S_mass_lt; +#else + Word32 tod_S_map_lt_fx[TOD_NSPEC]; /* tonal detector - long-term correlation map, Q22 */ + Word32 tod_thr_lt_fx; /* tonal detector - adaptive threshold, Q22 */ + Word16 tod_weight_fx; /* tonal detector - adaptive weight, Q15 */ + Word32 tod_S_mass_prev_fx; /* Q22 */ + Word32 tod_S_mass_lt_fx; /* Q22 */ +#endif int16_t lt_music_hangover; +#ifndef IVAS_FLOAT_FIXED float tonality2_buf[HANG_LEN_INIT]; float tonality3_buf[HANG_LEN_INIT]; float LPCErr_buf[HANG_LEN_INIT]; - Word16 tonality2_buf_fx[HANG_LEN_INIT]; - Word16 tonality3_buf_fx[HANG_LEN_INIT]; - Word16 LPCErr_buf_fx[HANG_LEN_INIT]; +#else + Word16 tonality2_buf_fx[HANG_LEN_INIT]; /* Q14 */ + Word16 tonality3_buf_fx[HANG_LEN_INIT]; /* Q14 */ + Word16 LPCErr_buf_fx[HANG_LEN_INIT]; /* Q10 */ +#endif int16_t lt_music_state; int16_t lt_speech_state; int16_t lt_speech_hangover; +#ifndef IVAS_FLOAT_FIXED float lpe_buf[HANG_LEN_INIT]; float voicing_buf[HANG_LEN_INIT]; - Word16 lpe_buf_fx[HANG_LEN_INIT]; - Word16 voicing_buf_fx[HANG_LEN_INIT]; +#else + Word16 lpe_buf_fx[HANG_LEN_INIT]; /* Q10 */ + Word16 voicing_buf_fx[HANG_LEN_INIT]; /* Q13 */ +#endif int16_t gsc_hangover; +#ifndef IVAS_FLOAT_FIXED float sparse_buf[HANG_LEN_INIT]; float hf_spar_buf[HANG_LEN_INIT]; float LT_sparse; +#else Word16 sparse_buf_fx[HANG_LEN_INIT]; - Word16 hf_spar_buf_fx[HANG_LEN_INIT]; - Word16 LT_sparse_fx; + Word16 hf_spar_buf_fx[HANG_LEN_INIT]; /* Q15 */ + Word16 LT_sparse_fx; /* Q8 */ +#endif int16_t gsc_cnt; /* speech/music classification */ int16_t last_vad_spa; int16_t lt_old_mode[3]; +#ifndef IVAS_FLOAT_FIXED float lt_voicing_flt; float lt_corr_flt; float lt_tonality_flt; - Word16 lt_voicing; - Word16 lt_corr; - Word32 lt_tonality; +#else + Word16 lt_voicing; /* Q15 */ + Word16 lt_corr; /* Q15 */ + Word32 lt_tonality; /* Q15 */ +#endif int16_t lt_corr_pitch[3]; int16_t lt_hangover; float lowrate_pitchGain_flt; - Word16 lowrate_pitchGain; - + Word16 lowrate_pitchGain; /* Q14 */ +#ifndef IVAS_FLOAT_FIXED float tdm_lt_Etot; float var_cor_t[VAR_COR_LEN]; - Word16 var_cor_t_fx[VAR_COR_LEN]; +#else + Word16 tdm_lt_Etot_fx; /* Q8 */ + Word16 var_cor_t_fx[VAR_COR_LEN]; /* Q11 */ +#endif int16_t high_stable_cor; float lps; float lpm; Word16 lps_fx; Word16 lpm_fx; - Word16 lpn_fx; - +#ifndef IVAS_FLOAT_FIXED float lpn; +#else + Word16 lpn_fx; /* Q7 */ +#endif + } SP_MUS_CLAS_DATA, *SP_MUS_CLAS_HANDLE; @@ -1041,12 +1122,12 @@ typedef struct lpd_state_structure float mem_syn_r_flt[L_SYN_MEM]; /* ACELP synthesis memory for 1.25ms */ float mem_syn3_flt[M]; + Word16 mem_w0; /* weighting filter memory */ Word16 mem_syn[M]; /* ACELP synthesis memory (pe) before post-proc */ Word16 mem_syn1_fx[M]; /* synthesis filter memory (for core switching and FD BWE) */ Word16 mem_syn2[M]; /* ACELP synthesis memory (pe) after post-proc */ Word16 mem_syn_r[L_SYN_MEM]; /* ACELP synthesis memory for 1.25ms */ Word16 mem_syn3[M]; - Word16 mem_w0; /* weighting filter memory */ Word16 e_mem_syn; float tilt_code_flt; @@ -1100,7 +1181,6 @@ typedef struct gsc_enc_structure float mid_dyn; /* AC mode (GSC) - signal dynamic */ Word16 mem_w0_tmp_fx; Word16 mem_syn_tmp_fx[M]; - Word16 mid_dyn_fx; /* AC mode (GSC) - signal dynamic */ int16_t noise_lev; /* AC mode (GSC) - noise level */ int16_t past_dyn_dec; /* AC mode (GSC) - Past noise level decision */ @@ -1266,19 +1346,24 @@ typedef struct sc_vbr_enc_structure int16_t pattern_m; int16_t patterncount; int16_t Last_Resort; - int16_t numactive; /* keep the count of the frames inside current 600 frame block */ - float sum_of_rates; /* sum of the rates of past 600 active frames */ - float global_avr_rate; /* global rate up to current time. recorded a (rate in kbps) * 6000 */ - Word32 sum_of_rates_fx; /* sum of the rates of past 600 active frames*/ - Word32 global_avr_rate_fx; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - int16_t global_frame_cnt; /* 600 active frame block count. Used to update the global rate */ + int16_t numactive; /* keep the count of the frames inside current 600 frame block */ +#ifndef IVAS_FLOAT_FIXED + float sum_of_rates; /* sum of the rates of past 600 active frames */ + float global_avr_rate; /* global rate up to current time. recorded a (rate in kbps) * 6000 */ +#else + Word32 sum_of_rates_fx; /*Q=13 sum of the rates of past 600 active frames*/ + Word32 global_avr_rate_fx; /*Q=13 global rate upto current time. recorded a (rate in kbps) *6000*/ +#endif + int16_t global_frame_cnt; /* 600 active frame block count. Used to update the global rate */ int16_t set_ppp_generic; int16_t avoid_HQ_VBR_NB; int16_t vbr_generic_ho; int16_t Local_VAD; int16_t last_7k2_coder_type; - Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows */ +#if 0 + Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows. global_frame_cnt is used instead */ +#endif } SC_VBR_ENC_DATA, *SC_VBR_ENC_HANDLE; @@ -1321,30 +1406,42 @@ typedef struct td_bwe_enc_structure Word16 old_input_fhb_fx_Q; float prev_lsp_shb[LPC_SHB_ORDER]; - Word16 prev_lsp_shb_fx[LPC_SHB_ORDER]; + Word16 prev_lsp_shb_fx[LPC_SHB_ORDER]; /* Q15 */ float state_ana_filt_shb[2 * ALLPASSSECTIONS_STEEP + 1]; /* states for the analysis filters */ float cldfbHBLT_flt; Word16 state_ana_filt_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 cldfbHBLT; + Word16 cldfbHBLT; /* Q13 */ /* states for the filters used in generating SHB excitation from WB excitation*/ float mem_csfilt[2]; - Word32 mem_csfilt_fx[2]; - float mem_shb_res[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ - float old_EnvSHBres[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ - float old_mean_EnvSHBres; /* energy of the last subframe of the SHB residual signal from previous frame */ - float prev_enr_EnvSHBres; /* energy of the residual SHB envelope from the previous frame */ - float prev_shb_env_tilt; /* tilt of the residual SHB envelope from the previous frame */ - float prev_pow_exc16kWhtnd; /* power of the LB excitation signal in the previous frame */ - float prev_mix_factor; /* mixing factor in the previous frame */ - float prev_Env_error; /* error in SHB envelope modelling */ + Word32 mem_csfilt_fx[2]; /* Q(prev_Q_bwe_exc) */ + float mem_shb_res[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + Word16 mem_shb_res_fx[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + Word32 mem_shb_res_32_fx[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + float old_EnvSHBres[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ + Word16 old_EnvSHBres_fx[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ + float old_mean_EnvSHBres; /* energy of the last subframe of the SHB residual signal from previous frame */ + Word16 old_mean_EnvSHBres_fx; /* energy of the last subframe of the SHB residual signal from previous frame Q15 */ + float prev_enr_EnvSHBres; /* energy of the residual SHB envelope from the previous frame */ + Word32 prev_enr_EnvSHBres_fx; /* energy of the residual SHB envelope from the previous frame Q(31 - prev_enr_EnvSHBres_e) */ + Word16 prev_enr_EnvSHBres_e; + float prev_shb_env_tilt; /* tilt of the residual SHB envelope from the previous frame */ + Word16 prev_shb_env_tilt_fx; /* tilt of the residual SHB envelope from the previous frame Q(prev_shb_env_tilt_q) */ + Word16 prev_shb_env_tilt_q; + float prev_pow_exc16kWhtnd; /* power of the LB excitation signal in the previous frame */ + Word16 prev_pow_exc16kWhtnd_fx; /* power of the LB excitation signal in the previous frame */ + Word32 prev_pow_exc16kWhtnd_fx32; /* Use this power of the LB excitation signal in the previous frame Q0 */ + float prev_mix_factor; /* mixing factor in the previous frame */ + Word16 prev_mix_factor_fx; /* mixing factor in the previous frame Q15 */ + float prev_Env_error; /* error in SHB envelope modelling */ + Word16 prev_Env_error_fx; /* error in SHB envelope modelling */ /* states for the filters used in generating SHB signal from SHB excitation*/ float state_syn_shbexc[L_SHB_LAHEAD]; float state_lpc_syn[LPC_SHB_ORDER]; - float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ - Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; - Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; - Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ + float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ + Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ int16_t bwe_seed[2]; float bwe_non_lin_prev_scale; float old_bwe_exc_extended[NL_BUFF_OFFSET]; @@ -1354,14 +1451,14 @@ typedef struct td_bwe_enc_structure float mem_genSHBexc_filt_down_wb2[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; float mem_genSHBexc_filt_down_wb3[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; float mem_genSHBexc_filt_down_shb[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word32 bwe_non_lin_prev_scale_fx; /*Q30*/ - Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; - Word16 syn_overlap_fx[L_SHB_LAHEAD]; - Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_wb2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_wb3_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; + Word32 bwe_non_lin_prev_scale_fx; /* Q30 */ + Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 syn_overlap_fx[L_SHB_LAHEAD]; /* Q0 not sure */ + Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(-1) */ + Word16 decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(-1) */ + Word16 mem_genSHBexc_filt_down_wb2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_genSHBexc_filt_down_wb3_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_genSHBexc_filt_down_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ float elliptic_bpf_2_48k_mem[4][4]; float prev_fb_energy; @@ -1371,16 +1468,16 @@ typedef struct td_bwe_enc_structure float shb_inv_filt_mem[LPC_SHB_ORDER]; float lsp_shb_spacing[3]; float prev_swb_GainShape; - Word32 elliptic_bpf_2_48k_mem_fx[4][4]; + Word32 elliptic_bpf_2_48k_mem_fx[4][4]; /*elliptic_bpf_2_48k_mem_fx_Q[4]*/ Word16 elliptic_bpf_2_48k_mem_fx_Q[4]; - Word32 prev_fb_energy_fx; + Word32 prev_fb_energy_fx; /*prev_fb_energy_fx_Q*/ Word16 prev_fb_energy_fx_Q; - Word32 prev_gainFr_SHB_fx; - Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; - Word16 lsp_shb_fast_interpl_fx[LPC_SHB_ORDER]; + Word32 prev_gainFr_SHB_fx; /* Q18 */ + Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; /* Q15 */ + Word16 lsp_shb_fast_interpl_fx[LPC_SHB_ORDER]; /* Q15 */ Word16 shb_inv_filt_mem_fx[LPC_SHB_ORDER]; - Word16 lsp_shb_spacing_fx[3]; - Word16 prev_swb_GainShape_fx; + Word16 lsp_shb_spacing_fx[3]; /* Q15 */ + Word16 prev_swb_GainShape_fx; /* Q15 */ int16_t prev_frGainAtten; float prev_wb_GainShape_flt; @@ -1388,8 +1485,8 @@ typedef struct td_bwe_enc_structure float fb_state_lpc_syn[LPC_SHB_ORDER]; float fb_tbe_demph; float tilt_mem; - Word16 prev_wb_GainShape; - Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; + Word16 prev_wb_GainShape; /* Q15 */ + Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; /* Q15 */ Word16 fb_state_lpc_syn_fx[LPC_SHB_ORDER]; Word16 prev_Q_bwe_exc_fb; Word16 fb_tbe_demph_fx; @@ -1400,8 +1497,8 @@ typedef struct td_bwe_enc_structure float prev_tilt_para; float cur_sub_Aq[M + 1]; Word16 prev_lsf_diff_fx[LPC_SHB_ORDER - 2]; - Word16 prev_tilt_para_fx; - Word16 cur_sub_Aq_fx[M + 1]; + Word16 prev_tilt_para_fx; /* Q10 */ + Word16 cur_sub_Aq_fx[M + 1]; /* Q12 */ /* quantized data */ int16_t lsf_idx[NUM_Q_LSF]; @@ -1419,7 +1516,7 @@ typedef struct td_bwe_enc_structure int16_t idxGain; float dec_2_over_3_mem[L_FILT_2OVER3]; float dec_2_over_3_mem_lp[L_FILT_2OVER3_LP]; - Word16 dec_2_over_3_mem_fx[12]; + Word16 dec_2_over_3_mem_fx[L_FILT_2OVER3]; Word16 dec_2_over_3_mem_lp_fx[6]; float tbe_demph; @@ -1428,11 +1525,11 @@ typedef struct td_bwe_enc_structure float *ptr_mem_stp_swb; float gain_prec_swb; float mem_zero_swb[LPC_SHB_ORDER]; - Word16 tbe_demph_fx; - Word16 tbe_premph_fx; - Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; + Word16 tbe_demph_fx; /* Q(prev_Q_bwe_exc - 16 - NOISE_QADJ) */ + Word16 tbe_premph_fx; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; /* Q(st->prev_Q_bwe_syn) */ Word16 *ptr_mem_stp_swb_fx; - Word16 gain_prec_swb_fx; + Word16 gain_prec_swb_fx; /* Q14 */ Word16 mem_zero_swb_fx[LPC_SHB_ORDER]; } TD_BWE_ENC_DATA, *TD_BWE_ENC_HANDLE; @@ -1453,14 +1550,14 @@ typedef struct fd_bwe_enc_structure float mem_deemph_old_syn; Word16 new_input_hp_fx[NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS )]; Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS )]; - Word16 old_input_wb_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; + Word16 old_input_wb_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; /* Q(-1) */ Word16 old_input_lp_fx[NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS )]; Word16 old_syn_12k8_16k_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; Word16 old_fdbwe_speech_fx[L_FRAME48k]; Word16 mem_deemph_old_syn_fx; int16_t prev_mode; float old_wtda_swb[L_FRAME48k]; - Word16 L_old_wtda_swb_fx[L_FRAME48k]; + Word16 L_old_wtda_swb_fx[L_FRAME48k]; /* Q(Q_old_wtda) */ Word16 prev_Q_input_lp; int16_t prev_L_swb_norm1; float prev_global_gain; @@ -1469,6 +1566,7 @@ typedef struct fd_bwe_enc_structure float EnergyLF; Word32 EnergyLF_fx; float mem_old_wtda_swb; + Word16 mem_old_wtda_swb_fx; /* Q(-1) */ } FD_BWE_ENC_DATA, *FD_BWE_ENC_HANDLE; @@ -1632,6 +1730,7 @@ typedef struct tcx_enc_structure float *new_speech_TCX_flt; Word16 *speech_TCX; Word16 *new_speech_TCX; + Word16 q_speech_TCX; int16_t tcxltp; int16_t tcxltp_pitch_int; @@ -1706,6 +1805,7 @@ typedef struct tcx_enc_structure Word32 *spectrum_fx[2]; /* MDCT output for a short block */ Word16 spectrum_e[2]; Word32 spectrum_long_fx[N_MAX]; /* MDCT output for a long block. Points to spectrum */ + Word16 q_spectrum_long_fx; } TCX_ENC_DATA, *TCX_ENC_HANDLE; typedef struct TransientDetection @@ -1825,6 +1925,7 @@ typedef struct enc_core_structure float voicing[3]; /* open-loop normalized correlation values for three half-frames */ // Word16 pitch_fx[3]; Word16 voicing_fx[3]; + Word16 voicing_e; LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */ @@ -1839,7 +1940,7 @@ typedef struct enc_core_structure Word16 lsp_old1_fx[M]; /* old unquantized LSP vector at the end of the frame */ Word16 lsf_old1_fx[M]; /* old LSF vector at the end of the frame */ Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame */ // Q15 - Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame Qlog2(2.56) */ Word16 lsp_old16k_fx[M]; /* old LSP vector at the end of the frame @16kHz */ Word16 lspold_enc_fx[M]; /* old LSP vector at the end of the frame @16kHz */ @@ -1881,20 +1982,19 @@ typedef struct enc_core_structure Word16 mem_AR_fx[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean) */ Word16 mem_MA_fx[M]; /* MA memory of LSF quantizer (past quantized residual) (used also in AMR-WB IO mode) */ Word16 mCb1_fx; /* LSF quantizer - counter of stationary frames after a transition frame */ - int16_t GSC_noisy_speech; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ int16_t GSC_IVAS_mode; GSC_ENC_HANDLE hGSCEnc; - int16_t Last_pulse_pos; /* FEC - last position of the first glottal pulse in the frame */ - float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ - float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ - float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ - Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ - Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ - Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ - int16_t next_force_safety_net; /* FEC - flag to force safety net in next frame */ - Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ + int16_t Last_pulse_pos; /* FEC - last position of the first glottal pulse in the frame */ + float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ + float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ + float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ + Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ + Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ + Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ + int16_t next_force_safety_net; /* FEC - flag to force safety net in next frame */ + // Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ int16_t uv_count; /* Stationary noise UV modification - unvoiced counter */ int16_t act_count; /* Stationary noise UV modification - activation counter */ @@ -2022,6 +2122,7 @@ typedef struct enc_core_structure Word16 exp_old_inp_12k8; Word16 exp_old_inp_16k; Word16 exp_buf_wspeech_enc; + Word16 exp_buf_synth; #endif /*----------------------------------------------------------------------------------* @@ -2066,8 +2167,8 @@ typedef struct enc_core_structure 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; - int16_t active_cnt; /* counter of active frames */ + Word32 bckr_tilt_lt; // Q16 + int16_t active_cnt; /* counter of active frames */ TD_CNG_ENC_HANDLE hTdCngEnc; @@ -2231,7 +2332,7 @@ typedef struct enc_core_structure float preemph_fac_flt; /* Preemphasis factor */ float gamma_flt; - Word16 preemph_fac; /*Preemphasis factor*/ + Word16 preemph_fac; /*Preemphasis factor Q15*/ Word16 gamma; // Q15 Word16 inv_gamma; @@ -2375,6 +2476,8 @@ typedef struct enc_core_structure Word16 last_ener_fx; /* AC mode (GSC) - previous energy */ + Word16 Q_exc; + Word16 prev_Q_bwe_exc; Word16 prev_Q_bwe_syn; Word16 Q_stat_noise_ge; @@ -2950,4 +3053,5 @@ typedef struct context_rc_mem_struct } RC_CONTEXT_MEM, *HANDLE_RC_CONTEXT_MEM; + #endif diff --git a/lib_enc/stat_noise_uv_enc_fx.c b/lib_enc/stat_noise_uv_enc_fx.c index 809f4e5b36359234c5c2e6b69e177474a796050b..e741149c28c8bb9d188f776ac2ed4d2089ff8f59 100644 --- a/lib_enc/stat_noise_uv_enc_fx.c +++ b/lib_enc/stat_noise_uv_enc_fx.c @@ -11,6 +11,10 @@ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#ifdef IVAS_FLOAT_FIXED +#include "prot.h" +#endif + /*======================================================================*/ /* FUNCTION : stat_noise_uv_enc_fx */ /*----------------------------------------------------------------------*/ @@ -116,3 +120,88 @@ void stat_noise_uv_enc_fx( return; } + + +void stat_noise_uv_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word32 *LepsP, /* i : LP prediction errors Q=Qx*/ + const Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr Q=15*/ + const Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr Q=15*/ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes Q=12 */ + Word16 *exc2, /* i/o: excitation buffer Q=Q_stat_noise */ + const Word16 uc_two_stage_flag, /* o : flag undicating two-stage UC */ + Word16 Q_new ) +{ + Word16 noisiness = 0; + move16(); + Word16 num, den, expn, expd; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + test(); + test(); + test(); + IF( ( EQ_16( st_fx->coder_type, UNVOICED ) && uc_two_stage_flag == 0 ) || ( EQ_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, ACELP_9k60 ) ) ) + { + + /*-----------------------------------------------------------------* + * Calculate and write the noisiness parameter + *-----------------------------------------------------------------*/ + /* epsP[2] is located in LepsP[0] and epsP[16] in LepsP[1] */ + expn = sub( norm_l( LepsP[0] ), 1 ); +#ifdef BASOP_NOGLOB + num = extract_h( L_shl_o( LepsP[0], expn, &Overflow ) ); /*expn-16*/ +#else + num = extract_h( L_shl( LepsP[0], expn ) ); /*expn-16*/ +#endif + expd = norm_l( LepsP[1] ); +#ifdef BASOP_NOGLOB + den = extract_h( L_shl_o( LepsP[1], expd, &Overflow ) ); /*expd-16*/ +#else + den = extract_h( L_shl( LepsP[1], expd ) ); /*expd-16*/ +#endif + num = div_s( num, den ); /*expn-expd+15*/ +#ifdef BASOP_NOGLOB + num = shr_o( num, add( sub( expn, expd ), 5 ), &Overflow ); /*Q10*/ +#else + num = shr( num, add( sub( expn, expd ), 5 ) ); /*Q10*/ +#endif + num = sub( num, 1024 ); /*num - 1*/ + + test(); + IF( NE_16( st_fx->bwidth, NB ) ) + { + /* WB case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*2 * 32);*/ + noisiness = shr( num, 4 ); /*Q10 x64 -> Q0 */ + } + ELSE IF( EQ_16( st_fx->coder_type, INACTIVE ) && EQ_16( st_fx->bwidth, NB ) ) + { + /* NB GSC case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*.25f * 32);*/ + noisiness = shr( num, 4 + 3 ); /*Q10 x8 -> Q0 */ + } + ELSE + { + /* NB case */ + noisiness = shr( num, 4 + 2 ); /*Q16 x16 -> Q0 */ + } + + noisiness = s_max( noisiness, 0 ); + noisiness = s_min( noisiness, 31 ); + + push_indice( st_fx->hBstr, IND_NOISINESS, noisiness, 5 ); + } + + /*-----------------------------------------------------------------* + * Modify the stationary noise excitation signal + *-----------------------------------------------------------------*/ + + stat_noise_uv_mod_ivas_fx( st_fx->coder_type, noisiness, st_fx->lsp_old_fx, isp_new, isp_mid, Aq, exc2, Q_new, 0, &st_fx->ge_sm_fx, &st_fx->uv_count, &st_fx->act_count, + st_fx->lspold_s_fx, &st_fx->noimix_seed, &st_fx->min_alpha_fx, &st_fx->exc_pe_fx, + st_fx->core_brate, st_fx->bwidth, &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + + + return; +} diff --git a/lib_enc/swb_bwe_enc_fx.c b/lib_enc/swb_bwe_enc_fx.c index 1167ad1afcbf48c6f7539e48a46a6cbb5a5d2b55..d3e56a079a50715e772235e8c98709c1d1024735 100644 --- a/lib_enc/swb_bwe_enc_fx.c +++ b/lib_enc/swb_bwe_enc_fx.c @@ -34,6 +34,21 @@ static Word16 SWB_BWE_encoding_fx( Word16 Q_synth, Word16 Q_synth_lf ); +static Word16 SWB_BWE_encoding_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i/o: delayed original input signal at 32kHz (might be rescaled)*/ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf ); + static void delay_input_signal_fx( Word16 *old_sig, Word16 *cur_sig, @@ -109,6 +124,7 @@ static void delay_input_signal_fx( * * WB BWE encoder *-------------------------------------------------------------------*/ + void wb_bwe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *new_wb_speech_fx, /* i : original input signal at 16kHz */ @@ -180,19 +196,98 @@ void wb_bwe_enc_fx( return; } +/*-------------------------------------------------------------------* + * wb_bwe_enc_ivas_fx() + * + * WB BWE encoder + *-------------------------------------------------------------------*/ + +void wb_bwe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *new_wb_speech_fx /* i : original input signal at 16kHz */ +) +{ + Word16 mode = 0; + Word16 Sample_Delay_WB_BWE; + Word16 old_input_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME16k]; + Word32 yorig_32[L_FRAME16k]; + Word16 yorig_fx[L_FRAME16k]; + Word32 L_wtda_synth_fx[2 * L_FRAME16k]; + Word16 *new_input_fx; /* pointer to original input signal */ + Word16 scl, new_input_fx_exp; + Word16 Q_synth; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + Word16 WB_fenv_fx[SWB_FENV]; + move16(); + + IF( GT_32( st_fx->extl_brate, 0 ) ) + { + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + set16_fx( old_input_fx, 0, NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME16k ); + Sample_Delay_WB_BWE = NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + + new_input_fx = old_input_fx + Sample_Delay_WB_BWE; + Copy( hBWE_FD->old_input_wb_fx, old_input_fx, Sample_Delay_WB_BWE ); + Copy( new_wb_speech_fx, new_input_fx, L_FRAME16k ); + Copy( old_input_fx + L_FRAME16k, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + + /*---------------------------------------------------------------------*/ + /* WB BWE encoding */ + + + /* MDCT of the core synthesis signal */ + /*---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + move16(); + + wtda_fx( old_input_fx, &new_input_fx_exp, L_wtda_synth_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + L_FRAME16k ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx( L_wtda_synth_fx, yorig_32, 0, L_FRAME16k, &new_input_fx_exp, st_fx->element_mode ); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub( 16 + 8 /*MAX_Q_NEW_INPUT*/, new_input_fx_exp ); + /* Possible to Upscale? */ + IF( scl > 0 ) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32( yorig_32, L_FRAME16k ); + + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min( Q_synth, scl ); + } + Copy_Scale_sig32_16( yorig_32, yorig_fx, L_FRAME16k, scl ); + Q_synth = add( sub( new_input_fx_exp, 16 ), scl ) - 1; + + mode = WB_BWE_encoding_ivas_fx( st_fx, yorig_fx, WB_fenv_fx, Q_synth, Q_synth ); + push_indice( st_fx->hBstr, IND_WB_CLASS, mode - 2, 1 ); + } + + hBWE_FD->prev_mode = mode; + move16(); + + return; +} + /*-------------------------------------------------------------------* * swb_bwe_enc() * * SWB BWE encoder (only for 32kHz signals) *-------------------------------------------------------------------*/ -void swb_bwe_enc_fx( +void swb_bwe_enc_ivas_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ + const int16_t last_element_mode, /* i : last element mode */ Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ - const Word16 coder_type, /* i : coding type */ Word16 Q_shb_speech, Word16 Q_slb_speech ) { @@ -215,19 +310,23 @@ void swb_bwe_enc_fx( Word16 Sample_Delay_HP; Word16 Sample_Delay_LP; Word16 idxGain = 0; - + move16(); Word16 Q_synth_hf, Q_synth, Q_shb; Word16 tilt_nb_fx; Word16 SWB_fenv_fx[SWB_FENV]; Word32 ener_low_fx; - Word32 energy_fbe_fb_fx = 0; + Word32 energy_fbe_fb_fx; Word16 fb_ener_adjust_fx; Word16 ener_adjust_quan_fx = 0; + move16(); #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + Word16 fb_band_begin; FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; /*---------------------------------------------------------------------* @@ -236,12 +335,16 @@ void swb_bwe_enc_fx( IF( EQ_16( st_fx->extl, FB_BWE ) ) { inner_frame = L_FRAME48k; + move16(); inner_Fs = 48000; + move16(); } ELSE { inner_frame = L_FRAME32k; + move16(); inner_Fs = 32000; + move16(); } set16_fx( old_input_fx, 0, add( NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ), inner_frame ) ); @@ -250,17 +353,50 @@ void swb_bwe_enc_fx( { Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS ); + } Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ); - delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + IF( st_fx->element_mode > EVS_MONO ) + { + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); + Sample_Delay_HP = sub( Sample_Delay_HP, NS2SA( 16000, DELAY_FIR_RESAMPL_NS ) ); + + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Copy( old_input_12k8_fx + L_INP_MEM - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); + Copy( hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - Sample_Delay_HP, new_input_hp_fx, Sample_Delay_HP ); + } + } + Copy( hBWE_FD->old_input_lp_fx, old_input_lp_fx, Sample_Delay_LP ); + Copy( old_input_12k8_fx + L_INP_MEM, &old_input_lp_fx[Sample_Delay_LP], L_FRAME - Sample_Delay_LP ); + Copy( old_input_12k8_fx + L_INP_MEM + L_FRAME - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); } ELSE { Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS ); + } Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ); + IF( st_fx->element_mode > EVS_MONO ) + { + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); + Sample_Delay_HP = sub( Sample_Delay_HP, NS2SA( 16000, DELAY_FIR_RESAMPL_NS ) ); - delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Copy( old_input_16k_fx + L_INP_MEM - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); + Copy( hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - Sample_Delay_HP, new_input_hp_fx, Sample_Delay_HP ); + } + } + Copy( hBWE_FD->old_input_lp_fx, old_input_lp_fx, Sample_Delay_LP ); + Copy( old_input_16k_fx + L_INP_MEM, &old_input_lp_fx[Sample_Delay_LP], L_FRAME16k - Sample_Delay_LP ); + Copy( old_input_16k_fx + L_INP_MEM + L_FRAME16k - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); } Copy( hBWE_FD->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP ); @@ -285,13 +421,29 @@ void swb_bwe_enc_fx( * FB BWE encoding *---------------------------------------------------------------------*/ new_input_fx_exp = 0; + move16(); + test(); + IF( ( EQ_16( st_fx->idchan, 1 ) ) && ( EQ_16( last_element_mode, IVAS_CPE_DFT ) ) ) + { + FOR( i = 0; i < inner_frame; i++ ) + { + hBWE_FD->L_old_wtda_swb_fx[i] = mult_r( hBWE_FD->L_old_wtda_swb_fx[i], div_s( i, inner_frame ) ); + move16(); + } + } /* MDCT of the core synthesis signal */ wtda_fx( old_input_fx, &new_input_fx_exp, L_old_input_fx, hBWE_FD->L_old_wtda_swb_fx, &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ inner_frame ); /* DCT of the ACELP core synthesis */ - direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, /*st_fx->element_mode*/ EVS_MONO ); + direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, st_fx->element_mode ); + + /* high-band gain control in case of BWS */ + IF( st_fx->bwidth_sw_cnt > 0 ) + { + v_multc_fixed_16( &yorig_32[L_FRAME16k], div_s( st_fx->bwidth_sw_cnt, BWS_TRAN_PERIOD ), &yorig_32[L_FRAME16k], sub( inner_frame, L_FRAME16k ) ); + } /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ scl = sub( 16 + 8, new_input_fx_exp ); @@ -306,7 +458,6 @@ void swb_bwe_enc_fx( } Copy_Scale_sig32_16( yorig_32, yorig_fx, inner_frame, scl ); Q_synth = add( sub( new_input_fx_exp, 16 ), scl ); - max = 0; move16(); Q_synth_hf = 0; @@ -335,25 +486,27 @@ void swb_bwe_enc_fx( { exp = norm_s( max ); } - Copy_Scale_sig( &yorig_fx[scl], &yorig_fx[scl], sub( inner_frame, scl ), exp ); Q_synth_hf = add( exp, Q_synth ); + test(); IF( EQ_16( st_fx->last_extl, SWB_BWE ) || EQ_16( st_fx->last_extl, FB_BWE ) ) { exp = norm_l( st_fx->EnergyLT_fx ); - IF( add( st_fx->EnergyLT_fx_exp, exp ) > shl( sub( Q_synth_hf, 4 ), 1 ) ) + IF( GT_16( add( st_fx->EnergyLT_fx_exp, exp ), shl( sub( Q_synth_hf, 4 ), 1 ) ) ) { Q_shb = sub( Q_synth_hf, 4 ); st_fx->EnergyLT_fx = L_shr( st_fx->EnergyLT_fx, sub( st_fx->EnergyLT_fx_exp, shl( Q_shb, 1 ) ) ); + move32(); } ELSE { Q_shb = shr( add( st_fx->EnergyLT_fx_exp, exp ), 1 ); - IF( s_and( exp, 0x0001 ) == 1 ) + IF( EQ_16( s_and( exp, 0x0001 ), 1 ) ) { exp = sub( exp, 1 ); } st_fx->EnergyLT_fx = L_shl( st_fx->EnergyLT_fx, exp ); + move32(); } } ELSE @@ -361,30 +514,26 @@ void swb_bwe_enc_fx( Q_shb = sub( Q_synth_hf, 4 ); } Copy_Scale_sig( new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub( Q_shb, Q_shb_speech ) ); - /* SWB BWE encoding */ - IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) - { - SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, - SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); - } - ELSE - { - SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, - SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); - } /* FB BWE encoding */ IF( EQ_16( st_fx->extl, FB_BWE ) ) { + fb_band_begin = FB_BAND_BEGIN; + move16(); + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + fb_band_begin = FB_BAND_BEGIN_12k8; + move16(); + } energy_fbe_fb_fx = L_deposit_l( 0 ); - FOR( i = FB_BAND_BEGIN; i < FB_BAND_END; i++ ) + FOR( i = fb_band_begin; i < FB_BAND_END; i++ ) { tmp = shr( yorig_fx[i], 4 ); energy_fbe_fb_fx = L_mac0( energy_fbe_fb_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ } ener_low_fx = 0; move16(); - FOR( i = FB_BAND_BEGIN - FB_BAND_WIDTH; i < FB_BAND_BEGIN; i++ ) + FOR( i = fb_band_begin - FB_BAND_WIDTH; i < fb_band_begin; i++ ) { tmp = shr( yorig_fx[i], 4 ); ener_low_fx = L_mac0( ener_low_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ @@ -398,7 +547,7 @@ void swb_bwe_enc_fx( L_tmp = Mult_32_16( ener_low_fx, tmp ); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ exp1 = norm_l( L_tmp ); L_tmp = L_shl( L_tmp, exp1 ); - exp = 31 - exp1 - ( 30 - exp ); + exp = sub( sub( 31, exp1 ), sub( 30, exp ) ); L_tmp = Isqrt_lc( L_tmp, &exp ); /*31-exp */ #ifdef BASOP_NOGLOB fb_ener_adjust_fx = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /*Q15 */ @@ -416,1493 +565,2398 @@ void swb_bwe_enc_fx( idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl( 1, NUM_BITS_FB_FRAMEGAIN ) ); } + /* SWB BWE encoding */ + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + SWB_BWE_encoding_ivas_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + ELSE + { + SWB_BWE_encoding_ivas_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* write FB BWE frame gain to the bitstream */ IF( EQ_16( st_fx->extl, FB_BWE ) ) { - push_indice_fx( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + push_indice( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); } return; } -/*==========================================================================*/ -/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ -/*--------------------------------------------------------------------------*/ -/* PURPOSE : Scalar quantizer routine */ -/*--------------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* Word16 *cb i: quantizer codebook Q10 */ -/* Word16 cb_length i: length of codebook */ -/* Word16 cb_dim i: dimension of codebook */ -/*--------------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/*--------------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* Word16 *x i/o: energy of WB envelop Q10 */ -/*--------------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : */ -/* _ None */ -/*--------------------------------------------------------------------------*/ -/* */ -/*==========================================================================*/ -static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ - Word16 *x, /* i/o: energy of WB envelop Q10*/ - const Word16 *cb, /* i: quantizer codebook Q10 */ - const Word16 cb_length, /* i: length of codebook */ - const Word16 cb_dim /* i: dimension of codebook */ -) + +/*-------------------------------------------------------------------* + * swb_bwe_enc() + * + * SWB BWE encoder (only for 32kHz signals) + *-------------------------------------------------------------------*/ +void swb_bwe_enc_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech ) { - Word16 i, j, indx = 0; - Word32 dist, min_dist; - const Word16 *pit = cb; /*Q10 */ - Word16 tmp; + Word16 i; + Word16 *new_input_fx; + Word16 tmp, exp, exp1; + Word16 frac; Word32 L_tmp; + Word16 inner_frame; + Word32 inner_Fs; + Word32 L_old_input_fx[2 * L_FRAME48k]; + Word32 yorig_32[L_FRAME48k]; + Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; + Word16 old_input_lp_fx[L_FRAME16k]; + Word16 new_input_hp_fx[L_FRAME16k]; + Word16 yorig_fx[L_FRAME48k]; + Word16 scl, new_input_fx_exp; + Word16 max; + Word16 Sample_Delay_SWB_BWE; + Word16 Sample_Delay_HP; + Word16 Sample_Delay_LP; + Word16 idxGain = 0; - min_dist = L_add( MAX_32, 0 ); - FOR( i = 0; i < cb_length; i++ ) - { - dist = L_deposit_l( 0 ); - FOR( j = 0; j < cb_dim; j++ ) - { -#ifdef BASOP_NOGLOB - tmp = sub_sat( x[j], *pit ); /*Q10 */ - L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ - dist = L_add_sat( dist, L_tmp ); -#else - tmp = sub( x[j], *pit ); /*Q10 */ - L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ - dist = L_add( dist, L_tmp ); + Word16 Q_synth_hf, Q_synth, Q_shb; + Word16 tilt_nb_fx; + Word16 SWB_fenv_fx[SWB_FENV]; + Word32 ener_low_fx; + Word32 energy_fbe_fb_fx = 0; + Word16 fb_ener_adjust_fx; + Word16 ener_adjust_quan_fx = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; #endif - pit++; - } - IF( LT_32( dist, min_dist ) ) - { - min_dist = L_add( dist, 0 ); - indx = i; - move16(); - } - } + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( j = 0; j < cb_dim; j++ ) - { - x[j] = cb[cb_dim * indx + j]; - move16(); - } + + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + } + + set16_fx( old_input_fx, 0, add( NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ), inner_frame ) ); + + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ); + + delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + ELSE + { + Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ); + + delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + + Copy( hBWE_FD->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP ); + Copy( shb_speech_fx, &new_input_hp_fx[Sample_Delay_HP], L_FRAME16k - Sample_Delay_HP ); + Copy( shb_speech_fx + L_FRAME16k - Sample_Delay_HP, hBWE_FD->new_input_hp_fx, Sample_Delay_HP ); + new_input_fx = old_input_fx + Sample_Delay_SWB_BWE; + Copy( hBWE_FD->old_input_fx, old_input_fx, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx, new_input_fx, inner_frame ); + Copy( old_input_fx + inner_frame, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + /*----------------------------------------------------------------------* + * Calculate tilt of the input signal and the ACELP core synthesis + *----------------------------------------------------------------------*/ + + /* tilt returned in Q24 goto to Q11 */ +#ifdef BASOP_NOGLOB + tilt_nb_fx = round_fx_o( L_shl_o( calc_tilt_bwe_fx( old_input_lp_fx, Q_slb_speech, st_fx->L_frame ), 3, &Overflow ), &Overflow ); +#else + tilt_nb_fx = round_fx( L_shl( calc_tilt_bwe_fx( old_input_lp_fx, Q_slb_speech, st_fx->L_frame ), 3 ) ); +#endif + /*---------------------------------------------------------------------* + * SWB BWE encoding + * FB BWE encoding + *---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + /* MDCT of the core synthesis signal */ + wtda_fx( old_input_fx, &new_input_fx_exp, L_old_input_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + inner_frame ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, /*st_fx->element_mode*/ EVS_MONO ); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub( 16 + 8, new_input_fx_exp ); + /* Possible to Upscale? */ + IF( scl > 0 ) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32( yorig_32, inner_frame ); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min( Q_synth, scl ); + } + Copy_Scale_sig32_16( yorig_32, yorig_fx, inner_frame, scl ); + Q_synth = add( sub( new_input_fx_exp, 16 ), scl ); + + max = 0; + move16(); + Q_synth_hf = 0; + move16(); + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + scl = 300; + move16(); + } + ELSE + { + scl = 240; + move16(); + } + FOR( i = scl; i < inner_frame; i++ ) + { + max = s_max( max, abs_s( yorig_fx[i] ) ); + } + + IF( max == 0 ) + { + exp = 15; + move16(); + } + ELSE + { + exp = norm_s( max ); + } + + Copy_Scale_sig( &yorig_fx[scl], &yorig_fx[scl], sub( inner_frame, scl ), exp ); + Q_synth_hf = add( exp, Q_synth ); + IF( EQ_16( st_fx->last_extl, SWB_BWE ) || EQ_16( st_fx->last_extl, FB_BWE ) ) + { + exp = norm_l( st_fx->EnergyLT_fx ); + IF( add( st_fx->EnergyLT_fx_exp, exp ) > shl( sub( Q_synth_hf, 4 ), 1 ) ) + { + Q_shb = sub( Q_synth_hf, 4 ); + st_fx->EnergyLT_fx = L_shr( st_fx->EnergyLT_fx, sub( st_fx->EnergyLT_fx_exp, shl( Q_shb, 1 ) ) ); + } + ELSE + { + Q_shb = shr( add( st_fx->EnergyLT_fx_exp, exp ), 1 ); + IF( s_and( exp, 0x0001 ) == 1 ) + { + exp = sub( exp, 1 ); + } + st_fx->EnergyLT_fx = L_shl( st_fx->EnergyLT_fx, exp ); + } + } + ELSE + { + Q_shb = sub( Q_synth_hf, 4 ); + } + Copy_Scale_sig( new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub( Q_shb, Q_shb_speech ) ); + /* SWB BWE encoding */ + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + ELSE + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* FB BWE encoding */ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + energy_fbe_fb_fx = L_deposit_l( 0 ); + FOR( i = FB_BAND_BEGIN; i < FB_BAND_END; i++ ) + { + tmp = shr( yorig_fx[i], 4 ); + energy_fbe_fb_fx = L_mac0( energy_fbe_fb_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ + } + ener_low_fx = 0; + move16(); + FOR( i = FB_BAND_BEGIN - FB_BAND_WIDTH; i < FB_BAND_BEGIN; i++ ) + { + tmp = shr( yorig_fx[i], 4 ); + ener_low_fx = L_mac0( ener_low_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ + } + + IF( energy_fbe_fb_fx != 0 ) + { + exp = norm_l( energy_fbe_fb_fx ); + frac = extract_h( L_shl( energy_fbe_fb_fx, exp ) ); + tmp = div_s( 16384, frac ); /*15+14-(exp+2*(Q_synth_hf-4)-16) -->45-(exp+2*(Q_synth_hf-4)) */ + L_tmp = Mult_32_16( ener_low_fx, tmp ); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ + exp1 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp1 ); + exp = 31 - exp1 - ( 30 - exp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*31-exp */ +#ifdef BASOP_NOGLOB + fb_ener_adjust_fx = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /*Q15 */ +#else + fb_ener_adjust_fx = round_fx( L_shl( L_tmp, exp ) ); /*Q15 */ +#endif + } + ELSE + { + fb_ener_adjust_fx = 0; + move16(); + } + + fb_ener_adjust_fx = s_min( fb_ener_adjust_fx, 16384 ); /*Q15 */ + idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl( 1, NUM_BITS_FB_FRAMEGAIN ) ); + } + + /* write FB BWE frame gain to the bitstream */ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + push_indice_fx( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Scalar quantizer routine */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *cb i: quantizer codebook Q10 */ +/* Word16 cb_length i: length of codebook */ +/* Word16 cb_dim i: dimension of codebook */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *x i/o: energy of WB envelop Q10 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ + Word16 *x, /* i/o: energy of WB envelop Q10*/ + const Word16 *cb, /* i: quantizer codebook Q10 */ + const Word16 cb_length, /* i: length of codebook */ + const Word16 cb_dim /* i: dimension of codebook */ +) +{ + Word16 i, j, indx = 0; + Word32 dist, min_dist; + const Word16 *pit = cb; /*Q10 */ + Word16 tmp; + Word32 L_tmp; + + min_dist = MAX_32; + move32(); + FOR( i = 0; i < cb_length; i++ ) + { + dist = L_deposit_l( 0 ); + FOR( j = 0; j < cb_dim; j++ ) + { +#ifdef BASOP_NOGLOB + tmp = sub_sat( x[j], *pit ); /*Q10 */ + L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ + dist = L_add_sat( dist, L_tmp ); +#else + tmp = sub( x[j], *pit ); /*Q10 */ + L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ + dist = L_add( dist, L_tmp ); +#endif + pit++; + } + + IF( LT_32( dist, min_dist ) ) + { + min_dist = dist; + move32(); + indx = i; + move16(); + } + } + + FOR( j = 0; j < cb_dim; j++ ) + { + x[j] = cb[cb_dim * indx + j]; + move16(); + } return ( indx ); } -static void get_normalize_spec_fx( - const Word16 core, /* i : core selected */ - const Word16 extl, /* i : extension layer selected */ - const Word16 mode, /* i : SHB BWE class */ - const Word16 core_type, /* i : coding type */ - const Word16 *org_fx, /* i : input spectrum */ - Word16 *SWB_signal, /* o : output spectrum */ - Word16 *prev_L_swb_norm, /* i : previous norm. len */ - const Word16 offset, /* i : frequency offset */ - Word16 Q_new_lf ) -{ - Word16 n_freq, L_swb_norm; - Word32 envelope[L_FRAME32k]; - Word16 frq_end; - Word16 tmp; - Word16 exp; - Word32 L_tmp_m; +static void get_normalize_spec_fx( + const Word16 core, /* i : core selected */ + const Word16 extl, /* i : extension layer selected */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 core_type, /* i : coding type */ + const Word16 *org_fx, /* i : input spectrum */ + Word16 *SWB_signal, /* o : output spectrum */ + Word16 *prev_L_swb_norm, /* i : previous norm. len */ + const Word16 offset, /* i : frequency offset */ + Word16 Q_new_lf ) +{ + Word16 n_freq, L_swb_norm; + Word32 envelope[L_FRAME32k]; + Word16 frq_end; + Word16 tmp; + Word16 exp; + Word32 L_tmp_m; + + set16_fx( SWB_signal, 0, add( HQ_GENERIC_HIGH0, offset ) ); + calc_normal_length_fx( core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm, Q_new_lf ); + test(); + IF( EQ_16( extl, SWB_BWE ) || EQ_16( extl, FB_BWE ) ) + { + IF( EQ_16( mode, HARMONIC ) ) + { + Copy( org_fx, &SWB_signal[add( 240, offset )], 240 ); + Copy( &org_fx[128], &SWB_signal[add( 480, offset )], 80 ); + } + ELSE + { + Copy( &org_fx[112], &SWB_signal[add( 240, offset )], 128 ); + Copy( &org_fx[112], &SWB_signal[add( 368, offset )], 128 ); + Copy( &org_fx[176], &SWB_signal[add( 496, offset )], 64 ); + } + frq_end = add( 560, offset ); + } + ELSE IF( EQ_16( extl, WB_BWE ) ) + { + IF( core_type == 0 ) + { + Copy( &org_fx[160], &SWB_signal[240], 80 ); + } + ELSE + { + Copy( &org_fx[80], &SWB_signal[240], 80 ); + } + frq_end = L_FRAME16k; + move16(); + } + ELSE + { + Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH0, offset ), HQ_GENERIC_LEN0 ); + Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH1, offset ), HQ_GENERIC_LEN0 ); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_24K4 ) ) + { + Copy( org_fx + HQ_GENERIC_LOW0, SWB_signal + add( HQ_GENERIC_HIGH2, offset ), sub( HQ_GENERIC_END_FREQ, HQ_GENERIC_HIGH2 ) ); + } + frq_end = sub( L_FRAME32k, offset ); + } + + /* calculate envelope */ + calc_norm_envelop_fx( SWB_signal, envelope, L_swb_norm, sub( frq_end, offset ), offset ); + + /* Normalize with envelope */ + FOR( n_freq = add( swb_bwe_subband[0], offset ); n_freq < frq_end; n_freq++ ) + { + IF( envelope[n_freq] != 0 ) + { + exp = norm_l( envelope[n_freq] ); + tmp = extract_h( L_shl( envelope[n_freq], exp ) ); + exp = sub( sub( 30, exp ), Q_new_lf ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp_m = L_shr( L_mult0( SWB_signal[n_freq], tmp ), add( exp, Q_new_lf ) ); /*Q15 */ + SWB_signal[n_freq] = extract_l( L_tmp_m ); /*Q15 */ + move16(); + } + ELSE + { + SWB_signal[n_freq] = 1; + move16(); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * FD_BWE_class() + * + * classify signal of above 6.4kHz, can be used for WB/SWB switch + *-------------------------------------------------------------------*/ + +static Word16 FD_BWE_class_fx( /* o : FD BWE class */ + const Word16 *fSpectrum, /* i : input spectrum */ + const Word32 fGain, /* i : global gain */ + const Word16 tilt_nb, /* i : BWE tilt */ + Word16 Q_syn, + Word16 Q_shb, + Encoder_State *st_fx /* i/o: Encoder structure */ +) +{ + Word16 i, j, k, noise, sharpMod = 0; + Word16 peak, mag; + Word32 mean[20]; + Word16 sharpPeak; + const Word16 *input_hi = 0; + Word16 sharp; + Word16 gain_tmp = 0; + Word16 mode; + Word32 L_meanH, L_mean_d, L_tmp; + Word16 sharplimit; + Word16 numsharp, num, den; + Word16 numharmonic, tmp, expn, expd, scale; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + move16(); + + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + mode = NORMAL; + move16(); + k = 0; + move16(); + noise = 0; + move16(); + sharpPeak = 0; + move16(); + numsharp = 0; + move16(); + numharmonic = 4; + move16(); + sharplimit = 10; + move16(); + + L_mean_d = 0L; /* to avoid compilation warnings */ + move32(); + + test(); + IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + { + input_hi = &fSpectrum[256]; + move16(); + numsharp = NUM_SHARP; + move16(); + + test(); + test(); + test(); + IF( ( EQ_16( st_fx->last_extl, SWB_BWE ) && EQ_16( st_fx->extl, SWB_BWE ) ) || ( EQ_16( st_fx->last_extl, FB_BWE ) && EQ_16( st_fx->extl, FB_BWE ) ) ) + { + IF( hBWE_FD->prev_global_gain_fx == 0 ) + { +#ifdef BASOP_NOGLOB + gain_tmp = round_fx_o( L_shl_o( fGain, 30, &Overflow ), &Overflow ); /*Q14 */ +#else + gain_tmp = round_fx( L_shl( fGain, 30 ) ); /*Q14 */ +#endif + } + ELSE + { + expn = norm_l( fGain ); +#ifdef BASOP_NOGLOB + num = extract_h( L_shl_o( fGain, expn, &Overflow ) ); +#else + num = extract_h( L_shl( fGain, expn ) ); +#endif + expn = sub( sub( 30, expn ), shl( Q_shb, 1 ) ); + + expd = norm_l( hBWE_FD->prev_global_gain_fx ); +#ifdef BASOP_NOGLOB + den = extract_h( L_shl_o( hBWE_FD->prev_global_gain_fx, expd, &Overflow ) ); +#else + den = extract_h( L_shl( hBWE_FD->prev_global_gain_fx, expd ) ); +#endif + expd = sub( sub( 30, expd ), shl( st_fx->prev_Q_shb, 1 ) ); + + scale = shr( sub( den, num ), 15 ); +#ifdef BASOP_NOGLOB + num = shl_o( num, scale, &Overflow ); +#else + num = shl( num, scale ); +#endif + expn = sub( expn, scale ); + + tmp = div_s( num, den ); + expn = sub( expn, expd ); +#ifdef BASOP_NOGLOB + gain_tmp = shl_o( tmp, sub( expn, 1 ), &Overflow ); /*Q14 */ +#else + gain_tmp = shl( tmp, sub( expn, 1 ) ); /*Q14 */ +#endif + } + test(); + IF( EQ_16( hBWE_FD->prev_mode, TRANSIENT ) ) + { + numharmonic = shl( numharmonic, 1 ); + } + ELSE IF( EQ_16( hBWE_FD->prev_mode, NORMAL ) || EQ_16( hBWE_FD->prev_mode, NOISE ) ) + { + numharmonic = add( shr( numharmonic, 1 ), numharmonic ); + } + } + ELSE + { + gain_tmp = 16384; + move16(); + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + numharmonic = shr( numharmonic, 1 ); + sharplimit = shr( sharplimit, 1 ); + } + ELSE + { + numharmonic = shl( numharmonic, 1 ); + sharplimit = shl( sharplimit, 1 ); + } + } + } + ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + { + input_hi = &fSpectrum[224]; + move16(); + numsharp = 3; + move16(); + + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + numharmonic = shr( numharmonic, 2 ); + } + ELSE + { + numharmonic = shr( numharmonic, 1 ); + } + IF( NE_16( st_fx->last_extl, WB_BWE ) ) + { + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + sharplimit = shr( sharplimit, 1 ); + } + ELSE + { + sharplimit = shl( sharplimit, 1 ); + } + } + } - set16_fx( SWB_signal, 0, add( HQ_GENERIC_HIGH0, offset ) ); - calc_normal_length_fx( core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm, Q_new_lf ); + L_meanH = L_deposit_l( 0 ); + FOR( i = 0; i < numsharp; i++ ) + { + peak = 0; + move16(); + mean[i] = L_deposit_l( 0 ); + move32(); + + FOR( j = 0; j < SHARP_WIDTH; j++ ) + { + mag = abs_s( *input_hi ); + IF( GT_16( mag, peak ) ) + { + peak = mag; + move16(); /*Q_syn */ + } + mean[i] = L_add( mean[i], mag ); + move32(); /*Q_syn */ + input_hi++; + } + + L_meanH = L_add( L_meanH, mean[i] ); /*Q_syn */ + + IF( NE_32( mean[i], L_deposit_l( peak ) ) ) + { + L_tmp = L_sub( mean[i], peak ); /*Q_syn */ + L_tmp = Mpy_32_16_1( L_tmp, 16913 ); /* 1/31->Q19 -> Q_syn+19-15 */ + den = extract_l( L_shr( L_tmp, 4 ) ); /*Q_syn */ + IF( den == 0 ) + { + den = 1; + move16(); + } + expd = norm_s( den ); + tmp = div_s( shl( 1, sub( 14, expd ) ), den ); /*Q(29-expd-Q_syn) */ + L_tmp = L_mult( tmp, peak ); /*Q(30-expd) */ +#ifdef BASOP_NOGLOB + sharp = round_fx_o( L_shl_o( L_tmp, sub( expd, 4 ), &Overflow ), &Overflow ); /*Q10 */ +#else + sharp = round_fx( L_shl( L_tmp, sub( expd, 4 ) ) ); /*Q10 */ +#endif + } + ELSE + { + sharp = 0; + move16(); + } + + test(); +#ifdef BASOP_NOGLOB + IF( GT_16( sharp, 4608 ) && GT_16( peak, shl_o( 1, add( Q_syn, 3 ), &Overflow ) ) ) +#else + IF( GT_16( sharp, 4608 ) && GT_16( peak, shl( 1, add( Q_syn, 3 ) ) ) ) +#endif + { + k = add( k, 1 ); + move16(); + } + ELSE IF( LT_16( sharp, 3072 ) ) + { + noise = add( noise, 1 ); + move16(); + } + + IF( GT_16( sharp, sharpPeak ) ) + { + sharpPeak = sharp; + move16(); + } + } test(); - IF( EQ_16( extl, SWB_BWE ) || EQ_16( extl, FB_BWE ) ) + IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) { - IF( EQ_16( mode, HARMONIC ) ) + test(); + test(); + test(); + IF( GE_16( k, numharmonic ) && GT_16( gain_tmp, 8192 ) && LT_16( gain_tmp, 29491 ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) { - Copy( org_fx, &SWB_signal[add( 240, offset )], 240 ); - Copy( &org_fx[128], &SWB_signal[add( 480, offset )], 80 ); + sharpMod = 1; + move16(); } ELSE { - Copy( &org_fx[112], &SWB_signal[add( 240, offset )], 128 ); - Copy( &org_fx[112], &SWB_signal[add( 368, offset )], 128 ); - Copy( &org_fx[176], &SWB_signal[add( 496, offset )], 64 ); + sharpMod = 0; + move16(); + } + + L_meanH = Mpy_32_16_1( L_meanH, 29127 ); /*Q_syn+8 */ + L_mean_d = 0; + move16(); + FOR( i = 0; i < NUM_SHARP; i++ ) + { + L_tmp = L_sub( L_shl( mean[i], 8 - 5 ), L_meanH ); /*Q_syn+8 */ + L_mean_d = L_add( L_mean_d, L_abs( L_tmp ) ); /*Q_syn+8 */ } - frq_end = add( 560, offset ); } - ELSE IF( EQ_16( extl, WB_BWE ) ) + ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) { - IF( core_type == 0 ) + test(); + IF( GE_16( k, numharmonic ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) { - Copy( &org_fx[160], &SWB_signal[240], 80 ); + sharpMod = 1; + move16(); } ELSE { - Copy( &org_fx[80], &SWB_signal[240], 80 ); + sharpMod = 0; + move16(); } - frq_end = L_FRAME16k; + } + + test(); + test(); + IF( sharpMod && LT_16( hBWE_FD->modeCount, 12 ) ) + { + hBWE_FD->modeCount = add( hBWE_FD->modeCount, 1 ); move16(); } - ELSE + ELSE IF( sharpMod == 0 && hBWE_FD->modeCount > 0 ) { - Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH0, offset ), HQ_GENERIC_LEN0 ); - Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH1, offset ), HQ_GENERIC_LEN0 ); - IF( EQ_16( offset, HQ_GENERIC_FOFFSET_24K4 ) ) + hBWE_FD->modeCount = sub( hBWE_FD->modeCount, 1 ); + move16(); + } + + IF( GE_16( hBWE_FD->modeCount, 2 ) ) + { + sharpMod = 1; + move16(); + } + + test(); + IF( sharpMod ) + { + mode = HARMONIC; + move16(); + } + ELSE IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + { + L_tmp = Mpy_32_16_1( L_mean_d, 6827 ); /*Q_syn+8 ; 1/4.8 in Q15 */ + + test(); + test(); + test(); + IF( GT_16( noise, 4 ) && ( LT_32( L_tmp, L_meanH ) || L_meanH == 0 ) && LT_16( tilt_nb, 10240 ) ) { - Copy( org_fx + HQ_GENERIC_LOW0, SWB_signal + add( HQ_GENERIC_HIGH2, offset ), sub( HQ_GENERIC_END_FREQ, HQ_GENERIC_HIGH2 ) ); + mode = NOISE; + move16(); } - frq_end = sub( L_FRAME32k, offset ); } - /* calculate envelope */ - calc_norm_envelop_fx( SWB_signal, envelope, L_swb_norm, sub( frq_end, offset ), offset ); - - /* Normalize with envelope */ - FOR( n_freq = add( swb_bwe_subband[0], offset ); n_freq < frq_end; n_freq++ ) + return ( mode ); +} + +/*-------------------------------------------------------------------* + * freq_weights_fx() + * + *-------------------------------------------------------------------*/ +static void freq_weights_fx( + const Word16 Band_Ener[], /* i : Band energy Q8 */ + const Word16 f_weighting[], /* i : weigting coefs. Q15 */ + Word16 w_env[], /* o : Freq. weighting Q13 */ + const Word16 Nbands /* i : Number of bands */ +) +{ + Word16 i; + Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; + Word16 min_b, max_b; + Word32 L_tmp; + Word16 exp; + + /* Find Max band energy */ + min_b = Band_Ener[0]; + move16(); + max_b = Band_Ener[0]; + move16(); + FOR( i = 1; i < Nbands; i++ ) + { + if ( LT_16( Band_Ener[i], min_b ) ) + { + min_b = Band_Ener[i]; + move16(); /*Q8 */ + } + + if ( GT_16( Band_Ener[i], max_b ) ) + { + max_b = Band_Ener[i]; + move16(); /*Q8 */ + } + } + + /* Find weighting function */ + tmp = sub( max_b, min_b ); /*Q8 */ + IF( tmp != 0 ) + { + exp = norm_s( tmp ); + tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*(21-exp) */ +#ifdef BASOP_NOGLOB + tmp = shl_sat( tmp, sub( exp, 6 ) ); /*Q15 */ +#else + tmp = shl( tmp, sub( exp, 6 ) ); /*Q15 */ +#endif + } + ELSE + { + tmp = 32767; + move16(); + } + + FOR( i = 0; i < Nbands; i++ ) { - IF( envelope[n_freq] != 0 ) - { - exp = norm_l( envelope[n_freq] ); - tmp = extract_h( L_shl( envelope[n_freq], exp ) ); - exp = sub( sub( 30, exp ), Q_new_lf ); - tmp = div_s( 16384, tmp ); /*Q(15+exp) */ - L_tmp_m = L_shr( L_mult0( SWB_signal[n_freq], tmp ), add( exp, Q_new_lf ) ); /*Q15 */ - SWB_signal[n_freq] = extract_l( L_tmp_m ); /*Q15 */ - } - ELSE - { - SWB_signal[n_freq] = 1; - move16(); - } + tmp1 = sub( Band_Ener[i], min_b ); + L_tmp = L_mult( tmp1, tmp ); /*Q24 */ + L_tmp = L_add( L_tmp, 16777216 ); /*Q24 */ + L_tmp = L_shl( L_tmp, 5 ); /*Q29 */ + w1[i] = round_fx( L_tmp ); /*Q13 */ + move16(); + w2[i] = f_weighting[i]; + move16(); /*Q15 */ /*1~0.75*/ + w_env[i] = mult_r( w1[i], w2[i] ); + move16(); /*Q13 */ } return; } /*-------------------------------------------------------------------* - * FD_BWE_class() + * vqWithCand_w_fx() * - * classify signal of above 6.4kHz, can be used for WB/SWB switch *-------------------------------------------------------------------*/ -static Word16 FD_BWE_class_fx( /* o : FD BWE class */ - const Word16 *fSpectrum, /* i : input spectrum */ - const Word32 fGain, /* i : global gain */ - const Word16 tilt_nb, /* i : BWE tilt */ - Word16 Q_syn, - Word16 Q_shb, - Encoder_State *st_fx /* i/o: Encoder structure */ +static void vqWithCand_w_fx( + const Word16 *x, /* i : input vector Q8 */ + const Word16 *E_ROM_dico, /* i : codebook Q8 */ + const Word16 dim, /* i : codebook dimension */ + const Word16 E_ROM_dico_size, /* i : codebook size */ + Word16 *index, /* o : survivors indices */ + const Word16 surv, /* i : survivor number */ + Word32 dist_min[], /* o : minimum distortion Q5 */ + const Word16 *w, /* i : weighting Q13*/ + const Word16 flag /* i : flag indicationg weighted distortion metric */ ) { - Word16 i, j, k, noise, sharpMod = 0; - Word16 peak, mag; - Word32 mean[20]; - Word16 sharpPeak; - const Word16 *input_hi = 0; - Word16 sharp; - Word16 gain_tmp = 0; - Word16 mode; - Word32 L_meanH, L_mean_d, L_tmp; - Word16 sharplimit; - Word16 numsharp, num, den; - Word16 numharmonic, tmp, expn, expd, scale; + Word16 i, j, k, l; + const Word16 *p_E_ROM_dico; + Word16 dist, temp1; + Word32 L_dist, L_tmp; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + IF( flag ) + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - - mode = NORMAL; - move16(); - k = 0; - move16(); - noise = 0; - move16(); - sharpPeak = 0; - move16(); - numsharp = 0; - move16(); - numharmonic = 4; - move16(); - sharplimit = 10; - move16(); - - L_mean_d = 0L; /* to avoid compilation warnings */ + FOR( i = 0; i < surv; i++ ) + { + index[i] = i; + move16(); + } - test(); - IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) - { - input_hi = &fSpectrum[256]; - move16(); - numsharp = NUM_SHARP; + p_E_ROM_dico = E_ROM_dico; move16(); - test(); - test(); - test(); - IF( ( EQ_16( st_fx->last_extl, SWB_BWE ) && EQ_16( st_fx->extl, SWB_BWE ) ) || ( EQ_16( st_fx->last_extl, FB_BWE ) && EQ_16( st_fx->extl, FB_BWE ) ) ) + FOR( i = 0; i < E_ROM_dico_size; i++ ) { - IF( hBWE_FD->prev_global_gain_fx == 0 ) - { #ifdef BASOP_NOGLOB - gain_tmp = round_fx_o( L_shl_o( fGain, 30, &Overflow ), &Overflow ); /*Q14 */ + dist = sub_o( x[0], *p_E_ROM_dico++, &Overflow ); /*Q8 */ #else - gain_tmp = round_fx( L_shl( fGain, 30 ) ); /*Q14 */ + dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ #endif - } - ELSE + L_dist = L_mult( dist, w[0] ); /*Q22 */ + L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ + L_dist = L_shr( L_dist, 10 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - expn = norm_l( fGain ); #ifdef BASOP_NOGLOB - num = extract_h( L_shl_o( fGain, expn, &Overflow ) ); + temp1 = sub_o( x[j], *p_E_ROM_dico++, &Overflow ); #else - num = extract_h( L_shl( fGain, expn ) ); + temp1 = sub( x[j], *p_E_ROM_dico++ ); #endif - expn = sub( sub( 30, expn ), shl( Q_shb, 1 ) ); + L_tmp = L_mult( temp1, w[j] ); /*Q22 */ + L_tmp = Mult_32_16( L_tmp, temp1 ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ + } - expd = norm_l( hBWE_FD->prev_global_gain_fx ); -#ifdef BASOP_NOGLOB - den = extract_h( L_shl_o( hBWE_FD->prev_global_gain_fx, expd, &Overflow ) ); -#else - den = extract_h( L_shl( hBWE_FD->prev_global_gain_fx, expd ) ); -#endif - expd = sub( sub( 30, expd ), shl( st_fx->prev_Q_shb, 1 ) ); + FOR( k = 0; k < surv; k++ ) + { + IF( LT_32( L_dist, dist_min[k] ) ) + { + FOR( l = sub( surv, 1 ); l > k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + ELSE + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - scale = shr( sub( den, num ), 15 ); -#ifdef BASOP_NOGLOB - num = shl_o( num, scale, &Overflow ); -#else - num = shl( num, scale ); -#endif - expn = sub( expn, scale ); + FOR( i = 0; i < surv; i++ ) + { + index[i] = i; + move16(); + } - tmp = div_s( num, den ); - expn = sub( expn, expd ); + p_E_ROM_dico = E_ROM_dico; + move16(); + + FOR( i = 0; i < E_ROM_dico_size; i++ ) + { #ifdef BASOP_NOGLOB - gain_tmp = shl_o( tmp, sub( expn, 1 ), &Overflow ); /*Q14 */ + dist = sub_sat( x[0], *p_E_ROM_dico++ ); /*Q8 */ #else - gain_tmp = shl( tmp, sub( expn, 1 ) ); /*Q14 */ + dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ #endif - } - test(); - IF( EQ_16( hBWE_FD->prev_mode, TRANSIENT ) ) + L_dist = L_mult( dist, dist ); /*Q17 */ + L_dist = L_shr( L_dist, 12 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - numharmonic = shl( numharmonic, 1 ); + temp1 = sub( x[j], *p_E_ROM_dico++ ); /*Q8 */ + L_tmp = L_mult( temp1, temp1 ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - ELSE IF( EQ_16( hBWE_FD->prev_mode, NORMAL ) || EQ_16( hBWE_FD->prev_mode, NOISE ) ) + + FOR( k = 0; k < surv; k++ ) { - numharmonic = add( shr( numharmonic, 1 ), numharmonic ); + IF( LT_32( L_dist, dist_min[k] ) ) + { + FOR( l = sub( surv, 1 ); l > k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } } } - ELSE + } + + return; +} + +/*-------------------------------------------------------------------* + * vqSimple_w_fx() + * + *-------------------------------------------------------------------*/ + +static Word16 vqSimple_w_fx( + const Word16 *x, /* i : input for quantizer Q8 */ + Word16 *y, /* i : quantized value Q8 */ + const Word16 *cb, /* i : codebooks Q8 */ + const Word16 *w, /* i : weight Q13 */ + const Word16 dim, /* i : dimension */ + const Word16 l, /* i : number of candidates */ + const Word16 flag /* i : flag indicationg weighted distortion metric */ +) +{ + Word16 i, j, index; + const Word16 *cbP; + Word16 dist, temp; + Word32 L_dist, L_tmp, L_dist_min; + + index = 0; + move16(); + L_dist_min = L_add( MAX_32, 0 ); /* FLT_MAX */ + cbP = cb; + move16(); + IF( flag ) + { + FOR( i = 0; i < l; i++ ) { - gain_tmp = 16384; - move16(); - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + /*dist = x[0] - *cbP++; */ + /*dist *= (dist * w[0]); */ + dist = sub( x[0], *cbP++ ); /*Q8 */ + L_dist = L_mult( dist, w[0] ); /*Q22 */ + L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ + L_dist = L_shr( L_dist, 10 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - numharmonic = shr( numharmonic, 1 ); - sharplimit = shr( sharplimit, 1 ); + /*temp = x[j] - *cbP++; */ + /*dist += temp * temp * w[j]; */ + temp = sub( x[j], *cbP++ ); + L_tmp = L_mult( temp, w[j] ); /*Q22 */ + L_tmp = Mult_32_16( L_tmp, temp ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ } - ELSE + IF( LT_32( L_dist, L_dist_min ) ) { - numharmonic = shl( numharmonic, 1 ); - sharplimit = shl( sharplimit, 1 ); + L_dist_min = L_add( L_dist, 0 ); /*Q5 */ + index = i; + move16(); } } } - ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + ELSE { - input_hi = &fSpectrum[224]; - move16(); - numsharp = 3; - move16(); - - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) - { - numharmonic = shr( numharmonic, 2 ); - } - ELSE - { - numharmonic = shr( numharmonic, 1 ); - } - IF( NE_16( st_fx->last_extl, WB_BWE ) ) + FOR( i = 0; i < l; i++ ) { - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + /*dist = x[0] - *cbP++; */ + dist = sub( x[0], *cbP++ ); + /*dist *= dist; */ + L_dist = L_mult( dist, dist ); /*Q17 */ + L_dist = L_shr( L_dist, 12 ); + + FOR( j = 1; j < dim; j++ ) { - sharplimit = shr( sharplimit, 1 ); + /*temp = x[j] - *cbP++; */ + temp = sub( x[j], *cbP++ ); + /*dist += temp * temp; */ + L_tmp = L_mult( temp, temp ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - ELSE + IF( LT_32( L_dist, L_dist_min ) ) { - sharplimit = shl( sharplimit, 1 ); + L_dist_min = L_add( L_dist, 0 ); + index = i; + move16(); } } } - L_meanH = L_deposit_l( 0 ); - FOR( i = 0; i < numsharp; i++ ) + + /* Reading the selected vector */ + Copy( &cb[i_mult( index, dim )], y, dim ); + + return ( index ); +} + + +/*-------------------------------------------------------------------* + * MSVQ_Interpol_Tran_fx() + * + *-------------------------------------------------------------------*/ +static void MSVQ_Interpol_Tran_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ + Word16 *indice /* o : quantized index */ +) + +{ + Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2], tmp; + Word16 env_temp11[SWB_FENV_TRANS / 2], env_temp12[SWB_FENV_TRANS / 2]; + Word16 tmp_q; + Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; + Word16 quant_select[SWB_FENV_TRANS]; + Word32 L_tmp, L_dist, L_minDist, distCand[N_CAND_TR]; + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - peak = 0; - move16(); - mean[i] = L_deposit_l( 0 ); + env_temp11[n_band] = SWB_env_energy[2 * n_band]; + move16(); /*Q8 */ + env_temp12[n_band] = SWB_env_energy[2 * n_band + 1]; + move16(); /*Q8 */ + } - FOR( j = 0; j < SHARP_WIDTH; j++ ) - { - mag = abs_s( *input_hi ); - IF( GT_16( mag, peak ) ) - { - peak = mag; - move16(); /*Q_syn */ - } - mean[i] = L_add( mean[i], mag ); - move32(); /*Q_syn */ - input_hi++; - } + vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); - L_meanH = L_add( L_meanH, mean[i] ); /*Q_syn */ + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - IF( NE_32( mean[i], L_deposit_l( peak ) ) ) + FOR( k = 0; k < N_CAND_TR; k++ ) + { + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - L_tmp = L_sub( mean[i], peak ); /*Q_syn */ - L_tmp = Mult_32_16( L_tmp, 16913 ); /* 1/31->Q19 -> Q_syn+19-15 */ - den = extract_l( L_shr( L_tmp, 4 ) ); /*Q_syn */ - IF( den == 0 ) - { - den = 1; - move16(); - } - expd = norm_s( den ); - tmp = div_s( shl( 1, sub( 14, expd ) ), den ); /*Q(29-expd-Q_syn) */ - L_tmp = L_mult( tmp, peak ); /*Q(30-expd) */ -#ifdef BASOP_NOGLOB - sharp = round_fx_o( L_shl_o( L_tmp, sub( expd, 4 ), &Overflow ), &Overflow ); /*Q10 */ -#else - sharp = round_fx( L_shl( L_tmp, sub( expd, 4 ) ) ); /*Q10 */ -#endif + quant_tmp[n_band] = Env_TR_Cdbk1_fx[add( shl( candInd[k], 1 ), n_band )]; + move16(); /*DIM_TR1 == 2*/ } - ELSE + + FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) { - sharp = 0; - move16(); + /*quant_tmp2[n_band] = env_temp12[n_band] - ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f); */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ + tmp = shr( tmp, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); + move16(); /*Q8 */ } + /*quant_tmp2[n_band] = env_temp12[n_band] - quant_tmp[n_band]; */ + quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); + move16(); /*Q8 */ + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, Env_TR_Cdbk2_fx, NULL, DIM_TR2, N_CB_TR2, 0 ); + move16(); - test(); -#ifdef BASOP_NOGLOB - IF( GT_16( sharp, 4608 ) && GT_16( peak, shl_o( 1, add( Q_syn, 3 ), &Overflow ) ) ) -#else - IF( GT_16( sharp, 4608 ) && GT_16( peak, shl( 1, add( Q_syn, 3 ) ) ) ) -#endif + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - k = add( k, 1 ); + quant_select[n_band * 2] = quant_tmp[n_band]; move16(); } - ELSE IF( LT_16( sharp, 3072 ) ) + + FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) { - noise = add( noise, 1 ); + /*quant_select[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f) + quant_tmp2[n_band]; */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ + tmp = shr( tmp, 1 ); + quant_select[n_band * 2 + 1] = add( tmp, quant_tmp2[n_band] ); move16(); } + /*quant_select[n_band*2+1] = quant_tmp[n_band]+quant_tmp2[n_band]; */ + quant_select[n_band * 2 + 1] = add( quant_tmp[n_band], quant_tmp2[n_band] ); + move16(); - IF( GT_16( sharp, sharpPeak ) ) + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) { - sharpPeak = sharp; - move16(); + /*tmp_q = SWB_env_energy[n_band] - quant_select[n_band]; */ + tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); + /*dist += tmp_q*tmp_q; */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - } - test(); - IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) - { - test(); - test(); - test(); - IF( GE_16( k, numharmonic ) && GT_16( gain_tmp, 8192 ) && LT_16( gain_tmp, 29491 ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) + + /* Check optimal candidate */ + IF( LT_32( L_dist, L_minDist ) ) { - sharpMod = 1; + L_minDist = L_add( L_dist, 0 ); + indice[0] = candInd[k]; move16(); - } - ELSE - { - sharpMod = 0; + indice[1] = ind_tmp[0]; move16(); } - - L_meanH = Mult_32_16( L_meanH, 29127 ); /*Q_syn+8 */ - L_mean_d = 0; - move16(); - FOR( i = 0; i < NUM_SHARP; i++ ) - { - L_tmp = L_sub( L_shl( mean[i], 8 - 5 ), L_meanH ); /*Q_syn+8 */ - L_mean_d = L_add( L_mean_d, L_abs( L_tmp ) ); /*Q_syn+8 */ - } } - ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + return; +} + +/*-------------------------------------------------------------------* + * MSVQ_Interpol_fx() + * + *-------------------------------------------------------------------*/ + +static void msvq_interpol_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8*/ + Word16 *w_env, /* i/o : weighting coffecients Q13*/ + Word16 *indice /* o : quantized index */ +) +{ + Word16 k, n_band, n_band2, n_band2p1, candInd[N_CAND], ind_tmp[4]; + Word16 tmp_q; + Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; + Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; + Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2], tmp; + Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; + Word16 synth_energy[SWB_FENV]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - test(); - IF( GE_16( k, numharmonic ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) - { - sharpMod = 1; - move16(); - } - ELSE - { - sharpMod = 0; - move16(); - } + n_band2 = shl( n_band, 1 ); + n_band2p1 = add( n_band2, 1 ); + env_temp11[n_band] = SWB_env_energy[n_band2]; + move16(); /*Q8 */ + env_temp12[n_band] = SWB_env_energy[n_band2p1]; + move16(); /*Q8 */ + + w_env11[n_band] = w_env[n_band2]; + move16(); /*Q13 */ + w_env12[n_band] = w_env[n_band2p1]; + move16(); /*Q13 */ } - test(); - test(); - IF( sharpMod && LT_16( hBWE_FD->modeCount, 12 ) ) - { - hBWE_FD->modeCount = add( hBWE_FD->modeCount, 1 ); - } - ELSE IF( sharpMod == 0 && hBWE_FD->modeCount > 0 ) - { - hBWE_FD->modeCount = sub( hBWE_FD->modeCount, 1 ); - } + vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); - IF( GE_16( hBWE_FD->modeCount, 2 ) ) - { - sharpMod = 1; - move16(); - } + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - test(); - IF( sharpMod ) - { - mode = HARMONIC; - move16(); - } - ELSE IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + FOR( k = 0; k < N_CAND; k++ ) { - L_tmp = Mult_32_16( L_mean_d, 6827 ); /*Q_syn+8 ; 1/4.8 in Q15 */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) + { + quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; + move16(); /*Q8 */ + quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); + move16(); /*Q8 */ + } - test(); - test(); - test(); - IF( GT_16( noise, 4 ) && ( LT_32( L_tmp, L_meanH ) || L_meanH == 0 ) && LT_16( tilt_nb, 10240 ) ) + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); + ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); + + /* Extract vector for odd position */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - mode = NOISE; +#ifdef BASOP_NOGLOB + quant_tmp[n_band] = add_o( quant_tmp1[n_band], quant_tmp2[n_band], &Overflow ); +#else + quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); +#endif move16(); } - } - - return ( mode ); -} -/*-------------------------------------------------------------------* - * freq_weights_fx() - * - *-------------------------------------------------------------------*/ -static void freq_weights_fx( - const Word16 Band_Ener[], /* i : Band energy Q8 */ - const Word16 f_weighting[], /* i : weigting coefs. Q15 */ - Word16 w_env[], /* o : Freq. weighting Q13 */ - const Word16 Nbands /* i : Number of bands */ -) -{ - Word16 i; - Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; - Word16 min_b, max_b; - Word32 L_tmp; - Word16 exp; - /* Find Max band energy */ - min_b = Band_Ener[0]; - move16(); - max_b = Band_Ener[0]; - move16(); - FOR( i = 1; i < Nbands; i++ ) - { - if ( LT_16( Band_Ener[i], min_b ) ) + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) { - min_b = Band_Ener[i]; +#ifdef BASOP_NOGLOB + tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); /*Q8 */ +#else + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ +#endif + tmp = shr( tmp, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); move16(); /*Q8 */ } - if ( GT_16( Band_Ener[i], max_b ) ) + /*quant_tmp2[n_band] = env_temp12[n_band]-quant_tmp[n_band]; */ + quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); + move16(); /*Q8 */ + + ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); + move16(); + ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk4th_fx, w_env12 + DIM3RD, DIM4TH, N_CB4TH, 1 ); + move16(); + + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - max_b = Band_Ener[i]; + quant_select[n_band * 2] = quant_tmp[n_band]; move16(); /*Q8 */ } - } - /* Find weighting function */ - tmp = sub( max_b, min_b ); /*Q8 */ - IF( tmp != 0 ) - { - exp = norm_s( tmp ); - tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*(21-exp) */ + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + { #ifdef BASOP_NOGLOB - tmp = shl_sat( tmp, sub( exp, 6 ) ); /*Q15 */ + tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); #else - tmp = shl( tmp, sub( exp, 6 ) ); /*Q15 */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); #endif - } - ELSE - { - tmp = 32767; - move16(); - } + tmp = shr( tmp, 1 ); + quant_select[add( shl( n_band, 1 ), 1 )] = add( tmp, quant_tmp2[n_band] ); + move16(); /*Q8 */ + } + quant_select[add( shl( n_band, 1 ), 1 )] = add( quant_tmp[n_band], quant_tmp2[n_band] ); + move16(); /*Q8 */ - FOR( i = 0; i < Nbands; i++ ) - { - tmp1 = sub( Band_Ener[i], min_b ); - L_tmp = L_mult( tmp1, tmp ); /*Q24 */ - L_tmp = L_add( L_tmp, 16777216 ); /*Q24 */ - L_tmp = L_shl( L_tmp, 5 ); /*Q29 */ - w1[i] = round_fx( L_tmp ); /*Q13 */ - move16(); - w2[i] = f_weighting[i]; - move16(); /*Q15 */ /*1~0.75*/ - w_env[i] = mult_r( w1[i], w2[i] ); - move16(); /*Q13 */ + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) + { + tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); /*Q8 */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + } + + /* Check optimal candidate */ + IF( LT_32( L_dist, L_minDist ) ) + { + L_minDist = L_add( L_dist, 0 ); + + Copy( quant_select, synth_energy, SWB_FENV ); + + indice[0] = candInd[k]; + move16(); + indice[1] = ind_tmp[0]; + move16(); + indice[2] = ind_tmp[1]; + move16(); + indice[3] = ind_tmp[2]; + move16(); + indice[4] = ind_tmp[3]; + move16(); + } } + Copy( synth_energy, SWB_env_energy, SWB_FENV ); + return; } /*-------------------------------------------------------------------* - * vqWithCand_w_fx() + * msvq_interpol_2_fx() * *-------------------------------------------------------------------*/ -static void vqWithCand_w_fx( - const Word16 *x, /* i : input vector Q8 */ - const Word16 *E_ROM_dico, /* i : codebook Q8 */ - const Word16 dim, /* i : codebook dimension */ - const Word16 E_ROM_dico_size, /* i : codebook size */ - Word16 *index, /* o : survivors indices */ - const Word16 surv, /* i : survivor number */ - Word32 dist_min[], /* o : minimum distortion Q5 */ - const Word16 *w, /* i : weighting Q13*/ - const Word16 flag /* i : flag indicationg weighted distortion metric */ +static void msvq_interpol_2_fx( + Word16 *hq_generic_fenv, /* i/o: (original/quantized) energy */ + const Word16 *w_env, /* i : weighting coffecients */ + Word16 *indice, /* o : quantized index */ + const Word16 nenv /* i : the number of envelopes */ ) { - Word16 i, j, k, l; - const Word16 *p_E_ROM_dico; - Word16 dist, temp1; - Word32 L_dist, L_tmp; + Word16 k, n_band, n_band2, candInd[N_CAND], ind_tmp[4]; + Word16 tmp_q; + Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; + Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; + Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2]; + Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; + Word16 synth_energy[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; move32(); #endif - IF( flag ) + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM11 - 1; n_band++ ) { - set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ + n_band2 = shl( n_band, 1 ); + env_temp11[n_band] = hq_generic_fenv[n_band2]; + move16(); /*Q8 */ + w_env11[n_band] = w_env[n_band2]; + move16(); /*Q13 */ + } + env_temp11[DIM11 - 1] = hq_generic_fenv[2 * ( DIM11 - 2 ) + 1]; + move16(); /*Q8 */ + w_env11[DIM11 - 1] = w_env[2 * ( DIM11 - 2 ) + 1]; + move16(); /*Q13 */ - FOR( i = 0; i < surv; i++ ) + env_temp12[0] = hq_generic_fenv[0]; + move16(); /*Q8 */ + w_env12[0] = w_env[0]; + move16(); /*Q13 */ + FOR( n_band = 1; n_band < DIM11 - 1; n_band++ ) + { + n_band2 = sub( shl( n_band, 1 ), 1 ); + env_temp12[n_band] = hq_generic_fenv[n_band2 /*2*n_band-1*/]; + move16(); /*Q8 */ + w_env12[n_band] = w_env[n_band2 /*2*n_band-1*/]; + move16(); /*Q13 */ + } + + vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); + + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + FOR( k = 0; k < N_CAND; k++ ) + { + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - index[i] = i; + quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; + move16(); /*Q8 */ + quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); + move16(); /*Q8 */ + } + + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); + move16(); + ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); + move16(); + + /* Extract vector for odd position */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) + { + quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); + move16(); + } + + quant_tmp2[0] = sub( env_temp12[0], quant_tmp[0] ); + move16(); + FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + { +#ifdef BASOP_NOGLOB + tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); + tmp_q = shr( tmp_q, 1 ); + quant_tmp2[n_band] = sub_o( env_temp12[n_band], tmp_q, &Overflow ); +#else + tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); + tmp_q = shr( tmp_q, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp_q ); +#endif move16(); } - p_E_ROM_dico = E_ROM_dico; + ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); + move16(); + ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk3rd_fx, w_env12 + DIM3RD, DIM3RD, N_CB3RD, 1 ); move16(); - FOR( i = 0; i < E_ROM_dico_size; i++ ) + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) { -#ifdef BASOP_NOGLOB - dist = sub_o( x[0], *p_E_ROM_dico++, &Overflow ); /*Q8 */ -#else - dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#endif - L_dist = L_mult( dist, w[0] ); /*Q22 */ - L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ - L_dist = L_shr( L_dist, 10 ); /*Q5 */ + quant_select[n_band * 2] = quant_tmp[n_band]; + move16(); /*Q8 */ + } + quant_select[11] = quant_tmp[DIM12 - 1]; + move16(); /*Q8 */ - FOR( j = 1; j < dim; j++ ) - { + quant_select[0] = add( quant_select[0], quant_tmp2[0] ); + move16(); /*Q8 */ + FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + { #ifdef BASOP_NOGLOB - temp1 = sub_o( x[j], *p_E_ROM_dico++, &Overflow ); + tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); + tmp_q = shr( tmp_q, 1 ); + quant_select[sub( shl( n_band, 1 ), 1 )] = add_o( quant_tmp2[n_band], tmp_q, &Overflow ); #else - temp1 = sub( x[j], *p_E_ROM_dico++ ); + tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); + tmp_q = shr( tmp_q, 1 ); + quant_select[sub( shl( n_band, 1 ), 1 )] = add( quant_tmp2[n_band], tmp_q ); #endif - L_tmp = L_mult( temp1, w[j] ); /*Q22 */ - L_tmp = Mult_32_16( L_tmp, temp1 ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ - } - - FOR( k = 0; k < surv; k++ ) - { - IF( LT_32( L_dist, dist_min[k] ) ) - { - FOR( l = sub( surv, 1 ); l > k; l-- ) - { - dist_min[l] = dist_min[l - 1]; - move32(); - index[l] = index[l - 1]; - move16(); - } - dist_min[k] = L_dist; - move32(); - index[k] = i; - move16(); - BREAK; - } - } } - } - ELSE - { - set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - FOR( i = 0; i < surv; i++ ) + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV - 2; n_band++ ) { - index[i] = i; - move16(); + tmp_q = sub( hq_generic_fenv[n_band], quant_select[n_band] ); /*Q8 */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); } - p_E_ROM_dico = E_ROM_dico; - move16(); - - FOR( i = 0; i < E_ROM_dico_size; i++ ) + /* Check optimal candidate */ + IF( L_dist < L_minDist ) { -#ifdef BASOP_NOGLOB - dist = sub_sat( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#else - dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#endif - L_dist = L_mult( dist, dist ); /*Q17 */ - L_dist = L_shr( L_dist, 12 ); /*Q5 */ - - FOR( j = 1; j < dim; j++ ) - { - temp1 = sub( x[j], *p_E_ROM_dico++ ); /*Q8 */ - L_tmp = L_mult( temp1, temp1 ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ - } + L_minDist = L_add( L_dist, 0 ); + Copy( quant_select, synth_energy, SWB_FENV - 2 ); + synth_energy[SWB_FENV - 2] = 0; + move16(); + synth_energy[SWB_FENV - 1] = 0; + move16(); - FOR( k = 0; k < surv; k++ ) - { - IF( LT_32( L_dist, dist_min[k] ) ) - { - FOR( l = sub( surv, 1 ); l > k; l-- ) - { - dist_min[l] = dist_min[l - 1]; - move32(); - index[l] = index[l - 1]; - move16(); - } - dist_min[k] = L_dist; - move32(); - index[k] = i; - move16(); - BREAK; - } - } + indice[0] = candInd[k]; + move16(); + indice[1] = ind_tmp[0]; + move16(); + indice[2] = ind_tmp[1]; + move16(); + indice[3] = ind_tmp[2]; + move16(); + indice[4] = ind_tmp[3]; + move16(); } } + Copy( synth_energy, hq_generic_fenv, nenv ); + return; } + /*-------------------------------------------------------------------* - * vqSimple_w_fx() + * calculate_Tonality_fx() * + * Calculate tonality *-------------------------------------------------------------------*/ -static Word16 vqSimple_w_fx( - const Word16 *x, /* i : input for quantizer Q8 */ - Word16 *y, /* i : quantized value Q8 */ - const Word16 *cb, /* i : codebooks Q8 */ - const Word16 *w, /* i : weight Q13 */ - const Word16 dim, /* i : dimension */ - const Word16 l, /* i : number of candidates */ - const Word16 flag /* i : flag indicationg weighted distortion metric */ +static void calculate_Tonality_fx( + const Word16 *org, /* i : MDCT coefficients of original Q_new*/ + const Word16 *gen, /* i : MDCT coefficients of generated signal Q15*/ + Word16 *SFM_org, /* o : Spectral Flatness results Q12*/ + Word16 *SFM_gen, /* o : Spectral Flatness results Q12*/ + const Word16 length /* i : length for calculating tonality */ ) { - Word16 i, j, index; - const Word16 *cbP; - Word16 dist, temp; - Word32 L_dist, L_tmp, L_dist_min; + Word16 n_coeff; + Word16 inv_len, max; + Word16 exp, e_tmp, f_tmp; + Word32 L_tmp, L_tmp2, L_am_org, L_am_gen, L_tmp1; + Word16 org_spec[80], gen_spec[80]; + Word32 L_log_gm_org, L_log_gm_gen; + Word16 l_shift; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif - index = 0; + /* to reduce dynamic range of original spectrum */ + max = 0; move16(); - L_dist_min = L_add( MAX_32, 0 ); /* FLT_MAX */ - cbP = cb; + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + org_spec[n_coeff] = abs_s( org[n_coeff] ); + move16(); /*Q_new */ + /*test(); */ + /*if( sub(max, org_spec[n_coeff]) < 0) */ + /*{ */ + /* max = org_spec[n_coeff];move16();//Q_new */ + /*} */ + max = s_max( max, org_spec[n_coeff] ); + } + l_shift = norm_s( max ); + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + org_spec[n_coeff] = shl( org_spec[n_coeff], l_shift ); + move16(); + IF( org_spec[n_coeff] == 0 ) + { + org_spec[n_coeff] = shl( 1, l_shift ); + move16(); + } + } + + max = 0; move16(); - IF( flag ) + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) { - FOR( i = 0; i < l; i++ ) + gen_spec[n_coeff] = abs_s( gen[n_coeff] ); + move16(); /*Q15 */ + /*test(); + if( sub(max,gen_spec[n_coeff]) < 0) { - /*dist = x[0] - *cbP++; */ - /*dist *= (dist * w[0]); */ - dist = sub( x[0], *cbP++ ); /*Q8 */ - L_dist = L_mult( dist, w[0] ); /*Q22 */ - L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ - L_dist = L_shr( L_dist, 10 ); /*Q5 */ + max = gen_spec[n_coeff];move16(); + }*/ + max = s_max( max, org_spec[n_coeff] ); + } + l_shift = norm_s( max ); + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { +#ifdef BASOP_NOGLOB + gen_spec[n_coeff] = shl_sat( gen_spec[n_coeff], l_shift ); +#else + gen_spec[n_coeff] = shl( gen_spec[n_coeff], l_shift ); +#endif + move16(); + IF( gen_spec[n_coeff] == 0 ) + { + gen_spec[n_coeff] = shl( 1, l_shift ); + move16(); + } + } - FOR( j = 1; j < dim; j++ ) - { - /*temp = x[j] - *cbP++; */ - /*dist += temp * temp * w[j]; */ - temp = sub( x[j], *cbP++ ); - L_tmp = L_mult( temp, w[j] ); /*Q22 */ - L_tmp = Mult_32_16( L_tmp, temp ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ - } - IF( LT_32( L_dist, L_dist_min ) ) - { - L_dist_min = L_add( L_dist, 0 ); /*Q5 */ - index = i; - move16(); - } + exp = norm_s( length ); + inv_len = div_s( shl( 1, exp ), shl( length, exp ) ); /*Q15 */ + + L_am_org = L_deposit_l( 0 ); + L_am_gen = L_deposit_l( 0 ); + L_log_gm_org = 0; + move32(); + L_log_gm_gen = 0; + move32(); + + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + L_am_org = L_add( L_am_org, L_deposit_l( org_spec[n_coeff] ) ); /*Q10 */ + L_am_gen = L_add( L_am_gen, L_deposit_l( gen_spec[n_coeff] ) ); /*Q10 */ + + IF( org_spec[n_coeff] != 0 ) + { + L_tmp = L_deposit_h( org_spec[n_coeff] ); /*Q26 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 26 ); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + L_log_gm_org = L_add( L_log_gm_org, L_tmp ); /*Q14 */ } + + IF( gen_spec[n_coeff] != 0 ) + { + L_tmp = L_deposit_h( gen_spec[n_coeff] ); /*Q26 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 26 ); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + L_log_gm_gen = L_add( L_log_gm_gen, L_tmp ); /*Q14 */ + } + } + + IF( L_am_org != 0 ) + { + L_tmp = Mpy_32_16_1( L_am_org, inv_len ); /*Q10 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 10 ); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ } ELSE { - FOR( i = 0; i < l; i++ ) - { - /*dist = x[0] - *cbP++; */ - dist = sub( x[0], *cbP++ ); - /*dist *= dist; */ - L_dist = L_mult( dist, dist ); /*Q17 */ - L_dist = L_shr( L_dist, 12 ); + L_tmp1 = L_deposit_l( 0 ); + } - FOR( j = 1; j < dim; j++ ) - { - /*temp = x[j] - *cbP++; */ - temp = sub( x[j], *cbP++ ); - /*dist += temp * temp; */ - L_tmp = L_mult( temp, temp ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ - } - IF( LT_32( L_dist, L_dist_min ) ) - { - L_dist_min = L_add( L_dist, 0 ); - index = i; - move16(); - } - } + L_tmp2 = Mpy_32_16_1( L_log_gm_org, inv_len ); /* Q14 */ + + L_tmp = L_sub( L_tmp1, L_tmp2 ); +#ifdef BASOP_NOGLOB + *SFM_org = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ +#else + *SFM_org = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ +#endif + move16(); + *SFM_org = s_max( 0, s_min( *SFM_org, 24547 ) ); + move16(); /*0.0001 and 5.993 in Q12 */ + + IF( L_am_gen != 0 ) + { + L_tmp = Mpy_32_16_1( L_am_gen, inv_len ); /*Q10 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 10 ); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + } + ELSE + { + L_tmp1 = L_deposit_l( 0 ); } + L_tmp2 = Mpy_32_16_1( L_log_gm_gen, inv_len ); /* Q14 */ - /* Reading the selected vector */ - Copy( &cb[i_mult( index, dim )], y, dim ); + L_tmp = L_sub( L_tmp1, L_tmp2 ); +#ifdef BASOP_NOGLOB + *SFM_gen = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ +#else + *SFM_gen = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ +#endif + move16(); + *SFM_gen = s_max( 0, s_min( *SFM_gen, 24547 ) ); + move16(); /*0.0001 and 5.993 in Q12 */ - return ( index ); + return; } - /*-------------------------------------------------------------------* - * MSVQ_Interpol_Tran_fx() + * energy_control_fx() * *-------------------------------------------------------------------*/ -static void MSVQ_Interpol_Tran_fx( - Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ - Word16 *indice /* o : quantized index */ -) +static void energy_control_fx( + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 core, /* i : core */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 coder_type, /* i : coder type */ + const Word16 *org_fx, /* i : input spectrum */ + const Word16 offset, /* i : frequency offset */ + Word16 *energy_factor_fx, /* o : energy factor */ + Word16 Q_new_lf ) { - Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2], tmp; - Word16 env_temp11[SWB_FENV_TRANS / 2], env_temp12[SWB_FENV_TRANS / 2]; - Word16 tmp_q; - Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; - Word16 quant_select[SWB_FENV_TRANS]; - Word32 L_tmp, L_dist, L_minDist, distCand[N_CAND_TR]; - - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) - { - env_temp11[n_band] = SWB_env_energy[2 * n_band]; - move16(); /*Q8 */ - env_temp12[n_band] = SWB_env_energy[2 * n_band + 1]; - move16(); /*Q8 */ - } - - vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); - - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + Word16 n_band, max_band, band_step; + Word16 gamma_fx, core_type; + Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( k = 0; k < N_CAND_TR; k++ ) + IF( EQ_16( core, ACELP_CORE ) ) { - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + gamma_fx = 11469; + move16(); /*.35 in Q15 */ + test(); + IF( NE_16( coder_type, AUDIO ) && LT_32( st_fx->total_brate, ACELP_8k85 ) ) { - quant_tmp[n_band] = Env_TR_Cdbk1_fx[add( shl( candInd[k], 1 ), n_band )]; - move16(); /*DIM_TR1 == 2*/ + core_type = 0; + move16(); } - - FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) + ELSE { - /*quant_tmp2[n_band] = env_temp12[n_band] - ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f); */ - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ - tmp = shr( tmp, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); - move16(); /*Q8 */ + core_type = 1; + move16(); } - /*quant_tmp2[n_band] = env_temp12[n_band] - quant_tmp[n_band]; */ - quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); - move16(); /*Q8 */ - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, Env_TR_Cdbk2_fx, NULL, DIM_TR2, N_CB_TR2, 0 ); - move16(); + get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + IF( EQ_16( st_fx->extl, WB_BWE ) ) { - quant_select[n_band * 2] = quant_tmp[n_band]; + max_band = 4; + move16(); + band_step = 2; move16(); } - - FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) + ELSE { - /*quant_select[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f) + quant_tmp2[n_band]; */ - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ - tmp = shr( tmp, 1 ); - quant_select[n_band * 2 + 1] = add( tmp, quant_tmp2[n_band] ); + max_band = SWB_FENV; + move16(); + band_step = 1; move16(); } - /*quant_select[n_band*2+1] = quant_tmp[n_band]+quant_tmp2[n_band]; */ - quant_select[n_band * 2 + 1] = add( quant_tmp[n_band], quant_tmp2[n_band] ); - move16(); + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16(); /*.55 in Q15 */ + get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + band_step = 1; + move16(); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) { - /*tmp_q = SWB_env_energy[n_band] - quant_select[n_band]; */ - tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); - /*dist += tmp_q*tmp_q; */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ + max_band = 12; + move16(); } - - /* Check optimal candidate */ - IF( LT_32( L_dist, L_minDist ) ) + ELSE { - L_minDist = L_add( L_dist, 0 ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; + max_band = SWB_FENV; move16(); } } + + FOR( n_band = 0; n_band < max_band; ) + { + calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, + &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); + + IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + { + energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ + IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + { + energy_factor_fx[n_band] = gamma_fx; + move16(); + } + } + ELSE + { + energy_factor_fx[n_band] = 32767; + move16(); /* Q15 */ + } + n_band = add( n_band, band_step ); + } return; } /*-------------------------------------------------------------------* - * MSVQ_Interpol_fx() + * energy_control_ivas_fx() * *-------------------------------------------------------------------*/ -static void msvq_interpol_fx( - Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8*/ - Word16 *w_env, /* i/o : weighting coffecients Q13*/ - Word16 *indice /* o : quantized index */ -) +static void energy_control_ivas_fx( + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 core, /* i : core */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 coder_type, /* i : coder type */ + const Word16 *org_fx, /* i : input spectrum */ + const Word16 offset, /* i : frequency offset */ + Word16 *energy_factor_fx, /* o : energy factor */ + Word16 Q_new_lf ) { - Word16 k, n_band, n_band2, n_band2p1, candInd[N_CAND], ind_tmp[4]; - Word16 tmp_q; - Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; - Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; - Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2], tmp; - Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; - Word16 synth_energy[SWB_FENV]; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) - { - n_band2 = shl( n_band, 1 ); - n_band2p1 = add( n_band2, 1 ); - env_temp11[n_band] = SWB_env_energy[n_band2]; - move16(); /*Q8 */ - env_temp12[n_band] = SWB_env_energy[n_band2p1]; - move16(); /*Q8 */ - - w_env11[n_band] = w_env[n_band2]; - move16(); /*Q13 */ - w_env12[n_band] = w_env[n_band2p1]; - move16(); /*Q13 */ - } - - vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); - - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + Word16 n_band, max_band, band_step; + Word16 gamma_fx, core_type; + Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( k = 0; k < N_CAND; k++ ) + IF( EQ_16( core, ACELP_CORE ) ) { - FOR( n_band = 0; n_band < DIM11; n_band++ ) + gamma_fx = 11469; + move16(); /*.35 in Q15 */ + test(); + IF( NE_16( coder_type, AUDIO ) && LE_32( st_fx->total_brate, ACELP_8k00 ) ) { - quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; - move16(); /*Q8 */ - quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); - move16(); /*Q8 */ + core_type = 0; + move16(); } - - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); - ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); - - /* Extract vector for odd position */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) + ELSE { -#ifdef BASOP_NOGLOB - quant_tmp[n_band] = add_o( quant_tmp1[n_band], quant_tmp2[n_band], &Overflow ); -#else - quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); -#endif + core_type = 1; move16(); } + get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + IF( EQ_16( st_fx->extl, WB_BWE ) ) { -#ifdef BASOP_NOGLOB - tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); /*Q8 */ -#else - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ -#endif - tmp = shr( tmp, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); - move16(); /*Q8 */ + max_band = 4; + move16(); + band_step = 2; + move16(); } - - /*quant_tmp2[n_band] = env_temp12[n_band]-quant_tmp[n_band]; */ - quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); - move16(); /*Q8 */ - - ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); - move16(); - ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk4th_fx, w_env12 + DIM3RD, DIM4TH, N_CB4TH, 1 ); - move16(); - - FOR( n_band = 0; n_band < DIM11; n_band++ ) + ELSE { - quant_select[n_band * 2] = quant_tmp[n_band]; - move16(); /*Q8 */ + max_band = SWB_FENV; + move16(); + band_step = 1; + move16(); } + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16(); /*.55 in Q15 */ + get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + band_step = 1; + move16(); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) { -#ifdef BASOP_NOGLOB - tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); -#else - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); -#endif - tmp = shr( tmp, 1 ); - quant_select[add( shl( n_band, 1 ), 1 )] = add( tmp, quant_tmp2[n_band] ); - move16(); /*Q8 */ + max_band = 12; + move16(); } - quant_select[add( shl( n_band, 1 ), 1 )] = add( quant_tmp[n_band], quant_tmp2[n_band] ); - move16(); /*Q8 */ - - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) + ELSE { - tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); /*Q8 */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + max_band = SWB_FENV; + move16(); } + } - /* Check optimal candidate */ - IF( LT_32( L_dist, L_minDist ) ) - { - L_minDist = L_add( L_dist, 0 ); - - Copy( quant_select, synth_energy, SWB_FENV ); + FOR( n_band = 0; n_band < max_band; ) + { + calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, + &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; - move16(); - indice[2] = ind_tmp[1]; - move16(); - indice[3] = ind_tmp[2]; - move16(); - indice[4] = ind_tmp[3]; + IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + { + energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ move16(); + IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + { + energy_factor_fx[n_band] = gamma_fx; + move16(); + } + } + ELSE + { + energy_factor_fx[n_band] = 32767; + move16(); /* Q15 */ } + n_band = add( n_band, band_step ); } - - Copy( synth_energy, SWB_env_energy, SWB_FENV ); - return; } /*-------------------------------------------------------------------* - * msvq_interpol_2_fx() + * WB_BWE_encoding() * + * WB BWE main encoder *-------------------------------------------------------------------*/ -static void msvq_interpol_2_fx( - Word16 *hq_generic_fenv, /* i/o: (original/quantized) energy */ - const Word16 *w_env, /* i : weighting coffecients */ - Word16 *indice, /* o : quantized index */ - const Word16 nenv /* i : the number of envelopes */ -) -{ - Word16 k, n_band, n_band2, candInd[N_CAND], ind_tmp[4]; - Word16 tmp_q; - Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; - Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; - Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2]; - Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; - Word16 synth_energy[SWB_FENV]; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM11 - 1; n_band++ ) - { - n_band2 = shl( n_band, 1 ); - env_temp11[n_band] = hq_generic_fenv[n_band2]; - move16(); /*Q8 */ - w_env11[n_band] = w_env[n_band2]; - move16(); /*Q13 */ - } - env_temp11[DIM11 - 1] = hq_generic_fenv[2 * ( DIM11 - 2 ) + 1]; - move16(); /*Q8 */ - w_env11[DIM11 - 1] = w_env[2 * ( DIM11 - 2 ) + 1]; - move16(); /*Q13 */ - - env_temp12[0] = hq_generic_fenv[0]; - move16(); /*Q8 */ - w_env12[0] = w_env[0]; - move16(); /*Q13 */ - FOR( n_band = 1; n_band < DIM11 - 1; n_band++ ) - { - n_band2 = sub( shl( n_band, 1 ), 1 ); - env_temp12[n_band] = hq_generic_fenv[n_band2 /*2*n_band-1*/]; - move16(); /*Q8 */ - w_env12[n_band] = w_env[n_band2 /*2*n_band-1*/]; - move16(); /*Q13 */ - } - vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); +Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ + const Word16 coder_type, /* i : coder type */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Encoder_State *st_fx, /* i/o: Encoder structure */ + Word16 Q_synth, + Word16 Q_synth_lf ) +{ + Word16 mode; + Word16 i, n_coeff, n_band; + Word16 index; + Word32 energy_fx; + Word32 L_WB_fenv_fx[2]; + Word16 energy_factor_fx[4]; + Word16 ener_40, exp; + Word32 L_tmp; + Word16 tmp; - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - FOR( k = 0; k < N_CAND; k++ ) + n_band = 0; + move16(); + FOR( i = 0; i < 2; i++ ) { - FOR( n_band = 0; n_band < DIM11; n_band++ ) + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) { - quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; - move16(); /*Q8 */ - quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); - move16(); /*Q8 */ + energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ } - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); - move16(); - ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); - move16(); - - /* Extract vector for odd position */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) - { - quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); - move16(); - } + L_WB_fenv_fx[i] = energy_fx; + move32(); /*2*Q_synth-6 */ + n_band = add( n_band, 2 ); + } + mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); - quant_tmp2[0] = sub( env_temp12[0], quant_tmp[0] ); - move16(); - FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) - { -#ifdef BASOP_NOGLOB - tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); - tmp_q = shr( tmp_q, 1 ); - quant_tmp2[n_band] = sub_o( env_temp12[n_band], tmp_q, &Overflow ); -#else - tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); - tmp_q = shr( tmp_q, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp_q ); -#endif - move16(); - } - ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); - move16(); - ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk3rd_fx, w_env12 + DIM3RD, DIM3RD, N_CB3RD, 1 ); - move16(); + energy_control_fx( st_fx, ACELP_CORE, mode, coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + FOR( i = 0; i < 2; i++ ) + { + ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ + L_tmp = Mult_32_16( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ + IF( L_tmp ) { - quant_select[n_band * 2] = quant_tmp[n_band]; - move16(); /*Q8 */ + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = 30-exp-(2*Q_synth-2); */ + exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); + L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ + WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ } - quant_select[11] = quant_tmp[DIM12 - 1]; - move16(); /*Q8 */ - - quant_select[0] = add( quant_select[0], quant_tmp2[0] ); - move16(); /*Q8 */ - FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + ELSE { -#ifdef BASOP_NOGLOB - tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); - tmp_q = shr( tmp_q, 1 ); - quant_select[sub( shl( n_band, 1 ), 1 )] = add_o( quant_tmp2[n_band], tmp_q, &Overflow ); -#else - tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); - tmp_q = shr( tmp_q, 1 ); - quant_select[sub( shl( n_band, 1 ), 1 )] = add( quant_tmp2[n_band], tmp_q ); -#endif + WB_fenv_fx[i] = 0; + move16(); } + } - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV - 2; n_band++ ) + index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); + + push_indice_fx( st_fx->hBstr, IND_WB_FENV, index, 5 ); + + return ( mode ); +} + +/*-------------------------------------------------------------------* + * WB_BWE_encoding_ivas() + * + * WB BWE main encoder + *-------------------------------------------------------------------*/ + +Word16 WB_BWE_encoding_ivas_fx( /* o : classification of wb signal */ + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Word16 Q_synth, + Word16 Q_synth_lf ) +{ + Word16 mode; + Word16 i, n_coeff, n_band; + Word16 index; + Word32 energy_fx; + Word32 L_WB_fenv_fx[2]; + Word16 energy_factor_fx[4]; + Word16 ener_40, exp; + Word32 L_tmp; + Word16 tmp; + + n_band = 0; + move16(); + FOR( i = 0; i < 2; i++ ) + { + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) { - tmp_q = sub( hq_generic_fenv[n_band], quant_select[n_band] ); /*Q8 */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ } - /* Check optimal candidate */ - IF( L_dist < L_minDist ) - { - L_minDist = L_add( L_dist, 0 ); - Copy( quant_select, synth_energy, SWB_FENV - 2 ); - synth_energy[SWB_FENV - 2] = 0; - move16(); - synth_energy[SWB_FENV - 1] = 0; - move16(); + L_WB_fenv_fx[i] = energy_fx; + move32(); /*2*Q_synth-6 */ + n_band = add( n_band, 2 ); + } + mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; - move16(); - indice[2] = ind_tmp[1]; - move16(); - indice[3] = ind_tmp[2]; + energy_control_ivas_fx( st_fx, ACELP_CORE, mode, st_fx->coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); + + FOR( i = 0; i < 2; i++ ) + { + ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ + L_tmp = Mpy_32_16_1( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ + IF( L_tmp ) + { + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = 30-exp-(2*Q_synth-2); */ + exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); + L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ + WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ move16(); - indice[4] = ind_tmp[3]; + } + ELSE + { + WB_fenv_fx[i] = 0; move16(); } } - Copy( synth_energy, hq_generic_fenv, nenv ); + index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); - return; -} + push_indice( st_fx->hBstr, IND_WB_FENV, index, 5 ); + return ( mode ); +} /*-------------------------------------------------------------------* - * calculate_Tonality_fx() + * SWB_BWE_encoding() * - * Calculate tonality + * SWB BWE encoder *-------------------------------------------------------------------*/ - -static void calculate_Tonality_fx( - const Word16 *org, /* i : MDCT coefficients of original Q_new*/ - const Word16 *gen, /* i : MDCT coefficients of generated signal Q15*/ - Word16 *SFM_org, /* o : Spectral Flatness results Q12*/ - Word16 *SFM_gen, /* o : Spectral Flatness results Q12*/ - const Word16 length /* i : length for calculating tonality */ -) +static Word16 SWB_BWE_encoding_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i : delayed original input signal at 32kHz */ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf ) { - Word16 n_coeff; - Word16 inv_len, max; - Word16 exp, e_tmp, f_tmp; - Word32 L_tmp, L_tmp2, L_am_org, L_am_gen, L_tmp1; - Word16 org_spec[80], gen_spec[80]; - Word32 L_log_gm_org, L_log_gm_gen; - Word16 l_shift; + Word16 IsTransient, mode; + Word16 index; + Word16 i, n_coeff, n_band, pos, indice[6]; + Word16 L; + Word16 IsTransient_LF; + + Word16 tmp; + Word32 energy_fx; + Word16 tilt_fx; + Word32 global_gain_fx; + Word32 L_tmp; + Word32 L_SWB_fenv_fx[SWB_FENV]; + Word16 SWB_tenv_fx[SWB_TENV]; + Word32 L_SWB_tenv, WB_tenv_syn_fx, WB_tenv_orig_fx; + Word16 exp, expn, expd; + Word16 num, den; + Word16 scale; + Word16 Rat_tenv_fx; + Word16 SWB_tenv_tmp_fx[SWB_TENV]; + Word16 max_fx; + Word16 energy_factor_fx[SWB_FENV], w_env_fx[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif - /* to reduce dynamic range of original spectrum */ - max = 0; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + L = L_SUBFR; + move16(); + } + ELSE + { + L = L_SUBFR16k; + move16(); + } + + /* HF transient detect */ + IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, Q_shb, st_fx ); + st_fx->EnergyLT_fx_exp = shl( Q_shb, 1 ); + + /* LF transient detect */ + IsTransient_LF = 0; move16(); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + FOR( n_band = 0; n_band < 4; n_band++ ) { - org_spec[n_coeff] = abs_s( org[n_coeff] ); - move16(); /*Q_new */ - /*test(); */ - /*if( sub(max, org_spec[n_coeff]) < 0) */ - /*{ */ - /* max = org_spec[n_coeff];move16();//Q_new */ - /*} */ - max = s_max( max, org_spec[n_coeff] ); + tmp = i_mult2( n_band, L ); + energy_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L; i++ ) + { + energy_fx = L_add( energy_fx, L_shr( L_mult0( insig_lp_fx[i + tmp], insig_lp_fx[i + tmp] ), 7 ) ); /*2*Q_slb_speech - 7 */ + } + + IF( GT_32( Mult_32_16( energy_fx, 5958 ), hBWE_FD->EnergyLF_fx ) ) + { + IsTransient_LF = 1; + move16(); + } + + hBWE_FD->EnergyLF_fx = energy_fx; + move32(); } - l_shift = norm_s( max ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + + /* tilt returned in Q24 go to Q11 */ +#ifdef BASOP_NOGLOB + tilt_fx = round_fx_o( L_shl_o( calc_tilt_bwe_fx( insig_fx, 0, L_FRAME32k ), 3, &Overflow ), &Overflow ); +#else + tilt_fx = round_fx( L_shl( calc_tilt_bwe_fx( insig_fx, 0, L_FRAME32k ), 3 ) ); +#endif + test(); + test(); + IF( EQ_16( IsTransient, 1 ) && ( GT_16( tilt_fx, 16384 ) || GT_16( st_fx->clas, 1 ) ) ) { - org_spec[n_coeff] = shl( org_spec[n_coeff], l_shift ); + IsTransient = 0; move16(); - test(); - if ( org_spec[n_coeff] == 0 ) + st_fx->TransientHangOver = 0; + move16(); + } + + IF( EQ_16( IsTransient, 1 ) ) + { + mode = IsTransient; + move16(); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) { - org_spec[n_coeff] = shl( 1, l_shift ); + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_trans_subband[n_band] + st_offset; n_coeff < swb_bwe_trans_subband[n_band + 1] + st_offset; n_coeff++ ) + { + L_tmp = L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 7 ); /*2*Q_synth-7 */ + energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-7 */ + } + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( sub( shl( Q_synth, 1 ), 7 ), shl( Q_shb, 1 ) ) ) ); /*2*Q_shb */ + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ + + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + { + expd = norm_s( swb_bwe_trans_subband_width[n_band] ); + tmp = div_s( shl( 1, sub( 14, expd ) ), swb_bwe_trans_subband_width[n_band] ); /*Q(29-expd) */ + L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], tmp ); /*2*Q_synth-7+29-expd - 15 */ + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); move16(); + exp = sub( sub( 30, exp ), sub( add( shl( Q_synth, 1 ), 7 ), expd ) ); + L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + tmp = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + + SWB_fenv_fx[n_band] = sub( tmp, Mean_env_tr_fx[n_band] ); + move16(); /*Q8 */ } - } - max = 0; - move16(); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { - gen_spec[n_coeff] = abs_s( gen[n_coeff] ); - move16(); /*Q15 */ - /*test(); - if( sub(max,gen_spec[n_coeff]) < 0) + WB_tenv_orig_fx = L_deposit_l( 0 ); + WB_tenv_syn_fx = L_deposit_l( 1 ); + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { - max = gen_spec[n_coeff];move16(); - }*/ - max = s_max( max, org_spec[n_coeff] ); - } - l_shift = norm_s( max ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { + tmp = i_mult2( n_band, L_SUBFR16k ); + L_SWB_tenv = L_deposit_l( 0 ); + FOR( i = 0; i < L_SUBFR16k; i++ ) + { #ifdef BASOP_NOGLOB - gen_spec[n_coeff] = shl_sat( gen_spec[n_coeff], l_shift ); + L_SWB_tenv = L_add_sat( L_SWB_tenv, L_mult0( insig_hp_fx[i + tmp], insig_hp_fx[i + tmp] ) ); /*2*Q_shb */ #else - gen_spec[n_coeff] = shl( gen_spec[n_coeff], l_shift ); + L_SWB_tenv = L_add( L_SWB_tenv, L_mult0( insig_hp_fx[i + tmp], insig_hp_fx[i + tmp] ) ); /*2*Q_shb */ #endif - move16(); - test(); - if ( gen_spec[n_coeff] == 0 ) - { - gen_spec[n_coeff] = shl( 1, l_shift ); - move16(); - } - } + } - exp = norm_s( length ); - inv_len = div_s( shl( 1, exp ), shl( length, exp ) ); /*Q15 */ + tmp = i_mult2( n_band, L ); + FOR( i = 0; i < L; i++ ) + { + WB_tenv_syn_fx = L_add( WB_tenv_syn_fx, L_shr( L_mult0( synth_fx[i + tmp], synth_fx[i + tmp] ), 7 ) ); /*2*st_fx->Q_syn2 - 7 */ + WB_tenv_orig_fx = L_add( WB_tenv_orig_fx, L_shr( L_mult0( insig_lp_fx[i + tmp], insig_lp_fx[i + tmp] ), 7 ) ); /*2*Q_insig_lp - 7 */ + } - L_am_org = L_deposit_l( 0 ); - L_am_gen = L_deposit_l( 0 ); - L_log_gm_org = 0; - move16(); - L_log_gm_gen = 0; - move16(); + L_tmp = Mult_32_16( L_SWB_tenv, INV_L_SUBFR16k_FX ); /*2*Q_shb */ + SWB_tenv_fx[n_band] = 0; + move16(); + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( exp, sub( 30, 2 * Q_shb ) ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { - L_am_org = L_add( L_am_org, L_deposit_l( org_spec[n_coeff] ) ); /*Q10 */ - L_am_gen = L_add( L_am_gen, L_deposit_l( gen_spec[n_coeff] ) ); /*Q10 */ + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp) */ - IF( org_spec[n_coeff] != 0 ) - { - L_tmp = L_deposit_h( org_spec[n_coeff] ); /*Q26 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 26 ); - L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - L_log_gm_org = L_add( L_log_gm_org, L_tmp ); /*Q14 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band] = round_fx_sat( L_shl_sat( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band] = round_fx( L_shl( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ +#endif + } } - IF( gen_spec[n_coeff] != 0 ) + IF( WB_tenv_orig_fx != 0 ) { - L_tmp = L_deposit_h( gen_spec[n_coeff] ); /*Q26 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 26 ); - L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - L_log_gm_gen = L_add( L_log_gm_gen, L_tmp ); /*Q14 */ - } - } + expn = norm_l( WB_tenv_orig_fx ); + num = extract_h( L_shl( WB_tenv_orig_fx, expn ) ); + expn = sub( sub( 30, expn ), sub( shl( Q_insig_lp, 1 ), 7 ) ); - IF( L_am_org != 0 ) - { - L_tmp = Mult_32_16( L_am_org, inv_len ); /*Q10 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 10 ); - L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - } - ELSE - { - L_tmp1 = L_deposit_l( 0 ); - } + expd = norm_l( WB_tenv_syn_fx ); + den = round_fx( L_shl( WB_tenv_syn_fx, expd ) ); + expd = sub( sub( 30, expd ), sub( shl( st_fx->Q_syn2, 1 ), 7 ) ); - L_tmp2 = Mult_32_16( L_log_gm_org, inv_len ); /* Q14 */ + scale = shr( sub( den, num ), 15 ); + num = shl( num, scale ); + expn = sub( expn, scale ); + + tmp = div_s( num, den ); + expn = sub( expn, expd ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &expn ); /*31-expn */ - L_tmp = L_sub( L_tmp1, L_tmp2 ); - move16(); /*Q14 */ #ifdef BASOP_NOGLOB - *SFM_org = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ + Rat_tenv_fx = round_fx_o( L_shl_o( L_tmp, sub( expn, 1 ), &Overflow ), &Overflow ); /*Q14 */ #else - *SFM_org = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ + Rat_tenv_fx = round_fx( L_shl( L_tmp, sub( expn, 1 ) ) ); /*Q14 */ #endif - *SFM_org = s_max( 0, s_min( *SFM_org, 24547 ) ); - move16(); /*0.0001 and 5.993 in Q12 */ - - IF( L_am_gen != 0 ) - { - L_tmp = Mult_32_16( L_am_gen, inv_len ); /*Q10 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 10 ); - L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - } - ELSE - { - L_tmp1 = L_deposit_l( 0 ); - } - - L_tmp2 = Mult_32_16( L_log_gm_gen, inv_len ); /* Q14 */ + } + ELSE + { + Rat_tenv_fx = 16384; + move16(); + } - L_tmp = L_sub( L_tmp1, L_tmp2 ); - move16(); /*Q14 */ + IF( LT_16( Rat_tenv_fx, 8192 ) ) + { + L_tmp = L_mult( Rat_tenv_fx, 19661 ); /*Q29 */ #ifdef BASOP_NOGLOB - *SFM_gen = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ + Rat_tenv_fx = round_fx_o( L_shl_o( L_tmp, 2, &Overflow ), &Overflow ); /*Q15 */ #else - *SFM_gen = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ + Rat_tenv_fx = round_fx( L_shl( L_tmp, 2 ) ); /*Q15 */ #endif - *SFM_gen = s_max( 0, s_min( *SFM_gen, 24547 ) ); - move16(); /*0.0001 and 5.993 in Q12 */ - - return; -} - -/*-------------------------------------------------------------------* - * energy_control_fx() - * - *-------------------------------------------------------------------*/ + } + ELSE IF( GT_16( Rat_tenv_fx, 16384 ) ) + { + Rat_tenv_fx = 32767; + move16(); + } -static void energy_control_fx( - Encoder_State *st_fx, /* i/o: Encoder structure */ - const Word16 core, /* i : core */ - const Word16 mode, /* i : SHB BWE class */ - const Word16 coder_type, /* i : coder type */ - const Word16 *org_fx, /* i : input spectrum */ - const Word16 offset, /* i : frequency offset */ - Word16 *energy_factor_fx, /* o : energy factor */ - Word16 Q_new_lf ) -{ - Word16 n_band, max_band, band_step; - Word16 gamma_fx, core_type; - Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; - FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], Rat_tenv_fx ); + move16(); /*Q3 */ + } - IF( EQ_16( core, ACELP_CORE ) ) - { - gamma_fx = 11469; - move16(); /*.35 in Q15 */ - test(); - IF( NE_16( coder_type, AUDIO ) && LT_32( st_fx->total_brate, ACELP_8k85 ) ) + max_fx = SWB_tenv_fx[0]; + move16(); + pos = 0; + move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) { - core_type = 0; - move16(); + IF( GT_16( SWB_tenv_fx[n_band], max_fx ) ) + { + max_fx = SWB_tenv_fx[n_band]; + move16(); + pos = n_band; + move16(); + } } - ELSE + + max_fx = SWB_tenv_fx[0]; + move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) { - core_type = 1; - move16(); + tmp = sub( mult_r( SWB_tenv_fx[n_band], 6554 ), SWB_tenv_fx[n_band - 1] ); + IF( tmp > 0 ) + { + BREAK; + } } - get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - IF( EQ_16( st_fx->extl, WB_BWE ) ) + IF( n_band < SWB_TENV ) { - max_band = 4; - move16(); - band_step = 2; - move16(); + energy_fx = L_deposit_l( 0 ); + FOR( n_band = ( pos + 1 ); n_band < SWB_TENV; n_band++ ) + { + energy_fx = L_add( energy_fx, SWB_tenv_fx[n_band] ); /*Q3 */ + } + + IF( pos == sub( SWB_TENV, 1 ) ) + { + energy_fx = L_deposit_l( 0 ); + } + ELSE + { + tmp = sub( SWB_TENV, pos + 1 ); + tmp = div_s( 1, tmp ); /*Q15 */ + energy_fx = Mult_32_16( energy_fx, tmp ); /*Q3 */ + } + + FOR( n_band = 0; n_band < pos; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 16384 ); + move16(); + } + + /*SWB_tenv_fx[pos] = add(SWB_tenv_fx[pos], mult_r(SWB_tenv_fx[pos], 164)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[pos] = round_fx_sat( L_mac_sat( L_mult_sat( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ +#else + SWB_tenv_fx[pos] = round_fx( L_mac( L_mult( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ +#endif + + IF( LT_32( energy_fx, SWB_tenv_fx[pos] ) ) + { + FOR( n_band = pos + 1; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 29491 ); + move16(); /*Q3 */ + } + } } ELSE { - max_band = SWB_FENV; - move16(); - band_step = 1; - move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) + { + IF( GT_16( SWB_tenv_fx[n_band - 1], SWB_tenv_fx[n_band] ) ) + { + /*SWB_tenv_fx[n_band-1] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band - 1] = round_fx_sat( L_mac_sat( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band - 1] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#endif + } + ELSE + { + /*SWB_tenv_fx[n_band] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band] = round_fx_sat( L_mac_sat( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#endif + } + } + + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 29491 ); + move16(); /*Q3 */ + } } - } - ELSE /* HQ core */ - { - gamma_fx = 18022; - move16(); /*.55 in Q15 */ - get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - band_step = 1; - move16(); - IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) + test(); + test(); + IF( IsTransient_LF == 0 && EQ_16( coder_type, INACTIVE ) && EQ_16( st_fx->TransientHangOver, 1 ) ) { - max_band = 12; - move16(); + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 16384 ); + move16(); + } + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + { + SWB_fenv_fx[n_band] = mult_r( SWB_fenv_fx[n_band], 1638 ); + move16(); + } } ELSE { - max_band = SWB_FENV; + SWB_fenv_fx[2] = mult_r( SWB_fenv_fx[2], 3277 ); + move16(); + SWB_fenv_fx[3] = mult_r( SWB_fenv_fx[3], 1638 ); move16(); } - } - - FOR( n_band = 0; n_band < max_band; ) - { - calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, - &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); - IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { - energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ - IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + IF( SWB_tenv_fx[n_band] == 0 ) { - energy_factor_fx[n_band] = gamma_fx; + SWB_tenv_tmp_fx[n_band] = -32768; + move16(); /*-16 in Q11 */ + } + ELSE + { + L_tmp = L_deposit_h( SWB_tenv_fx[n_band] ); /*Q19 */ + expn = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, expn ) ); + expn = sub( sub( 30, expn ), 19 ); + L_tmp = Mpy_32_16( expn, tmp, 32767 ); /* Q16 */ /*1 in Q15 */ + SWB_tenv_tmp_fx[n_band] = round_fx( L_shl( L_tmp, 11 ) ); /* Q11 */ + } + + IF( GT_16( SWB_tenv_tmp_fx[n_band], 30720 ) ) + { + index = 15; move16(); } + ELSE IF( SWB_tenv_tmp_fx[n_band] < 0 ) + { + index = 0; + move16(); + } + ELSE + { + index = shr( add( SWB_tenv_tmp_fx[n_band], 1024 ), 11 ); + } + + push_indice_fx( hBstr, IND_SWB_TENV, index, 4 ); } - ELSE - { - energy_factor_fx[n_band] = 32767; - move16(); /* Q15 */ - } - n_band = add( n_band, band_step ); - } - return; -} -/*-------------------------------------------------------------------* - * WB_BWE_encoding() - * - * WB BWE main encoder - *-------------------------------------------------------------------*/ -Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ - const Word16 coder_type, /* i : coder type */ - const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ - Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ - Encoder_State *st_fx, /* i/o: Encoder structure */ - Word16 Q_synth, - Word16 Q_synth_lf ) -{ - Word16 mode; - Word16 i, n_coeff, n_band; - Word16 index; - Word32 energy_fx; - Word32 L_WB_fenv_fx[2]; - Word16 energy_factor_fx[4]; - Word16 ener_40, exp; - Word32 L_tmp; - Word16 tmp; + MSVQ_Interpol_Tran_fx( SWB_fenv_fx, indice ); - n_band = 0; - move16(); - FOR( i = 0; i < 2; i++ ) + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 6 ); + } + ELSE { - energy_fx = L_deposit_l( 0 ); - FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ - } + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band] + st_offset; n_coeff < swb_bwe_subband[n_band + 1] + st_offset; n_coeff++ ) + { + L_tmp = L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 5 ); /*2*Q_synth-5 */ + energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-5 */ + } - L_WB_fenv_fx[i] = energy_fx; - move32(); /*2*Q_synth-6 */ - n_band = add( n_band, 2 ); - } - mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); + IF( LT_16( n_band, sub( SWB_FENV, 2 ) ) ) + { + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( 2 * Q_synth - 5, 2 * Q_shb ) ) ); /*2*Q_shb */ + } + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ + mode = FD_BWE_class_fx( yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx ); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); - energy_control_fx( st_fx, ACELP_CORE, mode, coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); + energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); - FOR( i = 0; i < 2; i++ ) - { - ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ - L_tmp = Mult_32_16( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ - IF( L_tmp ) + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - exp = norm_l( L_tmp ); - tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); - /*exp = 30-exp-(2*Q_synth-2); */ - exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); - L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ - WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ + L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], energy_factor_fx[n_band] ); /*2*Q_synth-5 */ + L_tmp = Mult_32_16( L_tmp, swb_inv_bwe_subband_width_fx[n_band] ); /*2*Q_synth-5 */ + + IF( L_tmp != 0 ) + { + expn = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, expn ) ); + expn = sub( 30, add( expn, sub( shl( Q_synth, 1 ), 5 ) ) ); + L_tmp = Mpy_32_16( expn, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + SWB_fenv_fx[n_band] = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + } + ELSE + { + SWB_fenv_fx[n_band] = -24576; + move16(); + } } - ELSE + freq_weights_fx( SWB_fenv_fx, w_NOR_fx, w_env_fx, SWB_FENV ); + + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - WB_fenv_fx[i] = 0; + SWB_fenv_fx[n_band] = sub( SWB_fenv_fx[n_band], Mean_env_fx[n_band] ); move16(); } - } - index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); + /* Energy VQ */ + msvq_interpol_fx( SWB_fenv_fx, w_env_fx, indice ); - push_indice_fx( st_fx->hBstr, IND_WB_FENV, index, 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[2], 6 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[3], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[4], 6 ); + } + hBWE_FD->prev_mode = mode; + move16(); + hBWE_FD->prev_global_gain_fx = global_gain_fx; + move32(); + st_fx->prev_Q_shb = Q_shb; + move16(); - return ( mode ); + return mode; } /*-------------------------------------------------------------------* @@ -1910,7 +2964,7 @@ Word16 WB_BWE_encoding_fx( /* o : classification of wb * * SWB BWE encoder *-------------------------------------------------------------------*/ -static Word16 SWB_BWE_encoding_fx( +static Word16 SWB_BWE_encoding_ivas_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word16 *insig_fx, /* i : delayed original input signal at 32kHz */ const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ @@ -1920,7 +2974,6 @@ static Word16 SWB_BWE_encoding_fx( Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ const Word16 tilt_nb_fx, /* i : SWB tilt */ const Word16 st_offset, /* i : start frequency offset for BWE envelope */ - const Word16 coder_type, /* i : coding type */ Word16 Q_insig_lp, Word16 Q_shb, Word16 Q_synth, @@ -1949,6 +3002,7 @@ static Word16 SWB_BWE_encoding_fx( Word16 energy_factor_fx[SWB_FENV], w_env_fx[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; @@ -1968,6 +3022,7 @@ static Word16 SWB_BWE_encoding_fx( /* HF transient detect */ IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, Q_shb, st_fx ); st_fx->EnergyLT_fx_exp = shl( Q_shb, 1 ); + move16(); /* LF transient detect */ IsTransient_LF = 0; @@ -2011,7 +3066,7 @@ static Word16 SWB_BWE_encoding_fx( { mode = IsTransient; move16(); - push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + push_indice( hBstr, IND_SWB_CLASS, mode, 2 ); /* Energy for the different bands and global energies */ global_gain_fx = L_deposit_l( 0 ); @@ -2036,7 +3091,6 @@ static Word16 SWB_BWE_encoding_fx( L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], tmp ); /*2*Q_synth-7+29-expd - 15 */ exp = norm_l( L_tmp ); tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); - move16(); exp = sub( sub( 30, exp ), sub( add( shl( Q_synth, 1 ), 7 ), expd ) ); L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ tmp = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ @@ -2074,7 +3128,7 @@ static Word16 SWB_BWE_encoding_fx( { exp = norm_l( L_tmp ); tmp = extract_h( L_shl( L_tmp, exp ) ); - exp = sub( exp, sub( 30, 2 * Q_shb ) ); + exp = sub( exp, sub( 30, shl( Q_shb, 1 ) ) ); tmp = div_s( 16384, tmp ); L_tmp = L_deposit_h( tmp ); @@ -2085,6 +3139,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band] = round_fx( L_shl( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ #endif + move16(); } } @@ -2167,7 +3222,7 @@ static Word16 SWB_BWE_encoding_fx( } } - IF( n_band < SWB_TENV ) + IF( LT_16( n_band, SWB_TENV ) ) { energy_fx = L_deposit_l( 0 ); FOR( n_band = ( pos + 1 ); n_band < SWB_TENV; n_band++ ) @@ -2175,13 +3230,13 @@ static Word16 SWB_BWE_encoding_fx( energy_fx = L_add( energy_fx, SWB_tenv_fx[n_band] ); /*Q3 */ } - IF( pos == sub( SWB_TENV, 1 ) ) + IF( EQ_16( pos, sub( SWB_TENV, 1 ) ) ) { energy_fx = L_deposit_l( 0 ); } ELSE { - tmp = sub( SWB_TENV, pos + 1 ); + tmp = sub( SWB_TENV, add( pos, 1 ) ); tmp = div_s( 1, tmp ); /*Q15 */ energy_fx = Mult_32_16( energy_fx, tmp ); /*Q3 */ } @@ -2198,6 +3253,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[pos] = round_fx( L_mac( L_mult( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ #endif + move16(); IF( LT_32( energy_fx, SWB_tenv_fx[pos] ) ) { @@ -2220,6 +3276,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band - 1] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ #endif + move16(); } ELSE { @@ -2229,6 +3286,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ #endif + move16(); } } @@ -2241,7 +3299,7 @@ static Word16 SWB_BWE_encoding_fx( test(); test(); - IF( IsTransient_LF == 0 && EQ_16( coder_type, INACTIVE ) && EQ_16( st_fx->TransientHangOver, 1 ) ) + IF( IsTransient_LF == 0 && st_fx->coder_type == INACTIVE && EQ_16( st_fx->TransientHangOver, 1 ) ) { FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { @@ -2277,6 +3335,7 @@ static Word16 SWB_BWE_encoding_fx( expn = sub( sub( 30, expn ), 19 ); L_tmp = Mpy_32_16( expn, tmp, 32767 ); /* Q16 */ /*1 in Q15 */ SWB_tenv_tmp_fx[n_band] = round_fx( L_shl( L_tmp, 11 ) ); /* Q11 */ + move16(); } IF( GT_16( SWB_tenv_tmp_fx[n_band], 30720 ) ) @@ -2294,13 +3353,13 @@ static Word16 SWB_BWE_encoding_fx( index = shr( add( SWB_tenv_tmp_fx[n_band], 1024 ), 11 ); } - push_indice_fx( hBstr, IND_SWB_TENV, index, 4 ); + push_indice( hBstr, IND_SWB_TENV, index, 4 ); } MSVQ_Interpol_Tran_fx( SWB_fenv_fx, indice ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 7 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[0], 7 ); + push_indice( hBstr, IND_SWB_FENV, indice[1], 6 ); } ELSE { @@ -2315,9 +3374,9 @@ static Word16 SWB_BWE_encoding_fx( energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-5 */ } - IF( LT_16( n_band, sub( SWB_FENV, 2 ) ) ) + IF( LT_16( n_band, SWB_FENV - 2 ) ) { - global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( 2 * Q_synth - 5, 2 * Q_shb ) ) ); /*2*Q_shb */ + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( sub( shl( Q_synth, 1 ), 5 ), shl( Q_shb, 1 ) ) ) ); /*2*Q_shb */ } L_SWB_fenv_fx[n_band] = energy_fx; move32(); @@ -2325,9 +3384,9 @@ static Word16 SWB_BWE_encoding_fx( global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ mode = FD_BWE_class_fx( yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx ); - push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + push_indice( hBstr, IND_SWB_CLASS, mode, 2 ); - energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); + energy_control_ivas_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { @@ -2341,6 +3400,7 @@ static Word16 SWB_BWE_encoding_fx( expn = sub( 30, add( expn, sub( shl( Q_synth, 1 ), 5 ) ) ); L_tmp = Mpy_32_16( expn, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ SWB_fenv_fx[n_band] = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + move16(); } ELSE { @@ -2359,11 +3419,11 @@ static Word16 SWB_BWE_encoding_fx( /* Energy VQ */ msvq_interpol_fx( SWB_fenv_fx, w_env_fx, indice ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 5 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 7 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[2], 6 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[3], 5 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[4], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[0], 5 ); + push_indice( hBstr, IND_SWB_FENV, indice[1], 7 ); + push_indice( hBstr, IND_SWB_FENV, indice[2], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[3], 5 ); + push_indice( hBstr, IND_SWB_FENV, indice[4], 6 ); } hBWE_FD->prev_mode = mode; move16(); @@ -2374,7 +3434,6 @@ static Word16 SWB_BWE_encoding_fx( return mode; } - /*-------------------------------------------------------------------* * get_normalize_spec_fx_32() * diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c index 3336ee3362dfa27b9e8a1d2e4dbbea7af16ea496..30f627c40229f5abe0f9ea3e5535385ffad48889 100644 --- a/lib_enc/swb_pre_proc.c +++ b/lib_enc/swb_pre_proc.c @@ -47,6 +47,7 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #include "prot_fx.h" +#include "prot_fx_enc.h" #endif /*-------------------------------------------------------------------* @@ -277,547 +278,716 @@ void wb_pre_proc( #ifdef IVAS_FLOAT_FIXED /*full implementation pending*/ void swb_pre_proc_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - float *new_swb_speech, /* o : original input signal at 32kHz */ - Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz */ - float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ - float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ - float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer */ - CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ + Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ + Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 *shb_speech_32, /* o : SHB target signal (6-14kHz) at 16kHz- Q - q_reImBuffer */ + Word16 *use_shb32, /* o : flags valid data in 32-bit shb buffer for better precision. */ + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ + Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ) { - int16_t Sample_Delay_SWB_BWE, inner_frame, delay; + Word16 Sample_Delay_SWB_BWE, inner_frame, delay; TD_BWE_ENC_HANDLE hBWE_TD; FD_BWE_ENC_HANDLE hBWE_FD; - int32_t inner_Fs, input_Fs; - float old_input[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; - Word32 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart - float spchTmp[L_FRAME32k], spchTmp2[L_FRAME32k]; - int16_t i, j, L_resamp; - int16_t startB, endB; - float *realBufferFlipped[CLDFB_NO_COL_MAX]; - float *imagBufferFlipped[CLDFB_NO_COL_MAX]; - float realBufferTmp[CLDFB_NO_COL_MAX][20]; - float imagBufferTmp[CLDFB_NO_COL_MAX][20]; - int16_t ts, nB, uB; - float sign, lbEner, v, t, regression; - const float *thr, *regV; - int16_t Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; - - lMemRecalc32k = NS2SA( 32000, L_MEM_RECALC_NS ); + Word32 inner_Fs, input_Fs; + Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart + Word32 old_input_fx_32[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart + Word16 spchTmp[L_FRAME32k], spchTmp2[L_FRAME32k]; + Word16 i, j, L_resamp; + Word16 startB, endB; + Word32 *realBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 *imagBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 imagBufferTmp[CLDFB_NO_COL_MAX][20]; + Word16 ts, nB, uB; + Word32 v, t, regression; + Word16 t_16; + const Word32 *thr, *regV; + Word32 lbEner; + Word16 exp_lbEner = 0; + Word16 Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; + Word32 one_by_50_Q31 = 42949673; + + *use_shb32 = 0; + move16(); + + lMemRecalc32k = NS2SA_FX2( 32000, L_MEM_RECALC_NS ); + move16(); // exp_lbEner + move16(); // lMemRecalc32k + move32(); // one_by_50_Q31 /* initialization */ hBWE_TD = st->hBWE_TD; hBWE_FD = st->hBWE_FD; input_Fs = st->input_Fs; - for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - set_f( realBufferTmp[j], 0, 20 ); - set_f( imagBufferTmp[j], 0, 20 ); + set32_fx( realBufferTmp[j], 0, 20 ); + set32_fx( imagBufferTmp[j], 0, 20 ); realBufferFlipped[j] = realBufferTmp[j]; imagBufferFlipped[j] = imagBufferTmp[j]; } - set_f( old_input, 0.0f, NS2SA( 48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k ); + set16_fx( old_input_fx, 0, NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k ); - if ( input_Fs == 32000 ) + IF( EQ_32( st->input_Fs, 32000 ) ) { - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS ); - if ( st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + IF( EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); } - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - mvr2r( st->input - L_FRAME32k, hBWE_FD->old_fdbwe_speech, L_FRAME32k ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - L_FRAME32k, hBWE_FD->old_fdbwe_speech_fx, L_FRAME32k ); - if ( st->element_mode == IVAS_CPE_TD && st->bwidth >= SWB ) + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) && GE_16( st->bwidth, SWB ) ) { - mvr2r( st->input - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->old_wtda_swb + L_FRAME32k - ( hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ), hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ) ); } - else if ( st->element_mode == IVAS_CPE_DFT && st->bwidth >= SWB ) + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && GE_16( st->bwidth, SWB ) ) { - mvr2r( st->input - hCPE->hStereoDft->dft_ovl, hBWE_FD->old_wtda_swb + L_FRAME32k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoDft->dft_ovl, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( hCPE->hStereoDft->dft_ovl, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoDft->dft_ovl, Sample_Delay_SWB_BWE ) ); } } - mvr2r( st->input, new_swb_speech, L_FRAME32k ); + Copy( st->input_fx, new_swb_speech, L_FRAME32k ); - if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE && st->extl != SWB_BWE_HIGHRATE ) + test(); + test(); + IF( NE_16( st->last_extl, SWB_BWE ) && NE_16( st->last_extl, FB_BWE ) && NE_16( st->extl, SWB_BWE_HIGHRATE ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); - if ( st->element_mode > EVS_MONO && st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + move16(); + test(); + IF( st->element_mode > EVS_MONO && EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + move16(); } - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE -= NS2SA( 32000, DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA_FX2( 32000, DELAY_FIR_RESAMPL_NS ) ); } - mvr2r( hBWE_FD->old_fdbwe_speech, &old_input[Sample_Delay_SWB_BWE], L_FRAME32k ); + Copy( hBWE_FD->old_fdbwe_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], L_FRAME32k ); - set_f( old_input, 0, Sample_Delay_SWB_BWE ); - mvr2r( hBWE_FD->old_fdbwe_speech + L_FRAME32k - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - if ( st->extl != WB_BWE ) + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( hBWE_FD->old_fdbwe_speech_fx + L_FRAME32k - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + IF( NE_16( st->extl, WB_BWE ) ) { - mvr2r( old_input, hBWE_FD->old_wtda_swb, L_FRAME32k ); + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, L_FRAME32k ); } } - if ( st->extl != SWB_BWE && st->extl != FB_BWE ) + test(); + IF( NE_16( st->extl, SWB_BWE ) && NE_16( st->extl, FB_BWE ) ) { - mvr2r( st->input, hBWE_FD->old_fdbwe_speech, L_FRAME32k ); + Copy( st->input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME32k ); } } - else /* 48 kHz */ + ELSE /* 48 kHz */ { - Sample_Delay_SWB_BWE32k = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS ); - Sample_Delay_SWB_BWE = NS2SA( 48000, DELAY_FD_BWE_ENC_12k8_NS ); - if ( st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE32k = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + Sample_Delay_SWB_BWE = NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + IF( EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE32k = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS ); - Sample_Delay_SWB_BWE = NS2SA( 48000, DELAY_FD_BWE_ENC_16k_NS ); + Sample_Delay_SWB_BWE32k = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); + Sample_Delay_SWB_BWE = NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); } dft_ovl32k = 0; - if ( st->element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - dft_ovl32k = (int16_t) ( STEREO_DFT_OVL_MAX * 32000 / 48000 ); + dft_ovl32k = (Word16) ( STEREO_DFT_OVL_MAX * 32000 / 48000 ); + move16(); } - if ( st->codec_mode == MODE1 ) + IF( EQ_16( st->codec_mode, MODE1 ) ) { - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - if ( st->element_mode == IVAS_CPE_TD ) + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) { } - else if ( st->bwidth == FB ) + ELSE IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); } - mvr2r( st->input - L_FRAME48k, hBWE_FD->old_fdbwe_speech, L_FRAME48k ); + Copy( st->input_fx - L_FRAME48k, hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k ); - if ( st->element_mode == IVAS_CPE_TD && st->bwidth >= SWB ) + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) && GE_16( st->bwidth, SWB ) ) { - if ( st->bwidth == SWB ) + IF( EQ_16( st->bwidth, SWB ) ) { /* buffers hBWE_FD->old_input[] and hBWE_FD->old_wtda_swb[] need to be at 32 kHz (inner) sampling rate */ - decimate_2_over_3_allpass( st->input - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, spchTmp, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, spchTmp, hBWE_TD->dec_2_over_3_mem_fx, + allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); - mvr2r( spchTmp, hBWE_FD->old_wtda_swb + L_FRAME32k - ( lMemRecalc32k - Sample_Delay_SWB_BWE32k ), lMemRecalc32k - Sample_Delay_SWB_BWE32k ); - mvr2r( spchTmp + lMemRecalc32k - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input, Sample_Delay_SWB_BWE32k ); + Copy( spchTmp, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( lMemRecalc32k, Sample_Delay_SWB_BWE32k ), sub( lMemRecalc32k, Sample_Delay_SWB_BWE32k ) ); + Copy( spchTmp + lMemRecalc32k - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE32k ); } - else /* FB_BWE */ + ELSE /* FB_BWE */ { - mvr2r( st->input - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->old_wtda_swb + L_FRAME48k - ( hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ), hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ); - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->L_old_wtda_swb_fx + L_FRAME48k - sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ) ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); } } - else if ( st->element_mode == IVAS_CPE_DFT && st->bwidth >= SWB ) + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && GE_16( st->bwidth, SWB ) ) { - if ( st->bwidth == SWB ) + IF( EQ_16( st->bwidth, SWB ) ) { - lerp_flt( st->input - hCPE->hStereoDft->dft_ovl, spchTmp, dft_ovl32k - Sample_Delay_SWB_BWE32k, hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + lerp( st->input_fx - hCPE->hStereoDft->dft_ovl, spchTmp, dft_ovl32k - Sample_Delay_SWB_BWE32k, hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); - mvr2r( spchTmp, hBWE_FD->old_wtda_swb + L_FRAME32k - ( dft_ovl32k - Sample_Delay_SWB_BWE32k ), dft_ovl32k - Sample_Delay_SWB_BWE32k ); + Copy( spchTmp, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - ( dft_ovl32k - Sample_Delay_SWB_BWE32k ), dft_ovl32k - Sample_Delay_SWB_BWE32k ); } - else + ELSE { - mvr2r( st->input - hCPE->hStereoDft->dft_ovl, hBWE_FD->old_wtda_swb + L_FRAME48k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoDft->dft_ovl, hBWE_FD->L_old_wtda_swb_fx + L_FRAME48k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); } } } - if ( ( st->extl != SWB_BWE && st->extl != FB_BWE && st->core == ACELP_CORE ) || ( st->element_mode == IVAS_CPE_DFT && st->core != ACELP_CORE ) /*resampling not needed for MDCT cores*/ ) + test(); + test(); + test(); + test(); + IF( ( NE_16( st->extl, SWB_BWE ) && NE_16( st->extl, FB_BWE ) && ( st->core == ACELP_CORE ) ) || ( EQ_16( st->element_mode, IVAS_CPE_DFT ) && ( st->core != ACELP_CORE ) ) /*resampling not needed for MDCT cores*/ ) { /* move the resampling out of the TDBWE path as new_swb_speech is not needed for TDBWE. */ - mvr2r( st->input, hBWE_FD->old_fdbwe_speech, L_FRAME48k ); + Copy( st->input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k ); } - else + ELSE { - if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) + test(); + IF( NE_16( st->last_extl, SWB_BWE ) && NE_16( st->last_extl, FB_BWE ) ) { /* resample 48 kHz to 32kHz */ - if ( st->last_bwidth == FB ) + IF( EQ_16( st->last_bwidth, FB ) ) { inner_frame = L_FRAME48k; + move16(); inner_Fs = 48000; - mvr2r( hBWE_FD->old_fdbwe_speech, new_swb_speech, L_FRAME48k ); + move32(); + Copy( hBWE_FD->old_fdbwe_speech_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { inner_frame = L_FRAME32k; + move16(); inner_Fs = 32000; + move32(); - if ( st->element_mode != IVAS_CPE_DFT ) + IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { - decimate_2_over_3_allpass( hBWE_FD->old_fdbwe_speech, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } - else + ELSE { - lerp_flt( hBWE_FD->old_fdbwe_speech, new_swb_speech, inner_frame, L_FRAME48k ); + lerp( hBWE_FD->old_fdbwe_speech_fx, new_swb_speech, inner_frame, L_FRAME48k ); } - if ( st->element_mode == IVAS_CPE_DFT && st->idchan == 0 ) + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && st->idchan == 0 ) { - for ( i = 0; i < STEREO_DFT_OVL_32k; i++ ) + FOR( i = 0; i < STEREO_DFT_OVL_32k; i++ ) { - hCPE->hStereoDft->output_mem_dmx_32k[i] = new_swb_speech[inner_frame - STEREO_DFT_OVL_32k + i] * hCPE->hStereoDft->win_32k[STEREO_DFT_OVL_32k - 1 - i]; + hCPE->hStereoDft->output_mem_dmx_32k_fx[i] = Mpy_32_16_1( hCPE->hStereoDft->win_32k_fx[STEREO_DFT_OVL_32k - 1 - i], new_swb_speech[sub( add( inner_frame, i ), STEREO_DFT_OVL_32k )] ); + move32(); } } } - Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); - if ( st->element_mode > EVS_MONO && st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + move16(); + test(); + IF( st->element_mode > EVS_MONO && EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + move16(); } - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE -= NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA_FX2( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); } - mvr2r( new_swb_speech, &old_input[Sample_Delay_SWB_BWE], inner_frame ); - set_f( old_input, 0, Sample_Delay_SWB_BWE ); - mvr2r( new_swb_speech + inner_frame - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - mvr2r( old_input, hBWE_FD->old_wtda_swb, inner_frame ); + Copy( new_swb_speech, &old_input_fx[Sample_Delay_SWB_BWE], inner_frame ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech + inner_frame - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, inner_frame ); } /* resample 48 kHz to 32kHz */ - if ( st->bwidth == FB ) + IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input, new_swb_speech, L_FRAME48k ); + Copy( st->input_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { - if ( st->element_mode == IVAS_CPE_TD ) + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) { - float dec_2_over_3_mem_tmp[L_FILT_2OVER3], dec_2_over_3_mem_lp_tmp[L_FILT_2OVER3_LP]; + Word16 dec_2_over_3_mem_tmp[L_FILT_2OVER3], dec_2_over_3_mem_lp_tmp[L_FILT_2OVER3_LP]; - decimate_2_over_3_allpass( st->input, L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); - mvr2r( hBWE_TD->dec_2_over_3_mem, dec_2_over_3_mem_tmp, L_FILT_2OVER3 ); - mvr2r( hBWE_TD->dec_2_over_3_mem_lp, dec_2_over_3_mem_lp_tmp, L_FILT_2OVER3_LP ); + Copy( hBWE_TD->dec_2_over_3_mem_fx, dec_2_over_3_mem_tmp, L_FILT_2OVER3 ); + Copy( hBWE_TD->dec_2_over_3_mem_lp_fx, dec_2_over_3_mem_lp_tmp, L_FILT_2OVER3_LP ); - decimate_2_over_3_allpass( st->input + L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, new_swb_speech + L_FRAME32k - lMemRecalc32k, dec_2_over_3_mem_tmp, dec_2_over_3_mem_lp_tmp ); + decimate_2_over_3_allpass_fx( st->input_fx + L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, new_swb_speech + L_FRAME32k - lMemRecalc32k, dec_2_over_3_mem_tmp, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, dec_2_over_3_mem_lp_tmp ); } - else if ( st->element_mode != IVAS_CPE_DFT ) + ELSE IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { - decimate_2_over_3_allpass( st->input, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } - else /* IVAS_CPE_DFT */ + ELSE /* IVAS_CPE_DFT */ { - /*flt2fix*/ - f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); - f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); - /*flt2fix end*/ - Word16 out_start_ind, out_end_ind; stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, new_swb_speech_fx, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 32000, 0, NULL ); - - /*fix2flt*/ - hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); - hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); - fixedToFloat_arrL( new_swb_speech_fx + out_start_ind, new_swb_speech + out_start_ind, 16, out_end_ind - out_start_ind ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); - /*fix2flt end*/ - - mvr2r( new_swb_speech - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input, Sample_Delay_SWB_BWE32k ); + Copy_Scale_sig32_16( new_swb_speech_fx, new_swb_speech, q_reImBuffer, L_FRAME48k ); + Copy( new_swb_speech - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE32k ); } } } } - else + ELSE { /* resample 48 kHz to 32kHz */ - if ( st->bwidth == FB ) + IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input, new_swb_speech, L_FRAME48k ); + Copy( st->input_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { - decimate_2_over_3_allpass( st->input, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } } } - if ( ( st->core == ACELP_CORE && st->extl != SWB_BWE_HIGHRATE && st->extl != FB_BWE_HIGHRATE ) || - ( ( st->total_brate == ACELP_9k60 || st->rf_mode ) && st->bwidth == SWB && st->element_mode == EVS_MONO ) ) + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( st->core == ACELP_CORE ) && NE_16( st->extl, SWB_BWE_HIGHRATE ) && NE_16( st->extl, FB_BWE_HIGHRATE ) ) || + ( ( EQ_32( st->total_brate, ACELP_9k60 ) || st->rf_mode ) && EQ_16( st->bwidth, SWB ) && ( st->element_mode == EVS_MONO ) ) ) { - float CldfbHB = 0; Word32 CldfbHB_fx = 0; // fixed counterpart Word16 CldfbHB_fx_e = 0; // fixed counterpart +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + Word16 realQ_neg1, imagQ_neg1, exp = 0, Cldfbtemp1; + move32(); + move16(); + move16(); - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - - /*flt2fix*/ - f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); - f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); - /*flt2fix end*/ - Word16 out_start_ind, out_end_ind; - CldfbHB_fx = stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, old_input_fx + STEREO_DFT_OVL_16k, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 16000, st->L_frame, &CldfbHB_fx_e ); - - /*fix2flt*/ - CldfbHB = me2f( CldfbHB_fx, CldfbHB_fx_e ); - hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); - hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); - fixedToFloat_arrL( old_input_fx + STEREO_DFT_OVL_16k + out_start_ind, old_input + STEREO_DFT_OVL_16k + out_start_ind, 16, out_end_ind - out_start_ind ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); - /*fix2flt end*/ + Word16 exp_icbweRefEner_fx; + Copy_Scale_sig_16_32( (const Word16 *) &old_input_fx[0], &old_input_fx_32[0], NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k, Q16 ); + CldfbHB_fx = stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, old_input_fx_32 + STEREO_DFT_OVL_16k, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 16000, st->L_frame, &CldfbHB_fx_e ); + Copy_Scale_sig_32_16( (const Word32 *) &old_input_fx_32[0], &old_input_fx[0], NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k, -Q16 ); /* delay corresponding to CLDFB delay */ - mvr2r( old_input + STEREO_DFT_OVL_16k - 20, shb_speech, L_FRAME16k ); - mvr2r( old_input, hBWE_TD->old_speech_shb + L_LOOK_16k + L_SUBFR16k - ( STEREO_DFT_OVL_16k - 20 ), STEREO_DFT_OVL_16k - 20 ); - mvr2r( old_input, hCPE->hStereoICBWE->mem_shb_speech_ref, STEREO_DFT_OVL_16k - 20 ); + Copy( old_input_fx + STEREO_DFT_OVL_16k - 20, shb_speech, L_FRAME16k ); + Copy( old_input_fx, hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - ( STEREO_DFT_OVL_16k - 20 ), STEREO_DFT_OVL_16k - 20 ); + Copy( old_input_fx, hCPE->hStereoICBWE->mem_shb_speech_ref_fx, STEREO_DFT_OVL_16k - 20 ); - if ( CldfbHB <= 0 ) + IF( LE_32( CldfbHB_fx, 0 ) ) { - CldfbHB = 1.0f; + CldfbHB_fx = EPSILON_FX; + move32(); } - hBWE_TD->cldfbHBLT_flt = 0.9f * hBWE_TD->cldfbHBLT_flt + 0.1f * ( 0.221462f /*=1/log10(32768)*/ * ( log10f( CldfbHB ) - 1.0f ) ); - - lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); - hCPE->hStereoICBWE->icbweRefEner = 0.05f * (float) sqrt( hCPE->hStereoDft->icbweRefEner ); - lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); - thr = icbwe_thr_DFT; - regV = icbwe_regressionValuesDFT; + CldfbHB_fx = L_shl( CldfbHB_fx, exp ); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ +#if 0 + Cldfbtemp1 = ( Log2_norm_lc( CldfbHB_fx ) ); + Cldfbtemp1 = add( shr( Cldfbtemp1, 6 ), shl( sub( 30, sub( exp, 2 ) ), 9 ) ); /* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_fx = L_mult( sub( Cldfbtemp1, 1741 /*3.401 Q9*/ ), 3495 ); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ +#else + Cldfbtemp1 = Log2_norm_lc( CldfbHB_fx ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + Cldfbtemp1 = sub( shr( Cldfbtemp1, 6 ), shl( add( sub( Q31 - Q30, CldfbHB_fx_e ), exp ), 9 ) ); + CldfbHB_fx = L_mult( Cldfbtemp1, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ + CldfbHB_fx = Mpy_32_16_1( L_sub( CldfbHB_fx, 1 << Q25 ), 11611 /* 0.1 * 0.221462 in Q19 */ ); + /* Resulting Q = Q25 + Q19 - Q15 = Q29 */ +#endif + hBWE_TD->cldfbHBLT = mac_r( CldfbHB_fx, 29491 /*0.9 Q15*/, hBWE_TD->cldfbHBLT ); /* cldfbHBLT is in Q13 */ + move16(); + + exp_lbEner = hCPE->hStereoDft->lbEner_fx_e; + move32(); + lbEner = Mpy_32_16_1( Sqrt32( hCPE->hStereoDft->lbEner_fx, &exp_lbEner ), 1638 /* 0.05 in Q15 */ ); + exp_icbweRefEner_fx = hCPE->hStereoDft->icbweRefEner_fx_e; + move16(); + hCPE->hStereoICBWE->icbweRefEner_fx = Mpy_32_16_1( Sqrt32( hCPE->hStereoDft->icbweRefEner_fx, &exp_icbweRefEner_fx ), 1638 /* 0.05 in Q15 */ ); + move32(); + hCPE->hStereoICBWE->icbweRefEner_fx_e = exp_icbweRefEner_fx; + move16(); + // lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); + thr = icbwe_thr_DFT_fx; + regV = icbwe_regressionValuesDFT_fx; } - else + ELSE { - if ( st->L_frame == L_FRAME ) + IF( EQ_16( st->L_frame, L_FRAME ) ) { startB = 34; + move16(); endB = 14; - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + move16(); + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - for ( nB = startB, uB = 0; nB > endB; nB--, uB++ ) + uB = 0; + move16(); + FOR( nB = startB; nB > endB; nB-- ) { - sign = ( ts % 2 ) ? 1.0f : -1.0f; - realBufferFlipped[ts][uB] = -sign * realBuffer[ts][nB]; - imagBufferFlipped[ts][uB] = sign * imagBuffer[ts][nB]; + realBufferFlipped[ts][uB] = realBuffer[ts][nB]; + move32(); + if ( s_and( ts, 1 ) != 0 ) + { + realBufferFlipped[ts][uB] = L_negate( realBufferFlipped[ts][uB] ); + move32(); + } + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + move32(); + if ( s_and( ts, 1 ) == 0 ) + { + imagBufferFlipped[ts][uB] = L_negate( imagBufferFlipped[ts][uB] ); + move32(); + } + uB = add( uB, 1 ); /* uB ++ */ } } } - else + ELSE { startB = 39; + move16(); endB = 19; - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + move16(); + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - for ( nB = startB, uB = 0; nB > endB; nB--, uB++ ) + uB = 0; + move16(); + FOR( nB = startB; nB > endB; nB-- ) { - realBufferFlipped[ts][uB] = -realBuffer[ts][nB]; + realBufferFlipped[ts][uB] = L_negate( realBuffer[ts][nB] ); + move32(); imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + move32(); + uB = add( uB, 1 ); /* uB ++ */ } } } - for ( nB = 0; nB < 10; nB++ ) + FOR( nB = 0; nB < 10; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - CldfbHB += ( realBufferFlipped[ts][nB] * realBufferFlipped[ts][nB] + imagBufferFlipped[ts][nB] * imagBufferFlipped[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBufferFlipped[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBufferFlipped[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + +#ifdef BASOP_NOGLOB + CldfbHB_fx = L_mac0_o( CldfbHB_fx, realQ_neg1, realQ_neg1, &Overflow ); + CldfbHB_fx = L_mac0_o( CldfbHB_fx, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ +#else + CldfbHB_fx = L_mac0( CldfbHB_fx, realQ_neg1, realQ_neg1 ); + CldfbHB_fx = L_mac0( CldfbHB_fx, imagQ_neg1, imagQ_neg1 ); /* Q(-2) */ +#endif } } - if ( CldfbHB <= 0 ) + CldfbHB_fx_e = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + exp = norm_l( CldfbHB_fx ); + CldfbHB_fx = L_shl( CldfbHB_fx, exp ); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ +#if 0 + Cldfbtemp1 = ( Log2_norm_lc( CldfbHB_fx ) ); + Cldfbtemp1 = add( shr( Cldfbtemp1, 6 ), shl( sub( 30, sub( exp, 2 ) ), 9 ) ); /* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_fx = L_mult( sub( Cldfbtemp1, 1741 /*3.401 Q9*/ ), 3495 ); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ +#else + Cldfbtemp1 = Log2_norm_lc( CldfbHB_fx ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + Cldfbtemp1 = sub( shr( Cldfbtemp1, 6 ), shl( add( sub( Q31 - Q30, CldfbHB_fx_e ), exp ), 9 ) ); + CldfbHB_fx = L_mult( Cldfbtemp1, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ + CldfbHB_fx = Mpy_32_16_1( L_sub( CldfbHB_fx, 1 << Q25 ), 11611 /* 0.1 * 0.221462 in Q19 */ ); + /* Resulting Q = Q25 + Q19 - Q15 = Q29 */ +#endif + hBWE_TD->cldfbHBLT = mac_r( CldfbHB_fx, 29491 /*0.9 Q15*/, hBWE_TD->cldfbHBLT ); /* cldfbHBLT is in Q13 */ + move32(); + + IF( CldfbHB_fx == 0 ) { - CldfbHB = 1.0f; + CldfbHB_fx = EPSILLON_FX; + move32(); } - hBWE_TD->cldfbHBLT_flt = 0.9f * hBWE_TD->cldfbHBLT_flt + 0.1f * ( 0.221462f /*=1/log10(32768)*/ * ( log10f( CldfbHB ) - 1.0f ) ); - if ( st->element_mode >= IVAS_CPE_DFT && hCPE->hStereoICBWE != NULL ) + test(); + IF( GE_16( st->element_mode, IVAS_CPE_DFT ) && hCPE->hStereoICBWE != NULL ) { - hCPE->hStereoICBWE->icbweRefEner = EPSILON; - for ( nB = 20; nB < 40; nB++ ) + Word32 icbweRefEner_fx = EPSILON_FX; + Word16 exp_icbweRefEner_fx = 0; + + move32(); + move16(); + FOR( nB = 20; nB < 40; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - hCPE->hStereoICBWE->icbweRefEner += ( realBuffer[ts][nB] * realBuffer[ts][nB] + imagBuffer[ts][nB] * imagBuffer[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBuffer[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBuffer[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + icbweRefEner_fx = L_mac0_o( icbweRefEner_fx, realQ_neg1, realQ_neg1, &Overflow ); + icbweRefEner_fx = L_mac0_o( icbweRefEner_fx, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ } } - hCPE->hStereoICBWE->icbweRefEner = 0.05f * sqrtf( hCPE->hStereoICBWE->icbweRefEner ); + exp_icbweRefEner_fx = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + hCPE->hStereoICBWE->icbweRefEner_fx = Mpy_32_16_1( Sqrt32( icbweRefEner_fx, &exp_icbweRefEner_fx ), 1638 /* 0.05 in Q15 */ ); + move32(); + hCPE->hStereoICBWE->icbweRefEner_fx_e = exp_icbweRefEner_fx; + move16(); } - lbEner = EPSILON; - for ( nB = 0; nB < 20; nB++ ) + lbEner = EPSILON_FX; + move32(); + FOR( nB = 0; nB < 20; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - lbEner += ( realBuffer[ts][nB] * realBuffer[ts][nB] + imagBuffer[ts][nB] * imagBuffer[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBuffer[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBuffer[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + + lbEner = L_mac0_o( lbEner, realQ_neg1, realQ_neg1, &Overflow ); + lbEner = L_mac0_o( lbEner, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ } } - lbEner = 0.05f * sqrtf( lbEner ); - thr = icbwe_thr_TDM; - regV = icbwe_regressionValuesTDM; - - cldfbSynthesis_ivas( realBufferFlipped, imagBufferFlipped, shb_speech, -1, st->cldfbSynTd ); + exp_lbEner = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + lbEner = Mpy_32_16_1( Sqrt32( lbEner, &exp_lbEner ), 1638 /* 0.05 in Q15 */ ); + thr = icbwe_thr_TDM_fx; + regV = icbwe_regressionValuesTDM_fx; + + // Copy_Scale_sig_16_32((const Word16 *)&shb_speech[0], (Word32 *)&shb_speech_32[0], L_FRAME16k,Q16); + cldfbSynthesis_ivas_fx( realBufferFlipped, imagBufferFlipped, shb_speech_32, -1, st->cldfbSynTd ); + *use_shb32 = 1; + move16(); + Copy_Scale_sig_32_16( (const Word32 *) &shb_speech_32[0], (Word16 *) &shb_speech[0], L_FRAME16k, negate( sub( q_reImBuffer, 1 ) ) ); } - if ( st->element_mode >= IVAS_CPE_DFT && hCPE->hStereoICBWE != NULL ) + IF( GE_16( st->element_mode, IVAS_CPE_DFT ) && hCPE->hStereoICBWE != NULL ) { + Word16 exp_t; hCPE->hStereoICBWE->MSFlag = 0; /* Init the multi-source flag */ - v = 0.3333f * sum_f( st->voicing, 3 ); - t = log10f( ( hCPE->hStereoICBWE->icbweRefEner + 1e-6f ) / ( lbEner + 1e-6f ) ); - + move16(); + v = Mpy_32_16_1( sum16_fx( st->voicing_fx, 3 ), 10923 /* 0.33333 in Q15 */ ); + + // t = log10f( ( hCPE->hStereoICBWE->icbweRefEner + 1e-6f ) / ( lbEner + 1e-6f ) ); + t = L_deposit_h( BASOP_Util_Divide3232_Scale( L_add( hCPE->hStereoICBWE->icbweRefEner_fx, EPSILON_FX ), L_add( lbEner, EPSILON_FX ), &exp_t ) ); + exp_t = add( exp_t, sub( hCPE->hStereoICBWE->icbweRefEner_fx_e, exp_lbEner ) ); + exp = norm_l( t ); + t = L_shl( t, exp ); + t_16 = Log2_norm_lc( t ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + t_16 = sub( shr( t_16, 6 ), shl( add( sub( Q31 - Q30, exp_t ), exp ), 9 ) ); + t = L_mult( t_16, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ /* Three Level Decision Tree to calculate a regression value first */ - if ( t < thr[0] ) /* level 1 */ + IF( LT_32( t, thr[0] ) ) /* level 1 */ { - if ( t < thr[1] ) /* level 2 */ + IF( LT_32( t, thr[1] ) ) /* level 2 */ { - regression = ( v < thr[3] ) ? regV[0] : regV[1]; /* level 3 */ + IF( LT_32( v, thr[3] ) ) + { + regression = regV[0]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[1]; + move32(); + } } - else + ELSE { - regression = ( v < thr[4] ) ? regV[2] : regV[3]; /* level 3 */ + IF( LT_32( v, thr[4] ) ) + { + regression = regV[2]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[3]; + move32(); + } } } - else + ELSE { - if ( t < thr[2] ) /* level 2 */ + IF( LT_32( t, thr[2] ) ) /* level 2 */ { - regression = ( v < thr[5] ) ? regV[4] : regV[5]; /* level 3 */ + IF( LT_32( v, thr[5] ) ) + { + regression = regV[4]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[5]; + move32(); + } } - else + ELSE { - regression = ( v < thr[6] ) ? regV[6] : regV[7]; /* level 3 */ + IF( LT_32( v, thr[6] ) ) + { + regression = regV[6]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[7]; + move32(); + } } } + test(); + test(); /* Convert the regression to a hard decision (classification) */ - if ( regression > 0.79f && !( st->bwidth < SWB || hCPE->hCoreCoder[0]->vad_flag == 0 ) ) + IF( GT_32( regression, 1696512081 /* 0.79f in Q31*/ ) && !( LT_16( st->bwidth, SWB ) || hCPE->hCoreCoder[0]->vad_flag == 0 ) ) { hCPE->hStereoICBWE->MSFlag = 1; + move16(); } } - if ( st->extl != WB_TBE && st->extl != SWB_TBE && st->extl != FB_TBE ) + test(); + test(); + IF( NE_16( st->extl, WB_TBE ) && NE_16( st->extl, SWB_TBE ) && NE_16( st->extl, FB_TBE ) ) { /* Update the previous superwideband speech buffer in case of a SWB_BWE frame - this code is in swb_tbe_enc */ delay = L_LOOK_16k + L_SUBFR16k; - mvr2r( shb_speech + L_FRAME16k - delay, hBWE_TD->old_speech_shb, delay ); + move16(); + Copy( shb_speech + sub( L_FRAME16k, delay ), hBWE_TD->old_speech_shb_fx, delay ); } } - else + ELSE { - if ( ( st->bwidth == FB || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) + test(); + test(); + IF( ( EQ_16( st->bwidth, FB ) || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) { - InitSWBencBufferStates( st->hBWE_TD, shb_speech ); + InitSWBencBufferStates_fx( st->hBWE_TD, shb_speech ); + *use_shb32 = 0; + move16(); } - else + ELSE { - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - if ( st->L_frame == L_FRAME ) + IF( EQ_16( st->L_frame, L_FRAME ) ) { L_resamp = 560; /* 6.4 kHz core -> 6 - 14 kHz SHB target. 20 ms is 560 samples in 28 kHz sample rate */ + move16(); } - else + ELSE { L_resamp = 620; /* 8 kHz core -> 7.5 - 15.5 kHz SHB target. 20 ms is 620 samples in 31 kHz sample rate */ + move16(); } /* Dirty downsampling to match Nyquist to upper frequency limit of target */ - lerp_flt( st->input, new_swb_speech, L_resamp, (int16_t) ( input_Fs / 50 ) ); + lerp( st->input_fx, new_swb_speech, L_resamp, (int16_t) Mpy_32_32( input_Fs, one_by_50_Q31 ) ); /* flip the spectrum */ - mvr2r( new_swb_speech, spchTmp, L_resamp ); - for ( i = 0; i < L_resamp; i = i + 2 ) + Copy( new_swb_speech, spchTmp, L_resamp ); + FOR( i = 0; i < L_resamp; i = i + 2 ) { - spchTmp[i] = -spchTmp[i]; + spchTmp[i] = negate( spchTmp[i] ); + move16(); } /* Dirty upsampling to match Nyquist/2 to lower frequency limit of target (reversed spectrum)*/ - lerp_flt( spchTmp, spchTmp2, L_FRAME32k, L_resamp ); - mvr2r( spchTmp2, spchTmp, L_FRAME32k ); + lerp( spchTmp, spchTmp2, L_FRAME32k, L_resamp ); + Copy( spchTmp2, spchTmp, L_FRAME32k ); } - else + ELSE { /* flip the spectrum */ - mvr2r( new_swb_speech, spchTmp, L_FRAME32k ); + Copy( new_swb_speech, spchTmp, L_FRAME32k ); - for ( i = 0; i < L_FRAME32k; i = i + 2 ) + FOR( i = 0; i < L_FRAME32k; i = i + 2 ) { - spchTmp[i] = -spchTmp[i]; + spchTmp[i] = negate( spchTmp[i] ); + move16(); } } - Decimate_allpass_steep( spchTmp, hBWE_TD->state_ana_filt_shb, L_FRAME32k, shb_speech ); + Decimate_allpass_steep_fx( spchTmp, hBWE_TD->state_ana_filt_shb_fx, L_FRAME32k, shb_speech ); + *use_shb32 = 0; + move16(); - mvr2r( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb, L_LOOK_16k + L_SUBFR16k ); + Copy( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb_fx, L_LOOK_16k + L_SUBFR16k ); /*Compute the past overlap for potential next iDFTs SHB*/ - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - for ( i = 0; i < STEREO_DFT_OVL_16k; i++ ) + FOR( i = 0; i < STEREO_DFT_OVL_16k; i++ ) { - hCPE->hStereoDft->output_mem_dmx_16k_shb[i] = shb_speech[20 + i] * hCPE->hStereoDft->win_ana_16k[STEREO_DFT_OVL_16k - 1 - i] * hCPE->hStereoDft->win_ana_16k[STEREO_DFT_OVL_16k - 1 - i]; + hCPE->hStereoDft->output_mem_dmx_16k_shb_fx[i] = L_mult( shb_speech[20 + i], mult_r( hCPE->hStereoDft->win_ana_16k_fx[STEREO_DFT_OVL_16k - 1 - i], hCPE->hStereoDft->win_ana_16k_fx[STEREO_DFT_OVL_16k - 1 - i] ) ); + move32(); } } } - if ( st->element_mode != IVAS_CPE_DFT ) + IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { /* Reset CLDFB synthesis buffer */ - set_f( st->cldfbSynTd->cldfb_state, 0.0f, st->cldfbSynTd->p_filter_length ); + set32_fx( st->cldfbSynTd->cldfb_state_fx, 0, st->cldfbSynTd->p_filter_length ); } - else + ELSE { - hCPE->hStereoDft->flip_sign = -hCPE->hStereoDft->flip_sign; /* Make sure sign is updated even if DFT SHB target is not generated */ + hCPE->hStereoDft->flip_sign = negate( hCPE->hStereoDft->flip_sign ); /* Make sure sign is updated even if DFT SHB target is not generated */ + move16(); } } /* Memory reset to compensate for 0.9375 ms offset when transitioning from IO to SWB */ /* When switching from n >1 to n = 1, we keep the enc/dec delay as 8.75/3.25 and below code not needed; only when n = 1 start, it will be 9.6875/2.3125 in that case this reset is needed for IO->BWE.*/ - if ( st->last_extl == -1 && st->element_mode == EVS_MONO ) + test(); + IF( EQ_16( st->last_extl, -1 ) && ( st->element_mode == EVS_MONO ) ) { - delay = NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); - for ( i = 0; i < delay; i++ ) + delay = NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ); + move16(); + FOR( i = 0; i < delay; i++ ) { - shb_speech[i] = (float) i * ( 0.03f * shb_speech[2 * delay - 1 - i] ); + shb_speech[i] = mult_r( mult_r( i, 983 /*0.03f Q15*/ ), shb_speech[2 * delay - 1 - i] ); + move16(); } + *use_shb32 = 0; + move16(); } return; } -#endif +#else void swb_pre_proc( Encoder_State *st, /* i/o: encoder state structure */ float *new_swb_speech, /* o : original input signal at 32kHz */ @@ -1301,3 +1471,4 @@ void swb_pre_proc( return; } +#endif diff --git a/lib_enc/swb_pre_proc_fx.c b/lib_enc/swb_pre_proc_fx.c index dbd41484e6713567f3b4b55e0652eb40a0b88da8..9a60072c3c4d412e58421a3d4cf616c2fd815854 100644 --- a/lib_enc/swb_pre_proc_fx.c +++ b/lib_enc/swb_pre_proc_fx.c @@ -164,6 +164,299 @@ void wb_pre_proc_fx( } +/*========================================================================*/ +/* FUNCTION : wb_pre_proc_ivas_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Resampling of input signal when input signal sample rate */ +/* is above 16kHz */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State *st_fx : Encoder State Structure */ +/* _ (Word16*) input : original input signal */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_wb_speech : original input signal at 16kHz Q-1 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_wtda_wb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void wb_pre_proc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 last_element_mode, /* i : last element mode */ + const Word16 *new_inp_resamp16k, /* i : original input signal in Q-1 */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz in Q-1 */ +) +{ + Word16 Sample_Delay_WB_BWE; + Word16 ramp_flag; + Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )], decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; + Word16 old_input[NS2SA( 16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + STEREO_DFT_OVL_16k + L_FRAME16k]; + Word16 *highband_new_speech; + Word16 highband_old_speech[( L_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 16]; + Word16 temp_buf[320]; + Word16 Q_wb_sp, i, max_wb; + Word16 fSwitchFromIO = 0; + Word16 ppp_mode; + Word32 temp1 = 0; + Word32 temp2 = 0; + move16(); + move32(); + move32(); + + + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + IF( st_fx->Opt_SC_VBR ) + { + ppp_mode = st_fx->hSC_VBR->ppp_mode; + move16(); + } + ELSE + { + ppp_mode = 0; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_32( st_fx->last_total_brate, ACELP_6k60 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_8k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_12k65 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_14k25 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_15k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_18k25 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_19k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_23k05 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_23k85 ) ) ) + { + fSwitchFromIO = 1; + move16(); + } + + set16_fx( old_input, 0, NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + STEREO_DFT_OVL_16k + L_FRAME16k ); + + max_wb = 1; + move16(); + FOR( i = 0; i < L_FRAME16k; i++ ) + { + max_wb = s_max( max_wb, abs_s( new_inp_resamp16k[i] ) ); + } + Q_wb_sp = norm_s( max_wb ); + + Copy_Scale_sig( new_inp_resamp16k, temp_buf, L_FRAME16k, -3 ); + temp1 = L_mac0( temp1, temp_buf[0], temp_buf[0] ); + FOR( i = 1; i < L_FRAME16k; i++ ) + { + temp1 = L_mac0( temp1, temp_buf[i], temp_buf[i] ); + temp2 = L_mac0( temp2, temp_buf[i - 1], temp_buf[i] ); + } + + if ( LT_32( temp2, Mpy_32_16_1( temp1, 31129 /*0.95f*/ ) ) ) + { + Q_wb_sp = sub( Q_wb_sp, 3 ); /* leave 3 bit headroom */ + } + Copy_Scale_sig( new_inp_resamp16k, temp_buf, L_FRAME16k, Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), Q_wb_sp ); + /* temp_buf, and the memory states are in Q_wb_sp */ + + test(); + test(); + IF( EQ_16( st_fx->extl, WB_BWE ) || EQ_16( st_fx->extl, WB_TBE ) || st_fx->igf ) + { + ramp_flag = 0; + move16(); + + test(); + test(); + test(); + test(); + IF( ( NE_16( st_fx->last_extl, WB_TBE ) && NE_16( st_fx->last_extl, WB_BWE ) && !st_fx->igf ) || + ( st_fx->igf && fSwitchFromIO ) ) + { + ramp_flag = 1; + move16(); + } + + IF( !ppp_mode ) + { + /* temp_buf is in Q_wb_sp + hb_speech and the two decimator memories are in Q_wb_sp */ + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + + IF( EQ_16( last_element_mode, IVAS_CPE_TD ) ) + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + ramp_flag = 1; + move16(); + } + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - STEREO_DFT_OVL_16k, old_input, STEREO_DFT_OVL_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + STEREO_DFT_OVL_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, &old_input[Sample_Delay_WB_BWE + STEREO_DFT_OVL_16k], L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /*Update memory*/ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( L_SUBFR * 5 / 16 ), STEREO_DFT_OVL_16k / 4, -Q_wb_sp ); + Copy( hb_speech + STEREO_DFT_OVL_16k / 4, hb_speech, ( L_FRAME16k - STEREO_DFT_OVL_16k ) / 4 ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k - STEREO_DFT_OVL_16k ) / 4, STEREO_DFT_OVL_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + ELSE IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Word16 l_recalc_16k = L_MEM_RECALC_16K + L_FILT16k + 1; /* Note: "+1" is used because L_FILT16k is not divisible by 4 */ + Word16 l_recalc_4k = ( L_MEM_RECALC_16K + L_FILT16k + 1 ) / 4; + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + IF( EQ_16( last_element_mode, IVAS_CPE_DFT ) ) + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + ramp_flag = 1; + move16(); + } + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - l_recalc_16k, old_input, l_recalc_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + l_recalc_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /* Saturation added to prevent the crash. Needs further review */ + old_input[Sample_Delay_WB_BWE] = shl_sat( hBWE_FD->mem_old_wtda_swb_fx, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, old_input + Sample_Delay_WB_BWE + l_recalc_16k, L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /*Update memory*/ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ) - l_recalc_4k, l_recalc_4k, -Q_wb_sp ); + Copy( hb_speech + l_recalc_4k, hb_speech, ( L_FRAME16k / 4 ) - l_recalc_4k ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k / 4 ) - l_recalc_4k, l_recalc_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + ELSE IF( EQ_16( st_fx->element_mode, IVAS_SCE ) ) + { + IF( EQ_32( st_fx->input_Fs, 16000 ) ) + { + flip_spectrum_and_decimby4_fx( new_inp_resamp16k, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + } + ELSE + { + Word16 l_recalc_16k = L_FILT16k + 1; /* Note: "+1" is used because L_FILT16k is not divisible by 4 */ + Word16 l_recalc_4k = ( L_FILT16k + 1 ) / 4; + + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - l_recalc_16k, old_input, l_recalc_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + l_recalc_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, old_input + Sample_Delay_WB_BWE + l_recalc_16k, L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /* update hBWE_TD->old_speech_wb memory */ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ) - l_recalc_4k, l_recalc_4k, -Q_wb_sp ); + Copy( hb_speech + l_recalc_4k, hb_speech, ( L_FRAME16k / 4 ) - l_recalc_4k ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k / 4 ) - l_recalc_4k, l_recalc_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + } + ELSE + { + flip_spectrum_and_decimby4_fx( temp_buf, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + } + + /* rescale the hb_speech and memories back to Q-1 to keep the downstream BWE coding unaffected */ + Scale_sig( hb_speech, L_FRAME16k / 4, -Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), -Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), -Q_wb_sp ); + + IF( NE_16( st_fx->extl, WB_TBE ) ) + { + /* Update the previous wideband speech buffer in case of a WB_BWE frame */ + Sample_Delay_WB_BWE = ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16; + + highband_new_speech = highband_old_speech + Sample_Delay_WB_BWE; + Copy( hb_speech, highband_new_speech, L_FRAME16k / 4 ); + Copy( highband_old_speech + L_FRAME16k / 4, hBWE_TD->old_speech_wb_fx, Sample_Delay_WB_BWE ); + } + } + } + ELSE + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->old_speech_wb_fx, 0, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + } + + if ( hBWE_FD != NULL ) + { + hBWE_FD->mem_old_wtda_swb_fx = new_inp_resamp16k[L_FRAME16k - L_MEM_RECALC_16K - L_FILT16k - 1]; + move16(); + } + + /* st->old_input_wb and st->old_wtda_wb must be updated each frame, or there are often some clicks during WB TBE <-> WB BWE switching */ + test(); + test(); + test(); + IF( ( NE_16( st_fx->extl, WB_BWE ) || ( EQ_16( st_fx->extl, WB_BWE ) && EQ_32( st_fx->total_brate, 0 ) ) ) && !ppp_mode ) + { + Sample_Delay_WB_BWE = NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + Copy( new_inp_resamp16k, &old_input[Sample_Delay_WB_BWE], L_FRAME16k ); + Copy( hBWE_FD->old_input_wb_fx, old_input, Sample_Delay_WB_BWE ); + Copy( new_inp_resamp16k + L_FRAME16k - Sample_Delay_WB_BWE, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + test(); + IF( NE_16( st_fx->extl, SWB_BWE ) && NE_16( st_fx->extl, FB_BWE ) ) + { + Copy( old_input, hBWE_FD->L_old_wtda_swb_fx, L_FRAME16k ); + st_fx->Q_old_wtda = -1; + move16(); + } + } + return; +} + + /*========================================================================*/ /* FUNCTION : swb_pre_proc_fx() */ /*------------------------------------------------------------------------*/ diff --git a/lib_enc/swb_tbe_enc.c b/lib_enc/swb_tbe_enc.c index fa64751348860272c44c241f534b7b3c42f1a5f8..61eec9e75d050923d892c027acfd8dee0f5a245a 100644 --- a/lib_enc/swb_tbe_enc.c +++ b/lib_enc/swb_tbe_enc.c @@ -44,6 +44,9 @@ #include "rom_enc.h" #include "wmc_auto.h" #include "ivas_prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif /*-----------------------------------------------------------------* * Local constants @@ -74,12 +77,7 @@ static void gainFrSmooth_En( TD_BWE_ENC_HANDLE hBWE_TD, const int16_t last_extl, static void Quant_BWE_LSF( BSTR_ENC_HANDLE hBstr, TD_BWE_ENC_HANDLE hBWE_TD, const int16_t codec_mode, const float lsp_shb[], float Q_lsfs[], const int32_t extl_brate ); static void Quant_shb_ener_sf( Encoder_State *st, float *shb_ener_sf ); static void Quant_shb_res_gshape( Encoder_State *st, float *shb_res_gshape ); -#ifdef IVAS_FLOAT_FIXED -static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, const Word16 lsf_shb_fx[], Word16 Q_lsfs_fx[], int16_t nbits ); -#else static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, const float lsf_shb[], float Q_lsfs[], int16_t nbits ); -#endif - /*-------------------------------------------------------------------* * InitSWBencBuffer() @@ -111,7 +109,15 @@ void InitSWBencBuffer( set_f( hBWE_TD->old_speech_wb, 0.0f, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); set_f( hBWE_TD->old_input_fhb, 0.0f, NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2 ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBufferStates_fx( hBWE_TD, NULL ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* To be removed */ InitSWBencBufferStates( hBWE_TD, NULL ); +#endif +#else + InitSWBencBufferStates( hBWE_TD, NULL ); +#endif for ( i = 0; i < LPC_SHB_ORDER; i++ ) { @@ -147,6 +153,10 @@ void InitSWBencBuffer( set_f( hBWE_TD->dec_2_over_3_mem, 0.0f, L_FILT_2OVER3 ); set_f( hBWE_TD->dec_2_over_3_mem_lp, 0.0f, L_FILT_2OVER3_LP ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( hBWE_TD->dec_2_over_3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( hBWE_TD->dec_2_over_3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); +#endif return; } @@ -170,6 +180,8 @@ void InitSWBencBufferStates( set_f( hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); set_f( hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); + set16_fx( hBWE_TD->mem_shb_res_fx, 0, MAX_LEN_MA_FILTER ); + set32_fx( hBWE_TD->mem_shb_res_32_fx, 0, MAX_LEN_MA_FILTER ); set_f( hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); hBWE_TD->old_mean_EnvSHBres = 0.0f; hBWE_TD->prev_enr_EnvSHBres = 1.0f; @@ -1442,7 +1454,6 @@ void swb_tbe_enc( return; } - /*-------------------------------------------------------------------* * EstimateSHBFrameGain() * @@ -2003,386 +2014,13 @@ static void gainFrSmooth_En( return; } + /*-------------------------------------------------------------------* * Quant_BWE_LSF() * * Quantize super highband spectral envolope *-------------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED -#define MAXINT32 MAX_32 -static void first_VQstages_fx( - const Word16 *const *cb, - Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ - Word16 *levels, /* i : number of levels in each stage */ - Word16 stagesVQ, /* i : number of stages */ - Word16 w[], /* i : weights */ - Word16 N, /* i : vector dimension */ - Word16 max_inner, /* i : maximum number of swaps in inner loop */ - Word16 indices_VQstage[] ) -{ - Word16 resid_buf[2 * LSFMBEST * M], *resid[2]; - Word32 dist_buf[2 * LSFMBEST], *dist[2], en; - Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; - Word16 Tmp[M], *pTmp, cs; - Word16 *pTmp_short, idx_buf[2 * LSFMBEST * MAX_VQ_STAGES], parents[LSFMBEST], counter = 0, j, - m, s, c, c2, p_max, *indices[2]; - move16(); - Word16 maxC = LSFMBEST; - move16(); -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move16(); -#endif - - /*float dd[16];*/ - const Word16 *cb_stage, *cbp; - - /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ - indices[0] = idx_buf; - move16(); - indices[1] = idx_buf + maxC * stagesVQ; - move16(); - resid[0] = resid_buf; - move16(); - resid[1] = resid_buf + maxC * N; - move16(); - dist[0] = dist_buf; - move16(); - dist[1] = dist_buf + maxC; - move16(); - - set16_fx( idx_buf, 0, ( const Word16 )( 2 * stagesVQ * maxC ) ); - set16_fx( parents, 0, maxC ); - - /* Set up inital distance vector */ - L_tmp = L_deposit_l( 0 ); - FOR( j = 0; j < N; j++ ) - { -#ifdef BASOP_NOGLOB - L_tmp1 = L_shl_o( L_mult0( u[j], w[j] ), 7, &Overflow ); /*x2.56 + Q8 + Q7 */ -#else /* BASOP_NOGLOB */ - L_tmp1 = L_shl( L_mult0( u[j], w[j] ), 7 ); /*x2.56 + Q8 + Q7 */ -#endif /* BASOP_NOGLOB */ - L_tmp1 = Mult_32_16( L_tmp1, u[j] ); /*x2.56 + Q15 + x2.56 -Q15 */ - L_tmp = L_add( L_tmp, L_tmp1 ); /*Q0 + x2.56 +x2.56 */ - } - set32_fx( dist[1], L_tmp, maxC ); - - /* Set up initial error (residual) vectors */ - pTmp = resid[1]; - move16(); - FOR( c = 0; c < maxC; c++ ) - { - Copy( u, pTmp, N ); - pTmp += N; - } - - /*----------------------------------------------------------------* - * LSF quantization - *----------------------------------------------------------------*/ - - /* Loop over all stages */ - m = 1; - move16(); - FOR( s = 0; s < stagesVQ; s++ ) - { - /* set codebook pointer to point to first stage */ - cbp = cb[s]; - - /* save pointer to the beginning of the current stage */ - cb_stage = cbp; - - /* swap pointers to parent and current nodes */ - pTmp_short = indices[0]; - indices[0] = indices[1]; - move16(); - indices[1] = pTmp_short; - move16(); - - pTmp = resid[0]; - resid[0] = resid[1]; - move16(); - resid[1] = pTmp; - move16(); - - pTmp32 = dist[0]; - dist[0] = dist[1]; - move32(); - dist[1] = pTmp32; - move32(); - - /* p_max points to maximum distortion node (worst of best) */ - p_max = 0; - move16(); - - /* set distortions to a large value */ - set32_fx( dist[1], MAXINT32, maxC ); - - FOR( j = 0; j < levels[s]; j++ ) - { - /* compute weighted codebook element and its energy */ - FOR( c2 = 0; c2 < N; c2++ ) - { - Tmp[c2] = shl( mult( w[c2], cbp[c2] ), 2 ); /* Q8 + x2.56 -Q15 +Q2 */ - move16(); - } - - en = L_mult( cbp[0], Tmp[0] ); - - FOR( c2 = 1; c2 < N; c2++ ) - { - en = L_mac( en, cbp[c2], Tmp[c2] ); /*x2.56 + x2.56 + Q-5 +Q1 */ - } - cbp += N; - move16(); - - /* iterate over all parent nodes */ - FOR( c = 0; c < m; c++ ) - { - pTmp = &resid[0][c * N]; - move16(); - L_tmp = L_mult( pTmp[0], Tmp[0] ); - FOR( c2 = 1; c2 < N; c2++ ) - { - L_tmp = L_mac( L_tmp, pTmp[c2], Tmp[c2] ); /* */ - } - - L_tmp = L_add( dist[0][c], L_sub( en, L_shl( L_tmp, 1 ) ) ); - - IF( LE_32( L_tmp, dist[1][p_max] ) ) - { - /* replace worst */ - dist[1][p_max] = L_tmp; - move32(); - indices[1][p_max * stagesVQ + s] = j; - move16(); - parents[p_max] = c; - move16(); - - /* limit number of times inner loop is entered */ - IF( LT_16( counter, max_inner ) ) - { - counter = add( counter, 1 ); - IF( LT_16( counter, max_inner ) ) - { - /* find new worst */ - p_max = maximum_32_fx( dist[1], maxC, &f_tmp ); - } - ELSE - { - /* find minimum distortion */ - p_max = minimum_32_fx( dist[1], maxC, &f_tmp ); - } - } - } - } - } - - /*------------------------------------------------------------* - * Compute error vectors for each node - *------------------------------------------------------------*/ - cs = 0; - move16(); - FOR( c = 0; c < maxC; c++ ) - { - /* subtract codebook entry from the residual vector of the parent node */ - pTmp = resid[1] + c * N; - move16(); - Copy( resid[0] + parents[c] * N, pTmp, N ); - Vr_subt( pTmp, cb_stage + ( indices[1][cs + s] ) * N, pTmp, N ); - - /* get indices that were used for parent node */ - Copy( indices[0] + parents[c] * stagesVQ, indices[1] + cs, s ); - cs = add( cs, stagesVQ ); - } - - m = maxC; - move16(); - } - - Copy( indices[1], indices_VQstage, maxC * stagesVQ ); - - return; -} -static Word16 dotp_loc( - const Word16 x[], /* i : vector x[] */ - const Word32 y[], /* i : vector y[] */ - const int16_t n /* i : vector length */ -) -{ - Word16 i; - Word32 suma; - Word16 guarded_bits = find_guarded_bits_fx( n ); - suma = L_shr( Mpy_32_16_1( y[0], x[0] ), guarded_bits ); - - FOR( i = 1; i < n; i++ ) - { - suma = L_add( suma, L_shr( Mpy_32_16_1( y[i], x[i] ), guarded_bits ) ); - } - suma = L_shl_sat( suma, guarded_bits ); - - return extract_h( suma ); -} -static void LVQQuant_BWE_LSF( - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle*/ - const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs */ - Word16 Q_lsfs_fx[], /* o : quanitzed LSFs */ - Word16 nbits ) -{ - - Word16 lsf_fx[LPC_SHB_ORDER]; - Word16 lsf_q_fx[LPC_SHB_ORDER]; - Word16 i, c2, dim1 = 6; - move16(); - Word16 levels[1], numbits_VQ; - Word16 c2_fx_temp; - - Word16 w_fx[8] = { 5120, 5120, 2048, 2048, 2048, 1024, 1024, 1024 }; // Q0 - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - Word16 cand_fx[LPC_SHB_ORDER], quant_fx[LPC_SHB_ORDER], e_fx[2], ftmp_fx; - const Word16 *cb_stage_fx; - Word16 indices_firstVQ[LSFMBEST]; - - Word16 Idx, idx_lead, idx_scale; - UWord32 LVQ_index; - Word16 dd_fx[LATTICE_DIM], cv_out_fx[LATTICE_DIM]; - Word16 bits_lvq, predictor_bits, empty_bits; - - empty_bits = 0; /* This is the difference to 21 bits, if we want lower number of bits */ - move16(); - nbits = sub( nbits, empty_bits ); /* THIS IS TO SIMULATE DIFFERENT NUMBER OF input BITS - should be removed */ - move16(); - c2 = sub( NUM_BITS_SHB_MSLVQ, nbits ); - move16(); - numbits_VQ = config_LSF_BWE[c2 * 3]; - move16(); - levels[0] = config_LSF_BWE[c2 * 3 + 1]; - move16(); - predictor_bits = config_LSF_BWE[c2 * 3 + 2]; - move16(); - IF( LT_16( nbits, 19 ) ) - { - cb_stage_fx = cb_LSF_BWE_fx[1]; - } - ELSE - { - cb_stage_fx = cb_LSF_BWE_fx[0]; - } - - FOR( i = 0; i < LPC_SHB_ORDER; i++ ) - { - lsf_fx[i] = sub( 16384, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); - } - - /* remove mean */ - v_sub_16( lsf_fx, SHB_LSF_mean_fx, Q_lsfs_fx, LPC_SHB_ORDER ); - - /* 6D multi-stage 6bit coding */ - first_VQstages_fx( &cb_stage_fx, Q_lsfs_fx, levels, 1, w_fx, dim1, 3000, indices_firstVQ ); - - - /* 8D MSLVQ coding */ - bits_lvq = sub( sub( nbits, numbits_VQ ), predictor_bits ); - Copy( SHB_LSF_mean_fx, cand_fx, LPC_SHB_ORDER ); - - Idx = indices_firstVQ[0]; - - v_add_16( cand_fx, cb_stage_fx + Idx * dim1, cand_fx, dim1 ); - - /* LVQ quantization */ - Copy( cand_fx, quant_fx, LPC_SHB_ORDER ); - - v_sub_16( lsf_fx, cand_fx, dd_fx, LATTICE_DIM ); - - mslvq_ivas_16( dd_fx, quant_fx, cv_out_fx, &idx_lead, &idx_scale, w_fx, 0, ( nbits < 19 ), bits_lvq ); - - IF( EQ_16( idx_scale, -1 ) ) - { - set16_fx( cv_out_fx, 0, LATTICE_DIM ); - } - v_add_16( cand_fx, quant_fx, cand_fx, LATTICE_DIM ); - - /* arrange the LSF candidate vector prior to selection to an ascending order*/ - v_sort( cand_fx, 0, LPC_SHB_ORDER - 1 ); - - set16_fx( Q_lsfs_fx, 0, LPC_SHB_ORDER ); - /* mvr2r( mean_lsf, Q_lsfs, LPC_SHB_ORDER ); */ - - v_add_16( Q_lsfs_fx, cb_stage_fx + Idx * dim1, Q_lsfs_fx, dim1 ); - - /* write VQ indexes */ - push_indice( hBstr, IND_SHB_LSF, Idx, numbits_VQ ); - - /* write MSLVQ index */ - LVQ_index = index_lvq_SHB_fx( idx_lead, idx_scale, bits_lvq, cv_out_fx, ( nbits < 19 ) ); - - IF( GT_16( bits_lvq, 15 ) ) - { - push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) & ( 0xffff >> 1 ) ), 15 ); - push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) >> 15 ) & ( 0xffff >> 1 ), bits_lvq - 15 ); - } - ELSE - { - push_indice( hBstr, IND_SHB_LSF, (Word16) LVQ_index, bits_lvq ); - } - - v_add_16( Q_lsfs_fx, quant_fx, lsf_q_fx, LATTICE_DIM ); /* quantized mean removed data for first 8 dim*/ - - /* predict last 2 components */ - IF( predictor_bits == 0 ) - { - lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, LastCoefPred_0bit_fx, LATTICE_DIM ); - lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_0bit_fx[LATTICE_DIM + 1], LATTICE_DIM ); - } - ELSE - { - v_sub_16( &lsf_fx[LATTICE_DIM], &SHB_LSF_mean_fx[LATTICE_DIM], &lsf_q_fx[LATTICE_DIM], 2 ); - - FOR( i = 0; i < 2; i++ ) - { - ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM]; - - e_fx[i] = mult( ftmp_fx, ftmp_fx ); - - ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i + LATTICE_DIM + 1], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM + 1]; - - e_fx[i] = add_sat( e_fx[i], mult( ftmp_fx, ftmp_fx ) ); - } - - c2_fx_temp = minimum_fx( e_fx, 2, &ftmp_fx ); - - lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp], LATTICE_DIM ); - - lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp + LATTICE_DIM + 1], LATTICE_DIM ); - - push_indice( hBstr, IND_SHB_LSF, c2, 1 ); - } - - if ( empty_bits > 0 ) - { - push_indice( hBstr, IND_SHB_LSF, 0, empty_bits ); - } - - v_add_16( SHB_LSF_mean_fx, lsf_q_fx, lsf_q_fx, LPC_SHB_ORDER ); - - v_sort( lsf_q_fx, 0, LPC_SHB_ORDER - 1 ); - - FOR( i = 0; i < LPC_SHB_ORDER; i++ ) - { - Q_lsfs_fx[i] = sub_sat( 16384, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); - } - - return; -} -#else static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle*/ const float lsf_shb[], /* i : unquanitzed LSFs */ @@ -2519,7 +2157,6 @@ static void LVQQuant_BWE_LSF( return; } -#endif /*-------------------------------------------------------------------* * Quant_BWE_LSF() * @@ -2545,25 +2182,7 @@ static void Quant_BWE_LSF( if ( extl_brate == SWB_TBE_1k75 ) { - -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 lsf_shb_fx[LPC_SHB_ORDER]; - for ( i = 0; i < LPC_SHB_ORDER; i++ ) - { - lsf_shb_fx[i] = (Word16) ( lsf_shb[i] * 32767 ); - } -#endif - LVQQuant_BWE_LSF( hBstr, lsf_shb_fx, lsf_shb_fx, NUM_BITS_SHB_MSLVQ ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( i = 0; i < LPC_SHB_ORDER; i++ ) - { - Q_lsfs[i] = (float) ( (float) lsf_shb_fx[i] / 32767.0 ); - } -#endif -#else LVQQuant_BWE_LSF( hBstr, lsf_shb, Q_lsfs, NUM_BITS_SHB_MSLVQ ); -#endif } else { @@ -2764,6 +2383,7 @@ static void Quant_shb_ener_sf( return; } + /*-------------------------------------------------------------------* * Quant_shb_res_gshape() * diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c index 5eb1d275a4b05b4d40890ae75a8ad1c104d1cf3a..b7901de5bd138c7397a22398151422e80fb3e543 100644 --- a/lib_enc/swb_tbe_enc_fx.c +++ b/lib_enc/swb_tbe_enc_fx.c @@ -9,10 +9,21 @@ //#include "prot_fx.h" #include "rom_com_fx.h" #include "rom_com.h" +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#include "ivas_prot.h" /* Function prototypes */ #include "stl.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define ENVSHBRES_ACORR_MIN 40 /* minimum lag for calculating autocorrelation function on SHB residual TD envelope */ +#define ENVSHBRES_ACORR_MAX 80 /* maximum lag for calculating autocorrelation function on SHB residual TD envelope */ + + /*-----------------------------------------------------------------* * Local functions *-----------------------------------------------------------------*/ @@ -30,9 +41,12 @@ static void determine_gain_weights_fx( const Word32 *gain, Word16 *weights, cons static void QuantizeSHBsubgains_fx( Encoder_State *st_fx, Word16 *subgains, const Word16 extl ); +static void QuantizeSHBsubgains_ivas_fx( Encoder_State *st_fx, Word16 subgains[], const Word16 extl ); static void QuantizeSHBframegain_fx( Encoder_State *st_fx, Word32 *GainFrame, const Word16 extl, Word32 extl_brate, Word16 *rf_gainFrame_ind ); +static void QuantizeSHBframegain_ivas_fx( Encoder_State *st_fx, Word32 *GainFrame, const Word16 extl, Word32 extl_brate, Word16 *rf_gainFrame_ind, const Word16 flag_conservative ); + static Word16 closest_centroid_fx( const Word16 *data, const Word16 *weights, const Word16 *quantizer, const Word16 centroids, const Word16 length ); static Word16 closest_centroid_lc_fx( const Word16 *data, const Word16 *quantizer, const Word16 centroids ); @@ -61,6 +75,8 @@ static void EstimateSHBGainShape_fx( const Word16 length, static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ); +static Word32 pow_off_pk_corrected_fx( Word16 a[], Word16 len, Word16 step ); + static void find_max_mem_enc( Encoder_State *st_fx, Word16 *n_mem, Word16 *n_mem2 ); static void rescale_genSHB_mem_enc( Encoder_State *st_fx, Word16 sf ); static void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ); @@ -72,10 +88,19 @@ static void Quant_lower_LSF_fx( const Word16 lsf[], static Word16 Quant_mirror_point_fx( const Word16 lsf[], const Word16 lsf_q[], Word16 *m ); static Word16 Find_LSF_grid_fx( const Word16 lsf[], Word16 lsf_q[], const Word16 m ); + static void Quant_BWE_LSF_fx( Encoder_State *st_fx, const Word16 lsp_shb[], Word16 Q_lsfs[] ); + +static void Quant_BWE_LSF_ivas_fx( BSTR_ENC_HANDLE hBstr, TD_BWE_ENC_HANDLE hBWE_TD, const Word16 codec_mode, const Word16 lsf_shb_fx[], Word16 Q_lsfs_fx[], const Word32 extl_brate ); + static void Quant_shb_ener_sf_fx( Encoder_State *st_fx, Word32 *shb_ener_sf_fx_32, Word16 Q_shb ); + +static void Quant_shb_ener_sf_ivas_fx( Encoder_State *st_fx, Word32 *shb_ener_sf_Q31, Word16 Q_ener ); + static void Quant_shb_res_gshape_fx( Encoder_State *st_fx, Word16 *shb_res_gshape_fx ); +static void Quant_shb_res_gshape_ivas_fx( Encoder_State *st, Word16 shb_res_gshape_fx[] ); + static void gainFrSmooth_En_fx( Encoder_State *st_fx, Word16 *shb_frame_fx, const Word16 *lpc_shb_fx, @@ -238,57 +263,59 @@ void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ) { Word16 i; Word16 n_mem_32; - Word16 max = 0; + Word16 max_16 = 0; Word32 Lmax = 0; TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + move16(); + move32(); FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) - max = s_max( max, abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ) ); + max_16 = s_max( max_16, abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ) ); FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); } FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ); } FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ); } FOR( i = 0; i < 10; i++ ) { - IF( abs_s( hBWE_TD->state_lpc_syn_fx[i] ) > max ) - max = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->state_lpc_syn_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); } FOR( i = 0; i < 5; i++ ) { - IF( abs_s( hBWE_TD->state_syn_shbexc_fx[i] ) > max ) - max = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->state_syn_shbexc_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); } - IF( max == 0 ) + IF( max_16 == 0 ) { *n_mem = 15; move16(); } ELSE { - *n_mem = norm_s( max ); + *n_mem = norm_s( max_16 ); move16(); } FOR( i = 0; i < 2; i++ ) { - IF( L_abs( hBWE_TD->mem_csfilt_fx[i] ) > Lmax ) + IF( GT_32( L_abs( hBWE_TD->mem_csfilt_fx[i] ), Lmax ) ) Lmax = L_abs( hBWE_TD->mem_csfilt_fx[i] ); } @@ -306,6 +333,7 @@ void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ) *n_mem = sub( s_min( *n_mem, n_mem_32 ), 1 ); move16(); *n_mem = s_max( *n_mem, 0 ); + move16(); } void rescale_genWB_mem_enc( Encoder_State *st_fx, Word16 sf ) @@ -1063,7 +1091,7 @@ void wb_tbe_enc_fx( tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */ #else /* BASOP_NOGLOB */ L_tmp = L_shl( L_tmp, add( exp, 10 ) ); - tmp = round_fx( L_tmp ); /* Q15 */ + tmp = round_fx( L_tmp ); /* Q15 */ #endif } @@ -1118,204 +1146,1795 @@ void wb_tbe_enc_fx( } -void fb_tbe_reset_enc_fx( - Word32 elliptic_bpf_2_48k_mem_fx[][4], - Word32 *prev_fb_energy_fx, - Word16 elliptic_bpf_2_48k_mem_fx_Q[], - Word16 *prev_fb_energy_fx_Q ) -{ - set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); - *prev_fb_energy_fx = 0; - move16(); - set16_fx( elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); - *prev_fb_energy_fx_Q = 0; - move16(); - - return; -} -/*======================================================================================*/ -/* FUNCTION : void swb_tbe_enc_fx () */ -/*--------------------------------------------------------------------------------------*/ -/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ -/*--------------------------------------------------------------------------------------*/ +/*==========================================================================*/ +/* FUNCTION : void wb_tbe_enc_ivas_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : WB TBE encoder, 6 - 8 kHz band encoding module */ +/*--------------------------------------------------------------------------*/ /* INPUT ARGUMENTS : */ -/* _(Word16) coder_type : coding type */ -/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ -/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ -/* _(Word16[]) voice_factors :voicing factors Q15 */ -/* _(Word16*) Q_white_exc :Q Format of White Exc */ -/*--------------------------------------------------------------------------------------*/ +/* Word16 *new_speech i : original input signal Q(-1) */ +/* Word32 *bwe_exc_extended i : bandwidth extended exciatation Q(2*Q_new) */ +/* Word16 voice_factors[] i : voicing factors Q15 */ +/* Word16 pitch_buf[] i : pitch for each subframe Q6 */ +/*--------------------------------------------------------------------------*/ /* OUTPUT ARGUMENTS : */ -/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ -/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ -/*--------------------------------------------------------------------------------------*/ +/* Word16 *synth o : WB SHB final synthesis */ +/*--------------------------------------------------------------------------*/ /* INPUT/OUTPUT ARGUMENTS : */ -/* _ Encoder_State *st_fx: : Encoder state structure */ -/*--------------------------------------------------------------------------------------*/ +/* Encoder_State *st_fx i/o: encoder state structure */ +/*--------------------------------------------------------------------------*/ /* RETURN ARGUMENTS : */ /* _ None */ -/*--------------------------------------------------------------------------------------*/ -/* CALLED FROM : TX */ -/*======================================================================================*/ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ -void swb_tbe_enc_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ - const Word16 coder_type, /* i : coding type */ - Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ - Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ - const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ - Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ - Word16 *Q_white_exc, - Word16 Q_new, - Word16 Q_shb, - Word16 *voicing, /* i : OL maximum normalized correlation */ - const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +void wb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz Q(-1) */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation Q(2*Q_new) */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors Q15 */ + const Word16 pitch_buf[] /* i : pitch for each subframe Q6 */ ) { - Word16 i, j; - - Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 i, j, k; + Word16 hb_old_speech[( L_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 16]; Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; - Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; - Word32 GainFrame_fx; - Word16 GainShape_fx[NUM_SHB_SUBFR]; - Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; - Word16 weights_lsp[LPC_SHB_ORDER]; - Word16 Q_out; - Word16 *shb_frame_fx, *shb_new_speech_fx; - Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ - Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 shaped_wb_excitation[( L_FRAME16k + L_SHB_LAHEAD ) / 4]; + Word16 exc4kWhtnd[L_FRAME16k / 4]; + /*Word16 ana_align_delay = WBTBE_ANA_ALIGNDELAY; */ /* -L_SHB_LAHEAD/4 - 5 */ + Word32 GainFrame; + Word16 GainShape[NUM_SHB_SUBFR]; + Word16 lpc_wb[LPC_SHB_ORDER_WB + 1]; + Word32 lpc_wb_32_fx[LPC_SHB_ORDER_WB + 1]; + Word16 lsp_wb[LPC_SHB_ORDER_WB], weights_lsp[LPC_SHB_ORDER_WB] = { 32767, 32767 }; + Word16 *hb_new_speech, *hb_frame /*, hb_speech[ L_FRAME16k ]*/; + Word16 R_h[LPC_SHB_ORDER_WB + 2], R_l[LPC_SHB_ORDER_WB + 2]; Word16 Q_R; - Word32 LepsP[LPC_SHB_ORDER + 1]; - - Word16 ana_align_delay[2] = { -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ), -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) }; - Word32 prev_pow_fx, curr_pow_fx, Lscale; - Word32 p2m_in_fx, p2m_out_fx; + Word32 LepsP[LPC_SHB_ORDER_WB + 1]; + move16(); + move16(); - Word16 exp_out, exp, exp1, frac; - Word16 cnt, n_mem, n_mem2; - Word32 L_tmp, L_tmp1; - Word16 Q_bwe_exc; + Word32 prev_pow, curr_pow, Lscale; + /* Word16 scale; */ + /*Word16 ramp_flag;*/ + Word32 p2m_in, p2m_out; + /*Word16 cnt, max =0;*/ + Word16 n_mem, Q_bwe_exc, Q_bwe_exc_ext, exp_out; /* Q_hb_frame; */ + Word32 L_tmp, Lmax; + Word16 tmp, exp, Q_out, sc; + Word16 Q_ns = -1; + move16(); - Word16 frGainAttenuate, frGainSmoothEn; - Word16 MA_lsp_shb_spacing; - Word16 temp_swb_fac, feedback; - Word32 L_feedback; - Word16 tmp, tmp1, tmp2; - Word32 Lmax; - Word16 sc; - Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; - Word16 sd_uq_q_fx; + Word16 pitBufAvg_fx, voicingBufAvg_fx; Word16 vf_modified_fx[NB_SUBFR16k]; - Word16 pitBufAvg_fx; - Word16 voicingBufAvg_fx; - Word16 sum1, sum2; - Word16 recip, Q_recip; - const Word16 *ptr_lsp_interp_coef_fx; - - Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; - Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; - - /*Word32 shb_ener_sf_fx_32[4];*/ - Word32 shb_ener_sf_Q31; - Word16 shb_res_fx[L_FRAME16k]; - Word16 shb_res_gshape_fx[NB_SUBFR16k]; - Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; - Word16 vf_ind_fx; - - Word16 formant_fac_fx; - Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; - - Word16 mean_vf; - Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; - Word16 refl[M]; - Word16 tilt_para; - Word16 Q_bwe_exc_fb; - Word16 n_subfr_saturation; + Word16 temp_wb_fac_fx, feedback_fx; + Word16 lsp_spacing_fx; + Word16 lsp_wb_temp_fx[LPC_SHB_ORDER_WB], lpc_wb_temp_fx[LPC_SHB_ORDER_WB + 1]; + Word32 L_feedback; + Word16 frac, exp1; + Word16 uv_flag; + Word16 dummy = 0; + Word16 avg_voice_fac; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif - TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; - RF_ENC_HANDLE hRF = st_fx->hRF; - - /* init and buffers set up */ - exp1 = 0; /* to avoid compilation warnings */ - set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); - - /* compensate for the delay in target generation and subframe LA */ - shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; move16(); - /* set up the speech buffers for TBE processing*/ - shb_new_speech_fx = shb_old_speech_fx + ( L_LOOK_16k + L_SUBFR16k ); - move16(); - Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( L_LOOK_16k + L_SUBFR16k ) ); - Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); - Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + /*Word16 att = 32767;*/ - /* autocorrelation of SHB speech for 10-th order LP analysis */ - autocorr_fx( shb_old_speech_fx, - LPC_SHB_ORDER + 1, - R_h, /* autocorr (msb) Q15 */ - R_l, /* autocorr (lsb) */ - &Q_R, - NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, - win_lpc_shb_fx, - 0, - 1 ); + hb_new_speech = hb_old_speech + WBTBE_LOOK_LSUFBR_5_OVER_16; + hb_frame = hb_old_speech + WBTBE_LSUBFR_5_OVER_16 + WBTBE_ANA_ALIGNDELAY; + Copy( hBWE_TD->old_speech_wb_fx, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + Copy( hb_speech, hb_new_speech, LFRAME16K_OVER_4 ); + Copy( hb_old_speech + LFRAME16K_OVER_4, hBWE_TD->old_speech_wb_fx, WBTBE_LOOK_LSUFBR_5_OVER_16 ); - /* Spectral smoothing of autocorrelation coefficients */ test(); - IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + test(); + test(); + test(); + test(); + test(); + IF( ( NE_16( st_fx->last_extl, WB_TBE ) && NE_16( st_fx->last_extl, WB_BWE ) ) && ( EQ_16( st_fx->clas, UNVOICED_CLAS ) || ( LT_16( st_fx->voicing_fx[0], 16384 ) && LT_16( st_fx->voicing_fx[1], 16384 ) && LT_16( st_fx->voicing_fx[2], 16384 ) ) ) && !st_fx->igf ) { - FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + /* In case of unvoiced signals after switching cores, back-propagate the target signal */ + Copy( hb_speech, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + i = WBTBE_LOOK_LSUFBR_5_OVER_16; + move16(); + k = 0; + move16(); + + FOR( j = 0; j < L_SUBFR16k; j = j + 4 ) { - L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); - L_Extract( L_tmp, &R_h[i], &R_l[i] ); + L_tmp = L_mult( hb_old_speech[i], ola_win_shb_switch_fold_fx[j] ); + hb_old_speech[i] = mac_r( L_tmp, hb_speech[j], ola_win_shb_switch_fold_fx[L_SUBFR16k - 4 - j] ); + move16(); + i = sub( i, 1 ); + k = add( k, 1 ); } } - /* Set the autocorr[0] element to a non-negative value */ - R_l[0] = s_max( R_l[0], 1 ); - move16(); - - E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ - { - Word16 enerG, lpc_shb1[M + 1]; + autocorr_fx( hb_old_speech, LPC_SHB_ORDER_WB + 1, R_h, R_l, &Q_R, ( ( NS2SA( INT_FS_12k8, 5000000L ) + L_SUBFR + L_FRAME ) * 5 / 16 ), win_lpc_hb_wb_fx, 0, 1 ); - /* extend the lpc_shb to a 16th order gain calc */ - set16_fx( lpc_shb1, 0, M + 1 ); - Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_wb_temp_fx, LepsP, LPC_SHB_ORDER_WB, NULL ); - /* estimate the LP gain */ - enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + Copy_Scale_sig( lpc_wb_temp_fx, lpc_wb_temp_fx, LPC_SHB_ORDER_WB + 1, sub( norm_s( lpc_wb_temp_fx[0] ), 2 ) ); - /* if the LP gain is greater than a threshold, avoid saturation */ - IF( GT_16( enerG, 256 /*32 Q3*/ ) ) - { - set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); - E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ - } + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb_temp_fx[i] ), 1 ) ); + move32(); } - /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ - Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb_temp_fx, st_fx->prev_lsp_wb_temp_fx, LPC_SHB_ORDER_WB ); - /* Expand bandwidth of the LP coeffs */ - test(); - IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_temp_fx[i] = lsp_wb_temp_fx[i]; + move16(); + } + + /* lsp_spacing_fx = 16384; move16(); */ + lsp_spacing_fx = lsp_wb_temp_fx[0]; + move16(); + FOR( i = 1; i < LPC_SHB_ORDER_WB; i++ ) + { + /*if ( i == 0 ) + { + tmp = lsp_wb_temp_fx[0]; move16(); + } + else + {*/ + tmp = sub( lsp_wb_temp_fx[i], lsp_wb_temp_fx[i - 1] ); + /*} */ + + lsp_spacing_fx = s_min( lsp_spacing_fx, tmp ); + } + + /* Spectral smoothing of autocorrelation coefficients */ + FOR( i = 1; i <= LPC_SHB_ORDER_WB; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + test(); + IF( EQ_16( st_fx->rf_mode, 1 ) || EQ_32( st_fx->extl_brate, WB_TBE_0k35 ) ) + { + E_LPC_lev_dur( R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_LBR_WB, NULL ); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_LBR_WB + 1, sub( norm_s( lpc_wb[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + FOR( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32(); /*Q27 */ + } + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + FOR( i = 0; i < LPC_SHB_ORDER_LBR_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_LBR_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, lbr_wb_bwe_lsfvq_cbook_2bit_fx, 4, LPC_SHB_ORDER_LBR_WB ); + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->lsf_WB = i; + move16(); + } + ELSE + { + push_indice( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_LBR_WB_LSF ); + } + + Copy( lbr_wb_bwe_lsfvq_cbook_2bit_fx + i * LPC_SHB_ORDER_LBR_WB, lsp_wb, LPC_SHB_ORDER_LBR_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + set16_fx( lpc_wb + LPC_SHB_ORDER_LBR_WB + 1, 0, ( LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB ) ); + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + + FOR( i = 1; i < LPC_SHB_ORDER_LBR_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + ELSE /* 13.2kbps */ + { + E_LPC_lev_dur( R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_WB, NULL ); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_WB + 1, sub( norm_s( lpc_wb[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32(); /*Q27 */ + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, wb_bwe_lsfvq_cbook_8bit_fx, 256, LPC_SHB_ORDER_WB ); /*move16(); */ + + push_indice( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_WB_LSF ); + Copy( wb_bwe_lsfvq_cbook_8bit_fx + i * LPC_SHB_ORDER_WB, lsp_wb, LPC_SHB_ORDER_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_WB ); + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + + uv_flag = 0; + move16(); + test(); + if ( EQ_32( st_fx->extl_brate, WB_TBE_1k05 ) && EQ_16( st_fx->coder_type_raw, UNVOICED ) ) + { + uv_flag = 1; + move16(); + } + + Copy( voice_factors, vf_modified_fx, NB_SUBFR16k ); + IF( EQ_16( st_fx->coder_type, VOICED ) ) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + /*vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1];*/ + vf_modified_fx[i] = add( mult_r( 26214, voice_factors[i] ), mult_r( 6553, voice_factors[i - 1] ) ); + move16(); + } + IF( NE_16( st_fx->L_frame, L_FRAME ) ) + { + vf_modified_fx[4] = add( mult_r( 26214, voice_factors[4] ), mult_r( 6553, voice_factors[3] ) ); + move16(); + } + } + + /* From low band excitation, generate highband excitation */ + Lmax = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[i] ) ); + } + + Q_bwe_exc = 31; + move16(); + if ( Lmax != 0 ) + { + Q_bwe_exc = norm_l( Lmax ); + } + Q_bwe_exc = sub( Q_bwe_exc, 3 ); + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + find_max_mem_wb_enc( st_fx, &n_mem ); + + if ( GT_16( sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ), n_mem ) ) + { + Q_bwe_exc = add( st_fx->prev_Q_bwe_exc, n_mem ); + } + + IF( uv_flag ) + { + if ( GT_16( Q_bwe_exc, 20 ) ) + { + Q_bwe_exc = 20; + move16(); /* restrict this to 20 due to the Q factor requireemnt of the random number generator (keep 1 bit headroom) */ + } + } + + prev_pow = 0; + move32(); +#ifdef NONBE_FIX_1132_THRESHOLD_POW_IN_SWB_TBE + IF( st_fx->element_mode > EVS_MONO ) + { + tmp = sub( shl( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), 31 + 16 ); +#ifdef BASOP_NOGLOB + prev_pow = L_shl_sat( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(st_fx->prev_Q_bwe_exc-16))*/ +#else + prev_pow = L_shl( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(st_fx->prev_Q_bwe_exc-16))*/ +#endif + } +#endif + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + prev_pow = L_mac0( prev_pow, hBWE_TD->state_syn_shbexc_fx[i], hBWE_TD->state_syn_shbexc_fx[i] ); /* Q(2*st_fx->prev_Q_bwe_exc) */ + } + + rescale_genWB_mem_enc( st_fx, sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) ); + + Copy( hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + bwe_exc_extended_16[i + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[i], sc ) ); + move16(); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + Copy( hBWE_TD->state_syn_shbexc_fx, shaped_wb_excitation, L_SHB_LAHEAD / 4 ); + Q_bwe_exc_ext = sub( Q_bwe_exc, 16 ); + + GenShapedWBExcitation_fx( shaped_wb_excitation + L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, hBWE_TD->mem_csfilt_fx, + hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, + hBWE_TD->state_lpc_syn_fx, st_fx->coder_type, bwe_exc_extended_16, Q_bwe_exc_ext, hBWE_TD->bwe_seed, + vf_modified_fx, uv_flag, st_fx->igf ); + + curr_pow = 0; + move32(); +#ifdef NONBE_FIX_1132_THRESHOLD_POW_IN_SWB_TBE + IF( st_fx->element_mode > EVS_MONO ) + { + tmp = sub( shl( Q_bwe_exc_ext, 1 ), 31 + 16 ); +#ifdef BASOP_NOGLOB + curr_pow = L_shl_sat( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(Q_bwe_exc_ext))*/ +#else + curr_pow = L_shl( 1407374848l /*0.00001f Q47*/, tmp ); /* 2*(Q_bwe_exc_ext) */ +#endif + } +#endif + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + curr_pow = L_mac0( curr_pow, shaped_wb_excitation[i + L_SHB_LAHEAD / 4], shaped_wb_excitation[i + L_SHB_LAHEAD / 4] ); /* Q(2*Q_bwe_exc_ext) */ + } + + IF( GT_16( voice_factors[0], 24576 ) ) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc_ext) */ + } + + Lscale = root_a_over_b_fx( curr_pow, shl_r( Q_bwe_exc_ext, 1 ), prev_pow, shl_r( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), &exp ); + + FOR( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) + { + L_tmp = Mpy_32_16_1( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ +#ifdef BASOP_NOGLOB + shaped_wb_excitation[i] = round_fx_sat( L_shl_sat( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#else + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#endif + move16(); + } + + Lscale = root_a_fx( Lscale, sub( 31, exp ), &exp ); + L_tmp = Mpy_32_16_1( Lscale, shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + move16(); + + /* Update WB excitation */ + Copy( shaped_wb_excitation + L_FRAME16k / 4, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD / 4 ); + + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, + shaped_wb_excitation, Q_bwe_exc_ext, GainShape, subwin_wb_fx, NULL ); + + /* Gain frame adjustment factor */ + test(); + IF( GainShape[0] && hBWE_TD->prev_wb_GainShape ) + { + exp = norm_s( hBWE_TD->prev_wb_GainShape ); + tmp = div_s( shl( 1, sub( 14, exp ) ), hBWE_TD->prev_wb_GainShape ); + L_tmp = L_mult( GainShape[0], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + L_feedback = L_mult0( temp_wb_fac_fx, temp_wb_fac_fx ); + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + /* temp_swb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); */ + test(); + IF( GainShape[i] && GainShape[i - 1] ) + { + exp = norm_s( GainShape[i - 1] ); + tmp = div_s( shl( 1, sub( 14, exp ) ), GainShape[i - 1] ); + L_tmp = L_mult( GainShape[i], tmp ); /*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_wb_fac_fx, temp_wb_fac_fx ); + } + L_tmp = L_add( L_shr( L_feedback, 1 ), 1 << 21 ); /* Q30 */ + + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /* Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /* Q31 */ + feedback_fx = round_fx( L_tmp ); /* Q15 */ + } + ELSE + { + feedback_fx = 8738; + move16(); /* Q15 */ + } + + + temp_wb_fac_fx = hBWE_TD->prev_wb_GainShape; + move16(); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShape[i] = add( mult_r( sub( 32767, feedback_fx ), GainShape[i] ), mult_r( feedback_fx, temp_wb_fac_fx ) ); + move16(); + temp_wb_fac_fx = GainShape[i]; + move16(); + } + + hBWE_TD->prev_wb_GainShape = GainShape[sub( shr( NUM_SHB_SUBFR, 2 ), 1 )]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_in = pow_off_pk_corrected_fx( GainShape, NUM_SHB_SUBFR / 4, 1 ); + } + ELSE + { + p2m_in = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 4, 1 ); + } + + IF( EQ_32( st_fx->extl_brate, WB_TBE_0k35 ) ) + { + FOR( i = 0; i < 8; i++ ) + { + GainShape[i] = RECIP_ROOT_EIGHT_FX; + move16(); + } + } + ELSE + { + push_indice( st_fx->hBstr, IND_UV_FLAG, uv_flag, 1 ); + + /* Quantization of the subframe gain parameter */ + QuantizeSHBsubgains_ivas_fx( st_fx, GainShape, st_fx->extl ); + } + + /* Compute the power of gains away from the peak gain after quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_out = pow_off_pk_corrected_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + } + ELSE + { + p2m_out = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + } + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, shaped_wb_excitation, Q_bwe_exc_ext, GainShape, + &GainFrame, window_wb_fx, subwin_wb_fx, 0 ); + + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + + IF( GT_32( p2m_out, L_shl( p2m_in, 1 ) ) ) + { + L_tmp = root_a_over_b_fx( L_shl( p2m_in, 1 ), 29, p2m_out, 29, &exp_out ); + GainFrame = L_shl( Mpy_32_32( GainFrame, L_tmp ), exp_out ); /* Q18 */ + } + + pitBufAvg_fx = 0; + move16(); + + FOR( i = 0; i < NB_SUBFR; i++ ) + { + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[i], 82 ) ); /*Q6 */ + } + voicingBufAvg_fx = 0; + move16(); + FOR( i = 0; i < 3; i++ ) + { + voicingBufAvg_fx = add( voicingBufAvg_fx, mult_r( st_fx->voicing_fx[i], 10912 ) ); /*Q15 */ + } + /* GainFrame *= max(min((float)(pitBufAvg/voicingBufAvg), 1.0f), 0.7f); */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ + L_tmp = L_mult( pitBufAvg_fx, tmp ); /* (21-exp) */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o( L_tmp, add( exp, 10 ), &Overflow ); + tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shl( L_tmp, add( exp, 10 ) ); + tmp = round_fx( L_tmp ); /* Q15 */ +#endif + } + + tmp = s_max( s_min( tmp, 32767 ), 22938 ); /* Q15 */ + GainFrame = Mpy_32_16_1( GainFrame, tmp ); /* Q18 */ + + IF( LT_16( lsp_spacing_fx, 328 ) && lsp_spacing_fx ) + { + GainFrame = Mpy_32_16_1( GainFrame, 21299 ); /* Q18 */ + } + + /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ + L_tmp = L_mult( voice_factors[0], 8192 ); + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mac( L_tmp, voice_factors[i], 8192 ); + } + avg_voice_fac = round_fx( L_tmp ); + + test(); + test(); + IF( st_fx->igf != 0 && EQ_16( st_fx->coder_type, VOICED ) ) + { + /*GainFrame *= 0.5f;*/ + GainFrame = Mpy_32_16_1( GainFrame, 16384 ); + } + ELSE IF( st_fx->igf != 0 && GT_16( avg_voice_fac, 11469 ) ) /*Q15 -> 0.35f*/ + { + /*GainFrame *= 0.75f;*/ + GainFrame = Mpy_32_16_1( GainFrame, 24576 ); + } + + /* Quantization of the frame gain parameter */ + IF( st_fx->rf_mode ) + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame, st_fx->extl, st_fx->extl_brate, &st_fx->hRF->RF_bwe_gainFr_ind, 0 ); + } + ELSE + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame, st_fx->extl, st_fx->extl_brate, NULL, 0 ); + } + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation*/ + ScaleShapedSHB_fx( SHB_OVERLAP_LEN / 2, shaped_wb_excitation, hBWE_TD->syn_overlap_fx, GainShape, GainFrame, window_wb_fx, subwin_wb_fx, + &Q_bwe_exc_ext, &dummy, dummy, dummy ); + + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + return; +} + + +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx, + Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q ) +{ + set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + *prev_fb_energy_fx = 0; + move16(); + set16_fx( elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); + *prev_fb_energy_fx_Q = 0; + move16(); + + return; +} + + +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ + +void swb_tbe_enc_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ + const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +) +{ + Word16 i, j; + + Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; + + Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; + Word32 GainFrame_fx; + Word16 GainShape_fx[NUM_SHB_SUBFR]; + Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16 *shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER + 1]; + + Word16 ana_align_delay[2] = { -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ), -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) }; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip, Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 mean_vf; + Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + Word16 refl[M]; + Word16 tilt_para; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; + move16(); + + /* set up the speech buffers for TBE processing*/ + shb_new_speech_fx = shb_old_speech_fx + ( L_LOOK_16k + L_SUBFR16k ); + move16(); + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + } + + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M + 1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx( lpc_shb1, 0, M + 1 ); + Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF( GT_16( enerG, 256 /*32 Q3*/ ) ) + { + set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ + } + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + lpc_shb_fx[i] = mult_r( lpc_shb_fx[i], lpc_weights_fx[i] ); + } + } + + /* LPC to LSP conversion */ + /* LPC: Q12, LSP: Q15 */ + E_LPC_a_lsp_conversion( lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + + /* LSP to LSF conversion */ + /* LSP: Q15, LSF: Q15 */ + E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); + + /* Input signal filtering in case of tonal sounds in the high band + gain Frame smoothing and attenuation control */ + gainFrSmooth_En_fx( st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn ); + + Copy( lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + Copy( lsf_shb_fx, lsf_shb_orig_fx, LPC_SHB_ORDER ); + + test(); + IF( ( EQ_16( st_fx->rf_mode, 1 ) ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + { + lsp_weights_fx( lsf_shb_fx, weights_lsp, LPC_SHB_ORDER, &Q_out ); + + /* to compensate for the 1.1* weighting done inside the function lsp_weights */ + /*weights_lsp[3]*=0.909091f; weights_lsp[4]*=0.909091f; */ + weights_lsp[3] = mult_r( weights_lsp[3], 29789 /*0.909091f Q15*/ ); + weights_lsp[4] = mult_r( weights_lsp[4], 29789 /*0.909091f Q15*/ ); + + /* 8-bit VQ, 10 dimension */ + i = closest_centroid_fx( lsf_shb_fx, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER ); + Copy( swb_tbe_lsfvq_cbook_8b + i * LPC_SHB_ORDER, lsf_shb_fx, LPC_SHB_ORDER ); + + set16_fx( hBWE_TD->lsf_idx, 0, NUM_Q_LSF ); + hBWE_TD->lsf_idx[0] = i; + } + ELSE + { + /* LSF quantization (21 bits) */ + Quant_BWE_LSF_fx( st_fx, lsf_shb_fx, lsf_shb_fx ); + } + + /* space the lsfs to assert a minimum distance */ + space_lsfs_fx( lsf_shb_fx, LPC_SHB_ORDER ); + + /* voice factor adjustment and gainframe attenuation factor */ + tmp = sub( lsf_shb_fx[0], lsf_shb_orig_fx[0] ); + L_tmp = L_mult( tmp, tmp ); + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + /* Estimate the QD in lsfs between UQ and Q */ + tmp = sub( lsf_shb_fx[i], lsf_shb_orig_fx[i] ); + L_tmp = L_mac( L_tmp, tmp, tmp ); + } + sd_uq_q_fx = round_fx( L_tmp ); /* sd_uq_q_fx in Q15 */ + /* voice factor modification to limit any spurious jumps in the middle of voiced subframes*/ + /* mean(voice_factors_fx[i], 4); */ + + L_tmp = L_mult( voice_factors_fx[0], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); + mean_vf = mac_r( L_tmp, voice_factors_fx[3], 8192 ); + + Copy( voice_factors_fx, vf_modified_fx, NB_SUBFR16k ); + + test(); + IF( EQ_16( coder_type, VOICED ) || GT_16( mean_vf, 13107 /*0.4f Q15*/ ) ) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mult( voice_factors_fx[i], 26214 ); + vf_modified_fx[i] = mac_r( L_tmp, voice_factors_fx[i - 1], 6554 ); + move16(); + } + IF( NE_16( st_fx->L_frame, L_FRAME ) ) + { + L_tmp = L_mult( voice_factors_fx[4], 26214 ); + vf_modified_fx[4] = mac_r( L_tmp, voice_factors_fx[3], 6554 ); + move16(); + } + } + + /* convert quantized LSFs to LSPs for interpolation */ + E_LPC_lsf_lsp_conversion( lsf_shb_fx, lsp_shb_2_fx, LPC_SHB_ORDER ); + + test(); + IF( EQ_16( st_fx->last_extl, SWB_TBE ) || EQ_16( st_fx->last_extl, FB_TBE ) ) + { + /* SHB LSP values from prev. frame for interpolation */ + Copy( hBWE_TD->swb_lsp_prev_interp_fx, lsp_shb_1_fx, LPC_SHB_ORDER ); + } + ELSE + { + /* Use current frame's LSPs; in effect no interpolation */ + Copy( lsp_shb_2_fx, lsp_shb_1_fx, LPC_SHB_ORDER ); + } + + lsf_diff[0] = lsf_diff[sub( LPC_SHB_ORDER, 1 )] = 16384; /*Q15*/ + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + lsf_diff[i] = sub( lsf_shb_fx[i], lsf_shb_fx[sub( i, 1 )] ); + } + a2rc_fx( hBWE_TD->cur_sub_Aq_fx + 1, refl, M ); + + /* LSP interpolation for 13.2 kbps and 16.4 kbps */ + /* tilt_para = 6.6956f * (1.0f + refl[0]) * (1.0f + refl[0]) + - 3.8714f * (1.0f + refl[0]) + + 1.3041f; */ + tmp = add( 16384, shr( refl[0], 1 ) ); /*Q14*/ + tmp1 = mult( 27425 /*Q12*/, tmp ); /*Q11*/ + tmp1 = mult( tmp1, tmp ); + tmp2 = shr( mult( 31715, tmp ), 2 ); /* Q11 */ + tilt_para = add( sub( tmp1, tmp2 ), 1335 ); /*Q10*/ + + IF( NE_16( st_fx->last_extl, SWB_TBE ) ) + { + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + hBWE_TD->prev_lsf_diff_fx[i - 1] = mult( lsf_diff[i], 16384 ); /*Q15*/ + } + } + + IF( LE_32( st_fx->total_brate, ACELP_16k40 ) ) + { + test(); + test(); + test(); + test(); + test(); + IF( !( GT_16( hBWE_TD->prev_tilt_para_fx, 5120 ) && ( EQ_16( coder_type, TRANSITION ) || LT_16( tilt_para, 1024 ) ) ) && + !( ( ( LT_16( hBWE_TD->prev_tilt_para_fx, 3072 ) && GE_16( hBWE_TD->prev_coder_type, VOICED ) ) ) && GT_16( tilt_para, 5120 ) ) ) + { + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + IF( LT_16( lsf_diff[i], hBWE_TD->prev_lsf_diff_fx[i - 1] ) ) + { + tmp = mult( 26214, lsf_diff[i] ); + tmp = div_s( tmp, hBWE_TD->prev_lsf_diff_fx[i - 1] ); + tmp = s_max( tmp, 16384 ); + w[i] = s_min( tmp, 32767 ); + } + ELSE + { + tmp = mult( 26214, hBWE_TD->prev_lsf_diff_fx[i - 1] ); + tmp = div_s( tmp, lsf_diff[i] ); + tmp = s_max( tmp, 16384 ); + w[i] = s_min( tmp, 32767 ); + } + } + w[0] = w[1]; + w[sub( LPC_SHB_ORDER, 1 )] = w[sub( LPC_SHB_ORDER, 2 )]; + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tmp1 = mult( lsp_shb_1_fx[i], sub( 32767, w[i] ) ); + tmp2 = mult( lsp_shb_2_fx[i], w[i] ); + lsp_temp_fx[i] = add( tmp1, tmp2 ); + } + } + ELSE + { + Copy( lsp_shb_2_fx, lsp_temp_fx, LPC_SHB_ORDER ); + } + } + + Copy( lsf_diff + 1, hBWE_TD->prev_lsf_diff_fx, LPC_SHB_ORDER - 2 ); + hBWE_TD->prev_tilt_para_fx = tilt_para; + + shb_ener_sf_Q31 = 0; + move16(); + test(); + IF( EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_32k ) ) + { + /* ---------- SHB LSP interpolation ---------- */ + ptr_lsp_interp_coef_fx = interpol_frac_shb; /* Q15 */ + FOR( j = 0; j < 4; j++ ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /*lsp_temp_fx[i] = lsp_shb_1_fx[i]*(*ptr_lsp_interp_coef_fx) */ + /* + lsp_shb_2_fx[i]*(*(ptr_lsp_interp_coef_fx+1)); */ + L_tmp = L_mult( lsp_shb_1_fx[i], ( *ptr_lsp_interp_coef_fx ) ); + lsp_temp_fx[i] = mac_r( L_tmp, lsp_shb_2_fx[i], ( *( ptr_lsp_interp_coef_fx + 1 ) ) ); + move16(); + } + ptr_lsp_interp_coef_fx += 2; + + tmp = i_mult2( j, ( LPC_SHB_ORDER + 1 ) ); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER ); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx + tmp, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_sf_fx[tmp] ), 2 ) ); + } + + /* -------- Calculate the SHB Energy -------- */ + /*shb_ener_sf[0] = 0.003125f * sum2_f( shb_frame + L_SHB_LAHEAD, 320 );*/ + FOR( i = L_SHB_LAHEAD; i < L_FRAME16k + L_SHB_LAHEAD; i++ ) + { + /* shbEner = shbEner + in[i] * in[i] */ +#ifdef BASOP_NOGLOB + shb_ener_sf_Q31 = L_mac0_sat( shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i] ); +#else + shb_ener_sf_Q31 = L_mac0( shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i] ); +#endif + /* o: shb_ener_sf_Q31 in (2*Q_shb) */ + } + shb_ener_sf_Q31 = Mult_32_16( shb_ener_sf_Q31, 102 /*0.003125f Q15*/ ); + shb_ener_sf_Q31 = L_add( 1l /*1 Q0*/, shb_ener_sf_Q31 ); + Quant_shb_ener_sf_fx( st_fx, &shb_ener_sf_Q31, ( 2 * Q_shb ) ); + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx( shb_res_fx, 0, L_FRAME16k ); + Residu3_10_fx( lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 2 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 3 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0 ); + /* i: shb_frame_fx in Q_shb */ + /* o: shb_res_fx in Q_shb */ + + set32_fx( shb_res_gshape_fx_32, 0, NB_SUBFR16k ); + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + shb_res_gshape_fx_32[i] = sum2_fx( shb_res_fx + i * 64, 64 ); + } + /* o: shb_res_gshape_fx_32 in (2*Q_shb+1) */ + + maximum_32_fx( shb_res_gshape_fx_32, NB_SUBFR16k, &L_tmp ); + + /* root_a_over_b_fx(shb_res_gshape_fx_32[i], (2*Q_shb+1), L_tmp, (2*Q_shb+1), &exp);*/ + /* First, find 1/L_tmp, L_tmp in QA = (2*Q_shb+1) */ + + /* case when den = 0 */ + recip = 0; /*instead of 32767 to be compatible with previous root_a_over_b_fx() output */ + Q_recip = 0; + + IF( L_tmp ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + recip = div_s( 16384, tmp ); + Q_recip = 31 - ( exp - 14 ); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ + } + + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + L_tmp1 = Mult_32_16( shb_res_gshape_fx_32[i], recip ); /*Q = Q_recip+1-16*/ + L_tmp = root_a_fx( L_tmp1, Q_recip + 1 - 16, &exp ); + shb_res_gshape_fx[i] = round_fx( L_shl( L_tmp, exp - 1 ) ); /* Q14 */ + } + + Quant_shb_res_gshape_fx( st_fx, shb_res_gshape_fx ); + } + + /* for 13.2 and 16.4kbps */ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_fx, LPC_SHB_ORDER ); + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); /* Q12 */ + + /* Save the SWB LSP values from current frame for interpolation */ + Copy( lsp_shb_2_fx, hBWE_TD->swb_lsp_prev_interp_fx, LPC_SHB_ORDER ); /* lsp_shb_2_fx in Q15 */ + + /* -------- start of memory rescaling -------- */ + /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ + Lmax = L_deposit_l( 0 ); + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = norm_l( Lmax ); + if ( Lmax == 0 ) + { + Q_bwe_exc = 31; + } + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + /* Account for any outliers in the memories from previous frame for rescaling to avoid saturation */ + find_max_mem_enc( st_fx, &n_mem, &n_mem2 ); + + tmp2 = add( st_fx->prev_Q_bwe_exc, n_mem ); + if ( GT_16( Q_bwe_exc, tmp2 ) ) + { + Q_bwe_exc = tmp2; + } + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ); + IF( sc != 0 ) + { + rescale_genSHB_mem_enc( st_fx, sc ); + } + + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ + Copy( hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { +#ifdef BASOP_NOGLOB + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx_sat( L_shl_sat( bwe_exc_extended[cnt], sc ) ); +#else + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); +#endif + } + Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ + Copy( hBWE_TD->state_syn_shbexc_fx, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + + /* save the previous Q factor of the buffer */ + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + Q_bwe_exc = sub( Q_bwe_exc, 16 ); /* Q_bwe_exc reflecting the single precision dynamic norm-ed buffers from here */ + + /* -------- end of rescaling memories -------- */ + Q_bwe_exc_fb = hBWE_TD->prev_Q_bwe_exc_fb; + move16(); + /* Determine formant PF strength */ + formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &hBWE_TD->tilt_mem_fx ); + /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ + vf_ind_fx = 20; + move16(); + + GenShapedSHBExcitation_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, + hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx, + coder_type, bwe_exc_extended_16, hBWE_TD->bwe_seed, vf_modified_fx, st_fx->extl, + &( hBWE_TD->tbe_demph_fx ), &( hBWE_TD->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, + shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, hBWE_TD->fb_state_lpc_syn_fx, + &( hBWE_TD->fb_tbe_demph_fx ), &Q_bwe_exc, &Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate, 0 ); + + *Q_white_exc = Q_bwe_exc_fb; + IF( EQ_16( st_fx->extl, FB_TBE ) ) + { + hBWE_TD->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + } + ELSE + { + /*Indirectly a memory reset of FB memories for next frame such that rescaling of memories would lead to 0 due to such high prev. Q value. + 51 because of 31 + 20(shift of Q_bwe_exc_fb before de-emphasis)*/ + hBWE_TD->prev_Q_bwe_exc_fb = 51; + move16(); + } + + test(); + IF( EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_32k ) ) + { + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->idx_mixFac = vf_ind_fx; + move16(); + } + ELSE + { + push_indice_fx( st_fx->hBstr, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF ); + } + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + hBWE_TD->mem_stp_swb_fx[i] = shl( hBWE_TD->mem_stp_swb_fx[i], sub( Q_bwe_exc, st_fx->prev_Q_bwe_syn ) ); + } + + FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + { + PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD + i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], hBWE_TD->mem_stp_swb_fx, + hBWE_TD->ptr_mem_stp_swb_fx, &( hBWE_TD->gain_prec_swb_fx ), hBWE_TD->mem_zero_swb_fx, formant_fac_fx ); + /* i: shaped_shb_excitation_fx in Q_bwe_exc */ + /* i: lpc_shb_fx in Q12 */ + } + Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); + + + tmp = sub( shl( Q_bwe_exc, 1 ), 31 ); + prev_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + curr_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + prev_pow_fx = L_mac0_o( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i], &Overflow ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0_o( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], &Overflow ); /* 2*Q_bwe_exc */ +#else + prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ +#endif + } + + if ( GT_16( voice_factors_fx[0], 24576 /*0.75f Q15*/ ) ) + { + /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ + curr_pow_fx = L_shr( curr_pow_fx, 2 ); /* scale by 0.25 */ + } + + Lscale = root_a_over_b_fx( curr_pow_fx, + shl( Q_bwe_exc, 1 ), + prev_pow_fx, + shl( Q_bwe_exc, 1 ), + &exp ); + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + IF( exp < 0 ) + { + Lscale = L_shl( Lscale, exp ); + exp = 0; + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + tmp = i_mult_o( sub( i, 19 ), 3277 /*0.1f Q15*/, &Overflow ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl_o( 1, sub( 31, exp ), &Overflow ), tmp ); /* Q31-exp */ +#else + tmp = i_mult( sub( i, 19 ), 3277 /*0.1f Q15*/ ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl( 1, sub( 31, exp ) ), tmp ); /* Q31-exp */ +#endif + tmp = sub( 32767 /*1.0f Q15*/, tmp ); + Lscale = L_add( Mult_32_16( Lscale, tmp ), L_tmp1 ); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ +#ifdef BASOP_NOGLOB + shaped_shb_excitation_fx[i] = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /* Q_bwe_exc */ +#else + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ +#endif + } + + /* Update SHB excitation */ + Copy( shaped_shb_excitation_fx + L_FRAME16k, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD ); /* Q_bwe_exc */ + + /* Estimate the gain-shape parameter */ + n_subfr_saturation = 0; + move16(); + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, + Q_bwe_exc, GainShape_fx, subwin_shb_fx, &n_subfr_saturation ); + + /* Gain shape BWS/high band low energy fix */ + IF( LT_16( hBWE_TD->cldfbHBLT, 8192 /*1.0f Q13*/ ) ) /* cldfbHBLT in Q13 */ + { + /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ + /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ + GainShape_fx[i] = mac_r( 676457349l /*0.315 Q31*/, 3277 /*0.1 Q15*/, GainShape_fx[i] ); + } + } + + /* Gain frame adjustment factor */ + /* log( (GainShape[0]) / (st->prev_wb_GainShape) )*/ + test(); + IF( GainShape_fx[0] && hBWE_TD->prev_swb_GainShape_fx ) + { + exp = norm_s( hBWE_TD->prev_swb_GainShape_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), hBWE_TD->prev_swb_GainShape_fx ); + L_tmp = L_mult( GainShape_fx[0], tmp ); /*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); /*move16(); */ + exp1 = sub( exp, exp1 ); /*move16(); */ + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + L_feedback = L_mult0( temp_swb_fac, temp_swb_fac ); + + + FOR( i = 1; i < NUM_SHB_SUBGAINS; i++ ) + { + test(); + IF( GainShape_fx[i] && GainShape_fx[i - 1] ) + { + exp = norm_s( GainShape_fx[i - 1] ); + tmp = div_s( shl( 1, sub( 14, exp ) ), GainShape_fx[i - 1] ); + L_tmp = L_mult( GainShape_fx[i], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_swb_fac, temp_swb_fac ); + } + + /* feedback = 0.4f / (1 + 0.5f * feedback) */ + L_tmp = L_add( L_shr( L_feedback, 1 ), L_shl( 1, 21 ) ); /* Q21 */ + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /*Q31 */ + feedback = round_fx( L_tmp ); /*Q15 */ + } + ELSE + { + feedback = 8738; + move16(); /*Q15 */ + } + + /* voicing in Q15 */ + L_tmp = L_mult( voicing[0], 8192 ); + L_tmp = L_mac( L_tmp, voicing[1], 8192 ); + L_tmp = L_mac( L_tmp, voicing[2], 8192 ); + tmp = sum1 = round_fx( L_tmp ); /* sum1 used again below - Q13 */ + tmp = add( tmp, 1 ); /* To ensure change is BE */ + + /* voice_factors_fx in Q15 */ + L_tmp = L_mult( voice_factors_fx[0], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[3], 8192 ); + tmp1 = sum2 = round_fx( L_tmp ); /* sum2 used again below - Q13 */ + + + test(); + test(); + IF( EQ_16( frGainAttenuate, 1 ) || ( GT_16( tmp, 19661 ) && GT_16( tmp1, 6554 ) ) ) + + { + temp_swb_fac = hBWE_TD->prev_swb_GainShape_fx; + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ + GainShape_fx[i] = round_fx( L_mac( L_mult( sub( 32767, feedback ), GainShape_fx[i] ), feedback, temp_swb_fac ) ); + temp_swb_fac = GainShape_fx[i]; + move16(); + } + } + hBWE_TD->prev_swb_GainShape_fx = GainShape_fx[3]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + + /* Quantization of the gain shape parameter */ + + QuantizeSHBsubgains_fx( st_fx, GainShape_fx, st_fx->extl ); + /* o: GainShape_fx in Q15 */ + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, + GainShape_fx, &GainFrame_fx, window_shb_fx, subwin_shb_fx, n_subfr_saturation ); + + IF( EQ_16( st_fx->tec_tfa, 1 ) ) + { + tfaCalcEnv_fx( shb_frame_fx, st_fx->tfa_enr ); + } + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + IF( GT_32( p2m_out_fx, L_shl( p2m_in_fx, 1 ) ) ) + { + L_tmp = root_a_over_b_fx( p2m_in_fx, 28, p2m_out_fx, 29, &exp_out ); + GainFrame_fx = L_shl( Mult_32_32( GainFrame_fx, L_tmp ), exp_out ); /* Q18 */ + } + test(); + IF( EQ_16( frGainSmoothEn, 1 ) && LT_32( hBWE_TD->prev_gainFr_SHB_fx, GainFrame_fx ) ) + { + GainFrame_fx = L_add( L_shr( hBWE_TD->prev_gainFr_SHB_fx, 1 ), L_shr( GainFrame_fx, 1 ) ); /* Q18 */ + } + + test(); + IF( EQ_16( frGainAttenuate, 1 ) && LE_16( MA_lsp_shb_spacing, 79 /*0.0024f Q15*/ ) ) + { + exp1 = norm_l( GainFrame_fx ); + frac = Log2_norm_lc( L_shl( GainFrame_fx, exp1 ) ); + exp = sub( 30, add( exp1, 21 ) ); + L_tmp = Mpy_32_16( exp, frac, 26214 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + GainFrame_fx = Pow2( 30, frac ); + exp = sub( exp, 30 ); + GainFrame_fx = L_shl( GainFrame_fx, exp + 18 ); /* Q18 */ + } + ELSE IF( EQ_16( hBWE_TD->prev_frGainAtten, 1 ) && GT_32( Mult_32_16( GainFrame_fx, 10923 ), hBWE_TD->prev_gainFr_SHB_fx ) ) + { + /*GainFrame *= (0.8f + 0.5f*feedback); */ + tmp = add( 26214, mult_r( feedback, 16384 ) ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 */ + } + hBWE_TD->prev_frGainAtten = frGainAttenuate; + move16(); + hBWE_TD->prev_gainFr_SHB_fx = GainFrame_fx; + move16(); /* Q18 */ + + + /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ + tmp = mult_r( 25600 /*400 Q6*/, sd_uq_q_fx ); /* Q6 * Q15 => Q6 */ + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + tmp1 = mult_r( 6554 /*0.2f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + ELSE + { + tmp1 = mult_r( 3277 /*0.1f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + /* sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); */ + L_tmp = L_min( L_tmp, 8192l /*1.0f Q13*/ ); + L_tmp = L_max( L_tmp, 4096l /*0.5f Q13*/ ); /* Q13 */ + /* keep the L_tmp; dont overwrite */ + + /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ + /* pitch_buf: Q6 */ + pitBufAvg_fx = mult_r( pitch_buf[0], 1311 ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[1], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[2], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[3], 1311 ) ); /* Q10 */ + + /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ + tmp2 = 5462 /*0.1667f Q15*/; + if ( GT_16( sum2, 4915 /*0.6f Q13*/ ) ) + { + tmp2 = 10912 /*0.333f Q15*/; /* Q15 */ + } + voicingBufAvg_fx = shl( mult( tmp2, sum1 ), 2 ); /* Q15 */ + + + /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ + /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + + /* 1/voicingBufAvg_fx */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ + + /* sd_uq_q*pitBufAvg */ + L_tmp = Mult_32_16( L_tmp, pitBufAvg_fx ); /* Q13 * Q10 + 1 -16 => Q8 */ + L_tmp = Mult_32_16( L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ +#ifdef BASOP_NOGLOB + tmp = round_fx_o( L_shl_o( L_tmp, 31 - ( 7 - exp ), &Overflow ), &Overflow ); /* Q15 */ +#else + tmp = round_fx( L_shl( L_tmp, 31 - ( 7 - exp ) ) ); /* Q15 */ +#endif + } + + tmp = s_min( tmp, 32767 /*1.0f Q15*/ ); + tmp = s_max( tmp, 19661 /*0.6f Q15*/ ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 + Q15 + 1 - 16 : Q18 */ + + test(); + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) || EQ_16( st_fx->rf_mode, 1 ) ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame_fx = Mult_32_16( GainFrame_fx, 27853 /*0.85f Q15*/ ); /* Q18 */ + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, &hRF->RF_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation */ + IF( EQ_32( st_fx->extl, FB_TBE ) ) + { + tmp = norm_l( GainFrame_fx ); + if ( GainFrame_fx == 0 ) + { + tmp = 31; + } + L_tmp = L_shl( GainFrame_fx, tmp ); /* 18 + tmp */ + + tmp1 = 0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp1 = Mult_32_16( L_tmp, GainShape_fx[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ + /*White_exc16k_fx[i] = round_fx( L_shl(Mult_32_16( L_tmp1, White_exc16k_fx[i]),(23 - tmp -*Q_white_exc)) );*/ + /*18 + tmp +*Q_white_exc -15 + 23 - tmp -*Q_white_exc -16 = 10*/ + White_exc16k_fx[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k_fx[i] ) ); /* 18 + tmp +*Q_white_exc -15 -16 */ + /*Lmax = L_max(Lmax,White_exc16k_fx[i]);*/ + tmp1 = s_max( tmp1, abs_s( White_exc16k_fx[i] ) ); + /*White_exc16k_fx[i] =32767;*/ + /*White_exc16k_fx[i] = shr(White_exc16k_fx[i],5);*/ + } + *Q_white_exc = sub( add( *Q_white_exc, tmp ), 13 ); /* *Q_white_exc + 18 + tmp -15 -16 */ + tmp = norm_s( tmp1 ); + if ( tmp1 == 0 ) + { + tmp = 15; + } + + FOR( i = 0; i < L_FRAME16k; i++ ) + { + White_exc16k_fx[i] = shl( White_exc16k_fx[i], sub( tmp, 1 ) ); + move16(); + } + *Q_white_exc = sub( add( *Q_white_exc, tmp ), 1 ); + move16(); + } + + /* *Q_white_exc = Q_bwe_exc_mod; move16(); output Qwhiteexc_FB from the GenShapedSHB function*/ + st_fx->prev_Q_bwe_syn = Q_bwe_exc; + move16(); + + return; +} + + +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_ivas_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ + +void swb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: IC-BWE state structure */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb */ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2 * Q_new */ + const Word16 voice_factors_fx[], /* i : voicing factors Q15 */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc */ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6 */ +) +{ + Word16 i, j, k, delay; + + Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; + + Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; + Word32 GainFrame_fx; /* Q18 */ + Word16 GainShape_fx[NUM_SHB_SUBFR]; /* Q15 */ + Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16 *shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER + 1]; + + Word16 ana_align_delay; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip, Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + // int16_t stab_check = 1; + Word16 MSFlag; + Word16 *nlExc16k_fx, *mixExc16k_fx; + + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 acorr_v2a_fx; /* Q15 */ + + Word16 acorr_EnvSHBres[ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN], *p_acorr, shb_env_tilt_fx; + Word16 buf_EnvSHBres_fx[2 * L_FRAME4k], *p_buf, EnvSHBres_fx[L_FRAME16k], EnvSHBres_4k_fx[L_FRAME4k], EnvSHBres_4k_norm_fx[L_FRAME4k], env_mean_normf_fx[L_FRAME4k]; + Word16 GainShape_Interp_fx[NUM_SHB_SUBGAINS], GainShape_tilt_fx; /* Q15 */ + Word16 seg_mean[4], den_seg_mean[4], *p_env, step; + Word16 temp, scale_fx, scale_e, pow_e, tmp_e, tmp1_e; + Word16 seg_len, seg_len_2; + Word16 den_seg_len, den_seg_len_2, fact_atten_fx; /* Q15 */ + Word32 sum_gain_fx, normFact_fx; + Word32 pow0_fx, alpha_fx; + Word16 Env_error_part_fx[NUM_SHB_SUBGAINS], Env_error_fx; /* Q0 */ + + Word16 mean_vf; + Word16 lsf_diff_fx[LPC_SHB_ORDER], w_fx[LPC_SHB_ORDER]; + Word16 refl_fx[M]; + Word16 tilt_para_fx; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + Env_error_fx = 0; + move16(); + pitBufAvg_fx = 0; + move16(); + voicingBufAvg_fx = 0; + move16(); + set16_fx( Env_error_part_fx, 0, NUM_SHB_SUBGAINS ); + shb_env_tilt_fx = 0; + move16(); + sum1 = 0; + move16(); + sum2 = 0; + move16(); + + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + move16(); + + IF( st_fx->element_mode >= IVAS_CPE_DFT && hStereoICBWE != NULL ) + { + nlExc16k_fx = hStereoICBWE->nlExc16k_fx; + mixExc16k_fx = hStereoICBWE->mixExc16k_fx; + MSFlag = hStereoICBWE->MSFlag; + move16(); + } + ELSE + { + nlExc16k_fx = NULL; + mixExc16k_fx = NULL; + MSFlag = 0; + move16(); + } + + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); + + test(); + test(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) && ( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) ) + { + ana_align_delay = -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) + 20; /* 20 corresponds to the 1.25 ms CLDFB delay */ + move16(); + } + ELSE + { + ana_align_delay = -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ); + move16(); + } + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay; + + set16_fx( shb_old_speech_fx, 0, L_LOOK_16k + L_SUBFR16k + L_FRAME16k ); + + /* set up the speech buffers for TBE processing*/ + delay = L_LOOK_16k + L_SUBFR16k; + move16(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + shb_new_speech_fx = shb_old_speech_fx + delay - L_MEM_RECALC_TBE_16K; + } + ELSE + { + shb_new_speech_fx = shb_old_speech_fx + delay; + } + + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, delay ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, delay ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + } + + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M + 1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx( lpc_shb1, 0, M + 1 ); + Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF( GT_16( enerG, 256 /*32 Q3*/ ) ) + { + set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ + } + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) { FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) { lpc_shb_fx[i] = mult_r( lpc_shb_fx[i], lpc_weights_fx[i] ); + move16(); } } + /* stab_check = a2lsp( lsf_shb, lpc_shb, LPC_SHB_ORDER ); - stab_check missing */ /* LPC to LSP conversion */ /* LPC: Q12, LSP: Q15 */ E_LPC_a_lsp_conversion( lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); @@ -1324,34 +2943,63 @@ void swb_tbe_enc_fx( /* LSP: Q15, LSF: Q15 */ E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); - /* Input signal filtering in case of tonal sounds in the high band - gain Frame smoothing and attenuation control */ - gainFrSmooth_En_fx( st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn ); + test(); + test(); + IF( ( NE_16( st_fx->last_extl, SWB_TBE ) && NE_16( st_fx->last_extl, FB_TBE ) ) || st_fx->ini_frame == 0 ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + // hBWE_TD->prev_lsp_shb_fx[i] = i / 20.0f; + hBWE_TD->prev_lsp_shb_fx[i] = lsp_shb_prev_tbl_fx[i]; + move16(); + } + } + + // if ( stab_check == 0 ) + //{ + // mvr2r( hBWE_TD->prev_lsp_shb, lsf_shb, LPC_SHB_ORDER ); + // } Copy( lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); Copy( lsf_shb_fx, lsf_shb_orig_fx, LPC_SHB_ORDER ); + /* Input signal filtering in case of tonal sounds in the high band + gain Frame smoothing and attenuation control */ + gainFrSmooth_En_fx( st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn ); + test(); - IF( ( EQ_16( st_fx->rf_mode, 1 ) ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) { lsp_weights_fx( lsf_shb_fx, weights_lsp, LPC_SHB_ORDER, &Q_out ); /* to compensate for the 1.1* weighting done inside the function lsp_weights */ /*weights_lsp[3]*=0.909091f; weights_lsp[4]*=0.909091f; */ weights_lsp[3] = mult_r( weights_lsp[3], 29789 /*0.909091f Q15*/ ); + move16(); weights_lsp[4] = mult_r( weights_lsp[4], 29789 /*0.909091f Q15*/ ); + move16(); /* 8-bit VQ, 10 dimension */ i = closest_centroid_fx( lsf_shb_fx, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER ); Copy( swb_tbe_lsfvq_cbook_8b + i * LPC_SHB_ORDER, lsf_shb_fx, LPC_SHB_ORDER ); set16_fx( hBWE_TD->lsf_idx, 0, NUM_Q_LSF ); - hBWE_TD->lsf_idx[0] = i; + + IF( EQ_16( st_fx->codec_mode, MODE1 ) ) + { + push_indice( hBstr, IND_SHB_LSF, i, 8 ); + } + ELSE + { + hBWE_TD->lsf_idx[0] = i; + move16(); + } } ELSE { /* LSF quantization (21 bits) */ - Quant_BWE_LSF_fx( st_fx, lsf_shb_fx, lsf_shb_fx ); + Quant_BWE_LSF_ivas_fx( hBstr, st_fx->hBWE_TD, st_fx->codec_mode, lsf_shb_fx, lsf_shb_fx, st_fx->extl_brate ); } /* space the lsfs to assert a minimum distance */ @@ -1378,7 +3026,7 @@ void swb_tbe_enc_fx( Copy( voice_factors_fx, vf_modified_fx, NB_SUBFR16k ); test(); - IF( EQ_16( coder_type, VOICED ) || GT_16( mean_vf, 13107 /*0.4f Q15*/ ) ) + IF( EQ_16( st_fx->coder_type, VOICED ) || GT_16( mean_vf, 13107 /*0.4f Q15*/ ) ) { FOR( i = 1; i < NB_SUBFR; i++ ) { @@ -1409,66 +3057,74 @@ void swb_tbe_enc_fx( Copy( lsp_shb_2_fx, lsp_shb_1_fx, LPC_SHB_ORDER ); } - lsf_diff[0] = lsf_diff[sub( LPC_SHB_ORDER, 1 )] = 16384; /*Q15*/ + lsf_diff_fx[0] = lsf_diff_fx[sub( LPC_SHB_ORDER, 1 )] = 16384; /*Q15*/ + move16(); FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) { - lsf_diff[i] = sub( lsf_shb_fx[i], lsf_shb_fx[sub( i, 1 )] ); + lsf_diff_fx[i] = sub( lsf_shb_fx[i], lsf_shb_fx[sub( i, 1 )] ); + move16(); } - a2rc_fx( hBWE_TD->cur_sub_Aq_fx + 1, refl, M ); + a2rc_fx( hBWE_TD->cur_sub_Aq_fx + 1, refl_fx, M ); /* LSP interpolation for 13.2 kbps and 16.4 kbps */ - /* tilt_para = 6.6956f * (1.0f + refl[0]) * (1.0f + refl[0]) - - 3.8714f * (1.0f + refl[0]) + /* tilt_para_fx = 6.6956f * (1.0f + refl_fx[0]) * (1.0f + refl_fx[0]) + - 3.8714f * (1.0f + refl_fx[0]) + 1.3041f; */ - tmp = add( 16384, shr( refl[0], 1 ) ); /*Q14*/ - tmp1 = mult( 27425 /*Q12*/, tmp ); /*Q11*/ + tmp = add( 16384, shr( refl_fx[0], 1 ) ); /*Q14*/ + tmp1 = mult( 27425 /*Q12*/, tmp ); /*Q11*/ tmp1 = mult( tmp1, tmp ); - tmp2 = shr( mult( 31715, tmp ), 2 ); /* Q11 */ - tilt_para = add( sub( tmp1, tmp2 ), 1335 ); /*Q10*/ + tmp2 = shr( mult( 31715, tmp ), 2 ); /* Q11 */ + tilt_para_fx = add( sub( tmp1, tmp2 ), 1335 ); /*Q10*/ IF( NE_16( st_fx->last_extl, SWB_TBE ) ) { FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) { - hBWE_TD->prev_lsf_diff_fx[i - 1] = mult( lsf_diff[i], 16384 ); /*Q15*/ + hBWE_TD->prev_lsf_diff_fx[i - 1] = mult( lsf_diff_fx[i], 16384 ); /*Q15*/ + move16(); } } - IF( LE_32( st_fx->total_brate, ACELP_16k40 ) ) + IF( LE_32( st_fx->extl_brate, FB_TBE_1k8 ) ) { test(); test(); test(); test(); test(); - IF( !( GT_16( hBWE_TD->prev_tilt_para_fx, 5120 ) && ( EQ_16( coder_type, TRANSITION ) || LT_16( tilt_para, 1024 ) ) ) && - !( ( ( LT_16( hBWE_TD->prev_tilt_para_fx, 3072 ) && GE_16( hBWE_TD->prev_coder_type, VOICED ) ) ) && GT_16( tilt_para, 5120 ) ) ) + IF( !( GT_16( hBWE_TD->prev_tilt_para_fx, 5120 /* 5.0f in Q10 */ ) && ( EQ_16( st_fx->coder_type, TRANSITION ) || LT_16( tilt_para_fx, 1024 /* 1.0f in Q10 */ ) ) ) && + !( ( ( LT_16( hBWE_TD->prev_tilt_para_fx, 3072 /* 3.0f in Q10 */ ) && GE_16( hBWE_TD->prev_coder_type, VOICED ) ) ) && GT_16( tilt_para_fx, 5120 /* 5.0f in Q10 */ ) ) ) { FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) { - IF( LT_16( lsf_diff[i], hBWE_TD->prev_lsf_diff_fx[i - 1] ) ) + IF( LT_16( lsf_diff_fx[i], hBWE_TD->prev_lsf_diff_fx[i - 1] ) ) { - tmp = mult( 26214, lsf_diff[i] ); + tmp = mult( 26214, lsf_diff_fx[i] ); tmp = div_s( tmp, hBWE_TD->prev_lsf_diff_fx[i - 1] ); tmp = s_max( tmp, 16384 ); - w[i] = s_min( tmp, 32767 ); + w_fx[i] = s_min( tmp, 32767 ); + move16(); } ELSE { tmp = mult( 26214, hBWE_TD->prev_lsf_diff_fx[i - 1] ); - tmp = div_s( tmp, lsf_diff[i] ); + tmp = div_s( tmp, lsf_diff_fx[i] ); tmp = s_max( tmp, 16384 ); - w[i] = s_min( tmp, 32767 ); + w_fx[i] = s_min( tmp, 32767 ); + move16(); } } - w[0] = w[1]; - w[sub( LPC_SHB_ORDER, 1 )] = w[sub( LPC_SHB_ORDER, 2 )]; + w_fx[0] = w_fx[1]; + move16(); + w_fx[sub( LPC_SHB_ORDER, 1 )] = w_fx[sub( LPC_SHB_ORDER, 2 )]; + move16(); FOR( i = 0; i < LPC_SHB_ORDER; i++ ) { - tmp1 = mult( lsp_shb_1_fx[i], sub( 32767, w[i] ) ); - tmp2 = mult( lsp_shb_2_fx[i], w[i] ); + tmp1 = mult( lsp_shb_1_fx[i], sub( 32767, w_fx[i] ) ); + tmp2 = mult( lsp_shb_2_fx[i], w_fx[i] ); lsp_temp_fx[i] = add( tmp1, tmp2 ); + move16(); } } ELSE @@ -1477,13 +3133,14 @@ void swb_tbe_enc_fx( } } - Copy( lsf_diff + 1, hBWE_TD->prev_lsf_diff_fx, LPC_SHB_ORDER - 2 ); - hBWE_TD->prev_tilt_para_fx = tilt_para; + Copy( lsf_diff_fx + 1, hBWE_TD->prev_lsf_diff_fx, LPC_SHB_ORDER - 2 ); + hBWE_TD->prev_tilt_para_fx = tilt_para_fx; + move16(); shb_ener_sf_Q31 = 0; move16(); test(); - IF( EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_32k ) ) + IF( GE_32( st_fx->extl_brate, SWB_TBE_2k8 ) ) { /* ---------- SHB LSP interpolation ---------- */ ptr_lsp_interp_coef_fx = interpol_frac_shb; /* Q15 */ @@ -1520,7 +3177,7 @@ void swb_tbe_enc_fx( } shb_ener_sf_Q31 = Mult_32_16( shb_ener_sf_Q31, 102 /*0.003125f Q15*/ ); shb_ener_sf_Q31 = L_add( 1l /*1 Q0*/, shb_ener_sf_Q31 ); - Quant_shb_ener_sf_fx( st_fx, &shb_ener_sf_Q31, ( 2 * Q_shb ) ); + Quant_shb_ener_sf_ivas_fx( st_fx, &shb_ener_sf_Q31, shl( Q_shb, 1 ) ); /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ set16_fx( shb_res_fx, 0, L_FRAME16k ); @@ -1534,7 +3191,8 @@ void swb_tbe_enc_fx( set32_fx( shb_res_gshape_fx_32, 0, NB_SUBFR16k ); FOR( i = 0; i < NB_SUBFR16k; i++ ) { - shb_res_gshape_fx_32[i] = sum2_fx( shb_res_fx + i * 64, 64 ); + shb_res_gshape_fx_32[i] = sum2_fx( shb_res_fx + i_mult( i, 64 ), 64 ); + move32(); } /* o: shb_res_gshape_fx_32 in (2*Q_shb+1) */ @@ -1545,32 +3203,272 @@ void swb_tbe_enc_fx( /* case when den = 0 */ recip = 0; /*instead of 32767 to be compatible with previous root_a_over_b_fx() output */ + move16(); Q_recip = 0; + move16(); IF( L_tmp ) { exp = norm_l( L_tmp ); tmp = extract_h( L_shl( L_tmp, exp ) ); recip = div_s( 16384, tmp ); - Q_recip = 31 - ( exp - 14 ); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ + Q_recip = sub( 31, sub( exp, 14 ) ); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ } FOR( i = 0; i < NB_SUBFR16k; i++ ) { L_tmp1 = Mult_32_16( shb_res_gshape_fx_32[i], recip ); /*Q = Q_recip+1-16*/ - L_tmp = root_a_fx( L_tmp1, Q_recip + 1 - 16, &exp ); - shb_res_gshape_fx[i] = round_fx( L_shl( L_tmp, exp - 1 ) ); /* Q14 */ + L_tmp = root_a_fx( L_tmp1, sub( Q_recip, 15 ), &exp ); + shb_res_gshape_fx[i] = round_fx( L_shl( L_tmp, sub( exp, 1 ) ) ); /* Q14 */ + move16(); } - Quant_shb_res_gshape_fx( st_fx, shb_res_gshape_fx ); + Quant_shb_res_gshape_ivas_fx( st_fx, shb_res_gshape_fx ); + } + ELSE IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + FOR( j = 0; j < 4; j++ ) + { + tmp = i_mult2( j, ( LPC_SHB_ORDER + 1 ) ); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER ); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx + tmp, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_sf_fx[tmp] ), 2 ) ); + } + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx( shb_res_fx, 0, L_FRAME16k ); + Residu3_10_fx( lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 2 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 3 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0 ); } + Copy( lsp_shb_2_fx, hBWE_TD->swb_lsp_prev_interp_fx, LPC_SHB_ORDER ); /* lsp_shb_2_fx in Q15 */ /* for 13.2 and 16.4kbps */ E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_fx, LPC_SHB_ORDER ); Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); /* Q12 */ + /* Determine formant PF strength */ + formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &hBWE_TD->tilt_mem_fx ); + /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ + + /* calculate SHB auto-correlation function and convert to SHB voicing factor */ + // acorr_v2a = 0.0f; + L_tmp = 0; + move32(); + acorr_v2a_fx = 0; + move16(); + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* calculate the TD envelope of the SHB residual signal */ + find_td_envelope_fx( shb_res_fx, L_FRAME16k, 20, hBWE_TD->mem_shb_res_fx, EnvSHBres_fx ); /* Q_shb */ + + /* downsample the TD envelope by 4 */ + FOR( k = 0; k < L_FRAME4k; k++ ) + { + EnvSHBres_4k_fx[k] = EnvSHBres_fx[4 * k]; /* Q_shb */ + } + + /* calculate long-term mean envelope over four consecutive segments using linear interpolation */ + seg_len = L_FRAME4k / 4; + move16(); + den_seg_len = 1638; /* Q15 */ + move16(); + seg_len_2 = L_FRAME4k / 8; + move16(); + den_seg_len_2 = 3641; /* Q15 */ + move16(); + FOR( k = 0; k < 4; k++ ) + { + // seg_mean[k] = max(1.0f, mean(&EnvSHBres_4k[k * seg_len], seg_len)); + seg_mean[k] = s_max( 1, mean_no_sat_fx( &EnvSHBres_4k_fx[k * seg_len], seg_len ) ); /* Q_shb */ + move16(); + // den_seg_mean[k] = 1.0f / seg_mean[k]; + tmp = BASOP_Util_Divide1616_Scale( MAX16B, seg_mean[k], &tmp_e ); + tmp_e = sub( tmp_e, sub( 15, Q_shb ) ); + den_seg_mean[k] = shl_sat( tmp, tmp_e ); /* Q15 */ + move16(); + } + + /* first half of the first segment */ + IF( hBWE_TD->old_mean_EnvSHBres_fx == 0 ) + { + set16_fx( env_mean_normf_fx, den_seg_mean[0], seg_len_2 ); + } + ELSE + { + env_mean_normf_fx[0] = hBWE_TD->old_mean_EnvSHBres_fx; /* Q15 */ + move16(); + // step = (den_seg_mean[0] - hBWE_TD->old_mean_EnvSHBres) * den_seg_len_2; + step = mult( sub( den_seg_mean[0], hBWE_TD->old_mean_EnvSHBres_fx ), den_seg_len_2 ); /* Q15 */ + FOR( i = 1; i < seg_len_2; i++ ) + { + env_mean_normf_fx[i] = add_sat( env_mean_normf_fx[i - 1], step ); /* Q15 */ + move16(); + } + } + + /* segments 1-4 */ + p_env = &env_mean_normf_fx[seg_len_2]; + FOR( k = 1; k < 4; k++ ) + { + // step = ( den_seg_mean[k] - den_seg_mean[k - 1] ) * den_seg_len; + step = mult( den_seg_mean[k] - den_seg_mean[k - 1], den_seg_len ); + FOR( i = 0; i < seg_len; i++ ) + { + *p_env = add_sat( *( p_env - 1 ), step ); + move16(); + p_env++; + } + } + + /* last half of the last segment */ + // set_f( p_env, den_seg_mean[3], seg_len_2 ); + set16_fx( p_env, den_seg_mean[3], seg_len_2 ); + hBWE_TD->old_mean_EnvSHBres_fx = den_seg_mean[3]; + move16(); + + /* normalize residual SHB envelope with its long-term mean envelope */ + FOR( k = 0; k < L_FRAME4k; k++ ) + { + EnvSHBres_4k_norm_fx[k] = mult( EnvSHBres_4k_fx[k], env_mean_normf_fx[k] ); + move16(); + } + + /* calculate tilt of the long-term mean envelope */ + lls_interp_n_fx( seg_mean, 4, &shb_env_tilt_fx, &temp, 0 ); + + /* copy previous residual envelope to the buffer */ + Copy( hBWE_TD->old_EnvSHBres_fx, buf_EnvSHBres_fx, L_FRAME4k ); // Qs to be handled + + /* subtract mean value from the normalized SHB residual envelope */ + p_buf = &buf_EnvSHBres_fx[L_FRAME4k]; + temp = mean_no_sat_fx( EnvSHBres_4k_norm_fx, L_FRAME4k ); + FOR( k = 0; k < L_FRAME4k; k++ ) + { + *p_buf++ = sub( EnvSHBres_4k_norm_fx[k], temp ); + move16(); + } + + /* update memory */ + Copy( &buf_EnvSHBres_fx[L_FRAME4k], hBWE_TD->old_EnvSHBres_fx, L_FRAME4k ); // Qs to be handled + + /* calculate energy normalization factor for the auto-correlation function */ + // pow0 = sum2_f( &buf_EnvSHBres[L_FRAME4k], L_FRAME4k ) + 1.0f; + pow_e = sub( 15, Q_shb ); + pow0_fx = sum2_16_exp_fx( &buf_EnvSHBres_fx[L_FRAME4k], L_FRAME4k, &pow_e, 0 /* Give guard bits */ ) + 1; + // if (hBWE_TD->prev_enr_EnvSHBres == 1.0f) + IF( BASOP_Util_Cmp_Mant32Exp( hBWE_TD->prev_enr_EnvSHBres_fx, hBWE_TD->prev_enr_EnvSHBres_e, 1, 31 ) == 0 ) + { + // scale = 1.0f / pow0; + scale_fx = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, pow0_fx, &tmp_e ); + scale_e = sub( tmp_e, pow_e ); + } + ELSE + { + // scale = 1.0f / max( pow0, hBWE_TD->prev_enr_EnvSHBres ); + L_tmp1 = pow0_fx; + move32(); + IF( BASOP_Util_Cmp_Mant32Exp( L_tmp1, pow_e, hBWE_TD->prev_enr_EnvSHBres_fx, hBWE_TD->prev_enr_EnvSHBres_e ) < 0 ) + { + L_tmp1 = hBWE_TD->prev_enr_EnvSHBres_fx; + move32(); + pow_e = hBWE_TD->prev_enr_EnvSHBres_e; + move16(); + } + scale_fx = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_tmp1, &tmp_e ); // Qs to be handled + scale_e = sub( tmp_e, pow_e ); + } + hBWE_TD->prev_enr_EnvSHBres_fx = pow0_fx; + move32(); + hBWE_TD->prev_enr_EnvSHBres_e = pow_e; + move16(); + + /* calculate normalized auto-correlation function on the residual normalized SHB envelope */ + p_acorr = acorr_EnvSHBres; + p_buf = &buf_EnvSHBres_fx[L_FRAME4k - ENVSHBRES_ACORR_MIN]; + + FOR( k = 0; k < ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN; k++ ) + { + //*p_acorr++ = scale * dotp(&buf_EnvSHBres[L_FRAME4k], p_buf--, L_FRAME4k); + Word64 W_tmp = 0; + move64(); + + // tmp = *p_buf; + FOR( i = 0; i < L_FRAME4k; ++i ) + { + L_tmp = L_mult( buf_EnvSHBres_fx[L_FRAME4k + i], p_buf[i] ); // 2 * Q_shb + 1 + W_tmp = W_add( W_tmp, W_deposit32_l( L_tmp ) ); + } + p_buf--; + tmp_e = W_norm( W_tmp ); + L_tmp1 = W_extract_h( W_shl( W_tmp, tmp_e ) ); // 2 * Q_shb + tmp_e - 31 + L_tmp = Mpy_32_16_1( L_tmp1, scale_fx ); /* 2 * Q_shb + tmp_e - 31 - scale_e */ + //*p_acorr++ = extract_h( L_shl( L_tmp, add( 16, Q_shb ) - ( 2 * Q_shb + tmp_e - 31 - scale_e ) ) ); + *p_acorr++ = extract_h( L_shl( L_tmp, sub( add( 16, Q_shb ), sub( sub( add( shl( Q_shb, 1 ), tmp_e ), 31 ), scale_e ) ) ) ); + move16(); + } + + /* calculate variance of the SHB autocorrelation function */ + // acorr_v2a = sum2_f( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ) / ( ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ); + tmp_e = sub( 15, Q_shb ); + L_tmp = Mpy_32_32( sum2_16_exp_fx( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN, &tmp_e, 0 ), 53687091 /* 1 / ( ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ) in Q31 */ ); + + /* multiply with the maximum of the SHB autocorrelation function */ + maximum_fx( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN, &temp ); + // acorr_v2a *= temp; + L_tmp = Mpy_32_16_1( L_tmp, temp ); /* 31 - tmp_e + Q_shb - 15 */ + + // alpha = 25.0f; + alpha_fx = -1677721600; // Q26 + move32(); + + // acorr_v2a = 2.0f / ( 1.0f + (float) expf( -alpha * acorr_v2a ) ) - 1.0f; + Word32 exp_tmp = 1459366444; + Word16 exp_e = 2; + Word16 res_e = 0; + move32(); + move16(); + move16(); + + L_tmp = Mpy_32_32( alpha_fx, L_tmp ); // 31 - tmp_e + Q_shb - 15 - 5 + + tmp_e = sub( 31, sub( sub( add( sub( 31, tmp_e ), Q_shb ), 15 ), 5 ) ); + + // L_tmp = BASOP_Util_fPow(exp_tmp, exp_e, 2, 31, &res_e); + + L_tmp = BASOP_Util_fPow( exp_tmp, exp_e, L_tmp, tmp_e, &res_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( ONE_IN_Q31, 0, L_tmp, res_e, &tmp_e ); + acorr_v2a_fx = BASOP_Util_Divide3232_Scale( 2, L_tmp, &res_e ); + + res_e = sub( add( res_e, 31 ), tmp_e ); + + acorr_v2a_fx = sub( acorr_v2a_fx, shl( 1, sub( 15, res_e ) ) ); + + /* limit in the range 0.0 - 1.0 */ + // acorr_v2a = min( 1.0f, max( 0.0f, acorr_v2a ) ); + acorr_v2a_fx = shl_sat( acorr_v2a_fx, res_e ); + + if ( acorr_v2a_fx < 0 ) + { + acorr_v2a_fx = 0; + move16(); + } + + hBWE_TD->prev_shb_env_tilt_fx = shb_env_tilt_fx; + move16(); + hBWE_TD->prev_shb_env_tilt_q = Q_shb; + move16(); + } + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ + vf_ind_fx = 20; + move16(); + /* Save the SWB LSP values from current frame for interpolation */ - Copy( lsp_shb_2_fx, hBWE_TD->swb_lsp_prev_interp_fx, LPC_SHB_ORDER ); /* lsp_shb_2_fx in Q15 */ /* -------- start of memory rescaling -------- */ /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ @@ -1583,6 +3481,7 @@ void swb_tbe_enc_fx( if ( Lmax == 0 ) { Q_bwe_exc = 31; + move16(); } Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); @@ -1593,6 +3492,7 @@ void swb_tbe_enc_fx( if ( GT_16( Q_bwe_exc, tmp2 ) ) { Q_bwe_exc = tmp2; + move16(); } /* rescale the memories if Q_bwe_exc is different from previous frame */ @@ -1602,19 +3502,17 @@ void swb_tbe_enc_fx( rescale_genSHB_mem_enc( st_fx, sc ); } - /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ - Copy( hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); - + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) { #ifdef BASOP_NOGLOB - bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx_sat( L_shl_sat( bwe_exc_extended[cnt], sc ) ); + bwe_exc_extended_16[cnt] = round_fx_sat( L_shl_sat( bwe_exc_extended[cnt], sc ) ); #else - bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); + bwe_exc_extended_16[cnt] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); #endif + move16(); } - Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ Copy( hBWE_TD->state_syn_shbexc_fx, shaped_shb_excitation_fx, L_SHB_LAHEAD ); @@ -1628,25 +3526,22 @@ void swb_tbe_enc_fx( /* -------- end of rescaling memories -------- */ Q_bwe_exc_fb = hBWE_TD->prev_Q_bwe_exc_fb; move16(); - /* Determine formant PF strength */ - formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &hBWE_TD->tilt_mem_fx ); - /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ - - /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ - vf_ind_fx = 20; - move16(); - GenShapedSHBExcitation_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, - hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx, - coder_type, bwe_exc_extended_16, hBWE_TD->bwe_seed, vf_modified_fx, st_fx->extl, - &( hBWE_TD->tbe_demph_fx ), &( hBWE_TD->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, - shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, hBWE_TD->fb_state_lpc_syn_fx, - &( hBWE_TD->fb_tbe_demph_fx ), &Q_bwe_exc, &Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate, 0 ); + // Replace with IVAS equivalent + GenShapedSHBExcitation_ivas_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, + hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx, + st_fx->coder_type, bwe_exc_extended_16, hBWE_TD->bwe_seed, vf_modified_fx, st_fx->extl, + &( hBWE_TD->tbe_demph_fx ), &( hBWE_TD->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, + shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, hBWE_TD->fb_state_lpc_syn_fx, + &( hBWE_TD->fb_tbe_demph_fx ), &Q_bwe_exc, &Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate, 0, st_fx->element_mode, st_fx->flag_ACELP16k, nlExc16k_fx, mixExc16k_fx, st_fx->extl_brate, MSFlag, + EnvSHBres_4k_norm_fx, &( hBWE_TD->prev_pow_exc16kWhtnd_fx32 ), &( hBWE_TD->prev_mix_factor_fx ), &Env_error_fx, Env_error_part_fx ); *Q_white_exc = Q_bwe_exc_fb; + move16(); IF( EQ_16( st_fx->extl, FB_TBE ) ) { hBWE_TD->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + move16(); } ELSE { @@ -1656,8 +3551,23 @@ void swb_tbe_enc_fx( move16(); } + /* fill-in missing SHB excitation */ test(); - IF( EQ_32( st_fx->total_brate, ACELP_24k40 ) || EQ_32( st_fx->total_brate, ACELP_32k ) ) + test(); + IF( ( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) || EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) && LE_32( st_fx->last_core_brate, SID_2k40 ) ) + { + Copy( shaped_shb_excitation_fx + L_SHB_LAHEAD, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + } + + test(); + IF( GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) + { + Copy( shaped_shb_excitation_fx + L_SHB_LAHEAD, hStereoICBWE->shbSynthRef_fx, L_FRAME16k ); + } + + test(); + test(); + IF( GE_32( st_fx->extl_brate, SWB_TBE_2k8 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { IF( EQ_16( st_fx->codec_mode, MODE2 ) ) { @@ -1666,77 +3576,94 @@ void swb_tbe_enc_fx( } ELSE { - push_indice_fx( st_fx->hBstr, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF ); + push_indice( hBstr, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF ); } } FOR( i = 0; i < LPC_SHB_ORDER; i++ ) { - hBWE_TD->mem_stp_swb_fx[i] = shl( hBWE_TD->mem_stp_swb_fx[i], sub( Q_bwe_exc, st_fx->prev_Q_bwe_syn ) ); + hBWE_TD->mem_stp_swb_fx[i] = shl_sat( hBWE_TD->mem_stp_swb_fx[i], sub( Q_bwe_exc, st_fx->prev_Q_bwe_syn ) ); + move16(); } - FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD + i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], hBWE_TD->mem_stp_swb_fx, - hBWE_TD->ptr_mem_stp_swb_fx, &( hBWE_TD->gain_prec_swb_fx ), hBWE_TD->mem_zero_swb_fx, formant_fac_fx ); - /* i: shaped_shb_excitation_fx in Q_bwe_exc */ - /* i: lpc_shb_fx in Q12 */ - } - Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); + FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + { + PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD + i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], hBWE_TD->mem_stp_swb_fx, + hBWE_TD->ptr_mem_stp_swb_fx, &( hBWE_TD->gain_prec_swb_fx ), hBWE_TD->mem_zero_swb_fx, formant_fac_fx ); + /* i: shaped_shb_excitation_fx in Q_bwe_exc */ + /* i: lpc_shb_fx in Q12 */ + } + Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); - tmp = sub( shl( Q_bwe_exc, 1 ), 31 ); - prev_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ - curr_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ - FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) - { + + tmp = sub( shl( Q_bwe_exc, 1 ), 31 ); + prev_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + curr_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { #ifdef BASOP_NOGLOB - prev_pow_fx = L_mac0_o( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i], &Overflow ); /* 2*Q_bwe_exc */ - curr_pow_fx = L_mac0_o( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], &Overflow ); /* 2*Q_bwe_exc */ + prev_pow_fx = L_mac0_o( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i], &Overflow ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0_o( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], &Overflow ); /* 2*Q_bwe_exc */ #else - prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ - curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ + prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ #endif - } - - if ( GT_16( voice_factors_fx[0], 24576 /*0.75f Q15*/ ) ) - { - /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ - curr_pow_fx = L_shr( curr_pow_fx, 2 ); /* scale by 0.25 */ - } + } - Lscale = root_a_over_b_fx( curr_pow_fx, - shl( Q_bwe_exc, 1 ), - prev_pow_fx, - shl( Q_bwe_exc, 1 ), - &exp ); - FOR( i = 0; i < L_SHB_LAHEAD; i++ ) - { - L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ - shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ - } - IF( exp < 0 ) - { - Lscale = L_shl( Lscale, exp ); - exp = 0; - } - FOR( ; i < L_SHB_LAHEAD + 10; i++ ) - { + if ( GT_16( voice_factors_fx[0], 24576 /*0.75f Q15*/ ) ) + { + /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ + curr_pow_fx = L_shr( curr_pow_fx, 2 ); /* scale by 0.25 */ + } + + Lscale = root_a_over_b_fx( curr_pow_fx, + shl( Q_bwe_exc, 1 ), + prev_pow_fx, + shl( Q_bwe_exc, 1 ), + &exp ); + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + move16(); + } + IF( exp < 0 ) + { + Lscale = L_shl( Lscale, exp ); + exp = 0; + move16(); + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { #ifdef BASOP_NOGLOB - tmp = i_mult_o( sub( i, 19 ), 3277 /*0.1f Q15*/, &Overflow ); /* Q15 */ - L_tmp1 = Mult_32_16( L_shl_o( 1, sub( 31, exp ), &Overflow ), tmp ); /* Q31-exp */ + tmp = i_mult_o( sub( i, 19 ), 3277 /*0.1f Q15*/, &Overflow ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl_o( 1, sub( 31, exp ), &Overflow ), tmp ); /* Q31-exp */ #else - tmp = i_mult( sub( i, 19 ), 3277 /*0.1f Q15*/ ); /* Q15 */ - L_tmp1 = Mult_32_16( L_shl( 1, sub( 31, exp ) ), tmp ); /* Q31-exp */ + tmp = i_mult( sub( i, 19 ), 3277 /*0.1f Q15*/ ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl( 1, sub( 31, exp ) ), tmp ); /* Q31-exp */ #endif - tmp = sub( 32767 /*1.0f Q15*/, tmp ); - Lscale = L_add( Mult_32_16( Lscale, tmp ), L_tmp1 ); - L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ + tmp = sub( 32767 /*1.0f Q15*/, tmp ); + Lscale = L_add( Mult_32_16( Lscale, tmp ), L_tmp1 ); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ #ifdef BASOP_NOGLOB - shaped_shb_excitation_fx[i] = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /* Q_bwe_exc */ + shaped_shb_excitation_fx[i] = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /* Q_bwe_exc */ #else - shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ #endif + move16(); + } + } + ELSE + { + /* reset the PF memories if the PF is not running */ + set16_fx( hBWE_TD->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + hBWE_TD->gain_prec_swb_fx = ONE_IN_Q14; + move16(); + set16_fx( hBWE_TD->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); } /* Update SHB excitation */ @@ -1748,15 +3675,54 @@ void swb_tbe_enc_fx( EstimateSHBGainShape_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, GainShape_fx, subwin_shb_fx, &n_subfr_saturation ); - /* Gain shape BWS/high band low energy fix */ - IF( LT_16( hBWE_TD->cldfbHBLT, 8192 /*1.0f Q13*/ ) ) /* cldfbHBLT in Q13 */ + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + /* Gain shape attenuation in case of big error in envelope modelling */ FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { - /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ - /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ - GainShape_fx[i] = mac_r( 676457349l /*0.315 Q31*/, 3277 /*0.1 Q15*/, GainShape_fx[i] ); + IF( GT_16( Env_error_part_fx[i], 100 ) ) + { + /* set gain shape to the average of the remaining gains */ + // GainShape[i] = ( sum_f( GainShape, NUM_SHB_SUBGAINS ) - GainShape[i] ) / ( NUM_SHB_SUBGAINS - 1 ); + L_tmp = L_sub( sum16_32_fx( GainShape_fx, NUM_SHB_SUBGAINS ), GainShape_fx[i] ); + tmp = BASOP_Util_Divide3232_Scale( L_tmp, NUM_SHB_SUBGAINS - 1, &exp ); + GainShape_fx[i] = shl( tmp, sub( exp, 15 ) ); /* Q15 */ + move16(); + } + } + } + + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* Gain shape BWS/high band low energy fix */ + IF( LT_16( hBWE_TD->cldfbHBLT, 8192 /*1.0f Q13*/ ) ) /* cldfbHBLT in Q13 */ + { + /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ + /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ + GainShape_fx[i] = mac_r( 676457349l /*0.315 Q31*/, 3277 /*0.1 Q15*/, GainShape_fx[i] ); + move16(); + } + } + } + + /* high-band gain control in case of BWS */ + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + IF( st_fx->bwidth_sw_cnt > 0 ) + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] *= ( (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD ); + tmp = i_mult( st_fx->bwidth_sw_cnt, ONE_BY_BWS_TRAN_PERIOD_Q15 ); + GainShape_fx[i] = mult( GainShape_fx[i], tmp ); + move16(); + } } } @@ -1824,47 +3790,154 @@ void swb_tbe_enc_fx( move16(); /*Q15 */ } - /* voicing in Q15 */ - L_tmp = L_mult( voicing[0], 8192 ); - L_tmp = L_mac( L_tmp, voicing[1], 8192 ); - L_tmp = L_mac( L_tmp, voicing[2], 8192 ); - tmp = sum1 = round_fx( L_tmp ); /* sum1 used again below - Q13 */ - tmp = add( tmp, 1 ); /* To ensure change is BE */ + /* calculate tilt in all sub-frame gains */ + Copy( GainShape_fx, GainShape_Interp_fx, NUM_SHB_SUBGAINS ); + lls_interp_n_fx( GainShape_Interp_fx, NUM_SHB_SUBGAINS, &GainShape_tilt_fx, &temp, 1 ); - /* voice_factors_fx in Q15 */ - L_tmp = L_mult( voice_factors_fx[0], 8192 ); - L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); - L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); - L_tmp = L_mac( L_tmp, voice_factors_fx[3], 8192 ); - tmp1 = sum2 = round_fx( L_tmp ); /* sum2 used again below - Q13 */ + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // if (acorr_v2a < 0.4f && vf_ind >= 5 && fabs(GainShape_tilt) < 0.2f && shb_env_tilt < 500.0f && hBWE_TD->prev_shb_env_tilt < 500.0f) + test(); + test(); + test(); + test(); + IF( LT_16( acorr_v2a_fx, 13107 ) /* 0.4f in Q15 */ && GE_16( vf_ind_fx, 5 ) && LT_16( abs_s( GainShape_tilt_fx ), 6554 /* 0.2f in Q15 */ ) && LT_32( L_deposit_l( shb_env_tilt_fx ), L_shl( 500, Q_shb ) ) && LT_32( L_deposit_l( hBWE_TD->prev_shb_env_tilt_fx ), L_shl( 500, hBWE_TD->prev_shb_env_tilt_q ) ) ) + { + /* stronger smoothing in case of unvoiced SHB residual signal with gaussian excitation */ + // feedback = lin_interp(acorr_v2a, 0.4f, 0.0f, 0.0f, 0.95f, 0); + feedback = lin_interp_ivas_fx( acorr_v2a_fx, 13107 /* 0.4f in Q15 */, 0, 0, 31130 /* 0.95f in Q15 */, 0 ); + // feedback = min( max( feedback, 0.0f ), 1.0f ); + feedback = s_min( s_max( feedback, 0 ), MAX16B ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] = ( 1 - feedback ) * GainShape[i] + feedback * GainShape_Interp[i]; + GainShape_fx[i] = extract_h( L_add( L_mult( sub( MAX16B, feedback ), GainShape_fx[i] ), L_mult( feedback, GainShape_Interp_fx[i] ) ) ); + move16(); + } + } + } + ELSE + { + /* voicing in Q15 */ + L_tmp = L_mult( voicing[0], 8192 ); + L_tmp = L_mac( L_tmp, voicing[1], 8192 ); + L_tmp = L_mac( L_tmp, voicing[2], 8192 ); + tmp = sum1 = round_fx( L_tmp ); /* sum1 used again below - Q13 */ + tmp = add( tmp, 1 ); /* To ensure change is BE */ - test(); - test(); - IF( EQ_16( frGainAttenuate, 1 ) || ( GT_16( tmp, 19661 ) && GT_16( tmp1, 6554 ) ) ) + /* voice_factors_fx in Q15 */ + L_tmp = L_mult( voice_factors_fx[0], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[3], 8192 ); + tmp1 = sum2 = round_fx( L_tmp ); /* sum2 used again below - Q13 */ + + + test(); + test(); + IF( EQ_16( frGainAttenuate, 1 ) || ( GT_16( tmp, 19661 /* 2.4f in Q13 */ ) && GT_16( tmp1, 6554 /* 0.8f in Q13 */ ) ) ) + + { + temp_swb_fac = hBWE_TD->prev_swb_GainShape_fx; + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ + GainShape_fx[i] = round_fx( L_mac( L_mult( sub( 32767, feedback ), GainShape_fx[i] ), feedback, temp_swb_fac ) ); + temp_swb_fac = GainShape_fx[i]; + move16(); + } + } + } + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - temp_swb_fac = hBWE_TD->prev_swb_GainShape_fx; - FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + /* Re-normalize gain shape before quantization */ + // sum_gain = sum2_f(GainShape, NUM_SHB_SUBGAINS); + sum_gain_fx = sum16_32_fx( GainShape_fx, NUM_SHB_SUBGAINS ); + IF( sum_gain_fx == 0 ) { - /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ - GainShape_fx[i] = round_fx( L_mac( L_mult( sub( 32767, feedback ), GainShape_fx[i] ), feedback, temp_swb_fac ) ); - temp_swb_fac = GainShape_fx[i]; + normFact_fx = 0; + move16(); + } + ELSE + { + // normFact = (float) sqrt( 1.0f / sum_gain ); + tmp = Q16; + move16(); + normFact_fx = ISqrt32( sum_gain_fx, &tmp ); + } + + // v_multc( GainShape, normFact, GainShape, NUM_SHB_SUBGAINS ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; ++i ) + { + GainShape_fx[i] = extract_h( L_shl( Mpy_32_16_1( normFact_fx, GainShape_fx[i] ), tmp ) ); /* Q15 */ move16(); } } + + hBWE_TD->prev_swb_GainShape_fx = GainShape_fx[3]; move16(); /* Compute the power of gains away from the peak gain prior to quantization */ - p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_in_fx = pow_off_pk_corrected_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + } + ELSE + { + p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + } /* Quantization of the gain shape parameter */ - - QuantizeSHBsubgains_fx( st_fx, GainShape_fx, st_fx->extl ); + QuantizeSHBsubgains_ivas_fx( st_fx, GainShape_fx, st_fx->extl ); /* o: GainShape_fx in Q15 */ + /* Compute the power of gains away from the peak gain after quantization */ - p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_out_fx = pow_off_pk_corrected_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + } + ELSE + { + p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + } + + /* Gain shape smoothing after quantization */ + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + GainShape_Interp_fx[i] = GainShape_fx[i * NUM_SHB_SUBGAINS]; + move16(); + } + + lls_interp_n_fx( GainShape_Interp_fx, NUM_SHB_SUBGAINS, &GainShape_tilt_fx, &temp, 1 ); + + // if ( vf_ind >= 6 && fabs( GainShape_tilt ) < 0.12f ) + test(); + IF( GE_16( vf_ind_fx, 6 ) && LT_16( abs_s( GainShape_tilt_fx ), 3932 /* 0.12f in Q15 */ ) ) + { + // feedback = 0.3f; + feedback = 9830; /* 0.3f in Q15 */ + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] = ( 1 - feedback ) * GainShape[i * NUM_SHB_SUBGAINS] + feedback * GainShape_Interp[i]; + GainShape_fx[i] = extract_h( L_add( L_mult( sub( MAX16B, feedback ), GainShape_fx[i * NUM_SHB_SUBGAINS] ), L_mult( feedback, GainShape_Interp_fx[i] ) ) ); // Q15 + move16(); + } + + FOR( i = NUM_SHB_SUBFR - 1; i > 0; i-- ) + { + GainShape_fx[i] = GainShape_fx[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + } + } /* Estimate the gain parameter */ EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, @@ -1882,12 +3955,74 @@ void swb_tbe_enc_fx( L_tmp = root_a_over_b_fx( p2m_in_fx, 28, p2m_out_fx, 29, &exp_out ); GainFrame_fx = L_shl( Mult_32_32( GainFrame_fx, L_tmp ), exp_out ); /* Q18 */ } + + // if ( st_fx->element_mode > EVS_MONO && st_fx->L_frame != st_fx->last_L_frame && hBWE_TD->prev_gainFr_SHB != 0 && ( st_fx->last_extl == SWB_TBE || st_fx->last_extl == FB_TBE ) && st_fx->coder_type == TRANSITION && st_fx->coder_type_raw != VOICED && st_fx->clas == VOICED_CLAS && st_fx->last_clas == VOICED_CLAS && ( 3.0f * voice_factors[0] < voice_factors[( st_fx->L_frame >> 6 ) - 1] ) ) test(); - IF( EQ_16( frGainSmoothEn, 1 ) && LT_32( hBWE_TD->prev_gainFr_SHB_fx, GainFrame_fx ) ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( st_fx->element_mode > EVS_MONO && NE_16( st_fx->L_frame, st_fx->last_L_frame ) && hBWE_TD->prev_gainFr_SHB != 0 && ( EQ_16( st_fx->last_extl, SWB_TBE ) || EQ_16( st_fx->last_extl, FB_TBE ) ) && EQ_16( st_fx->coder_type, TRANSITION ) && NE_16( st_fx->coder_type_raw, VOICED ) && EQ_16( st_fx->clas, VOICED_CLAS ) && EQ_16( st_fx->last_clas, VOICED_CLAS ) && LT_16( mult( 24576 /* 3.0f in Q13 */, voice_factors_fx[0] ), shr( voice_factors_fx[( st_fx->L_frame >> 6 ) - 1], 2 ) ) ) { - GainFrame_fx = L_add( L_shr( hBWE_TD->prev_gainFr_SHB_fx, 1 ), L_shr( GainFrame_fx, 1 ) ); /* Q18 */ + // float fac = GainFrame / hBWE_TD->prev_gainFr_SHB; + Word16 fac = BASOP_Util_Divide3232_Scale( GainFrame_fx, hBWE_TD->prev_gainFr_SHB_fx, &tmp_e ); + + // if ( fac > 4.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( fac ), tmp_e, 1073741824, 3 ) > 0 ) + { + // GainFrame = 4.0f * GainFrame / fac; + GainFrame_fx = BASOP_Util_Divide3216_Scale( GainFrame_fx, fac, &tmp1_e ); + GainFrame_fx = L_shl( GainFrame_fx, add( tmp1_e, 2 ) ); /* Q18 */ + } } + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // if ( acorr_v2a > 0.1f && Env_error > 5.0f ) + test(); + test(); + IF( GT_16( acorr_v2a_fx, 3277 /* 0.1f in Q15 */ ) && GT_16( Env_error_fx, 5 ) ) + { + /* attenuate frame gain in case of voiced SHB residual signal with gaussian excitation */ + // fact_atten = lin_interp( Env_error, 5.0f, 1.0f, 25.0f, 0.2f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( Env_error_fx, 5, MAX16B, 25, 6554 /* 0.2f in Q15 */, 1 ); + // GainFrame *= fact_atten; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, fact_atten_fx ); + } + /* Frame gain attenuation in case of big error in envelope modelling */ + // else if ( Env_error > 100.0f || hBWE_TD->prev_Env_error > 100.0f ) + ELSE IF( GT_16( Env_error_fx, 100 ) || GT_16( hBWE_TD->prev_Env_error_fx, 100 ) ) + { + // if ( Env_error > 100.0f ) + IF( GT_16( Env_error_fx, 100 ) ) + { + // fact_atten = lin_interp( Env_error, 100.0f, 1.0f, 300.0f, 0.1f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( Env_error_fx, 100, MAX16B, 300, 3277 /* 0.1f in Q15 */, 1 ); + } + ELSE + { + // fact_atten = lin_interp( hBWE_TD->prev_Env_error, 100.0f, 1.0f, 300.0f, 0.5f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( hBWE_TD->prev_Env_error_fx, 100, MAX16B, 300, ONE_IN_Q14 /* 0.5f in Q15 */, 1 ); + } + // GainFrame *= fact_atten; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, fact_atten_fx ); + } + } + ELSE + { + test(); + IF( EQ_16( frGainSmoothEn, 1 ) && LT_32( hBWE_TD->prev_gainFr_SHB_fx, GainFrame_fx ) ) + { + GainFrame_fx = L_add( L_shr( hBWE_TD->prev_gainFr_SHB_fx, 1 ), L_shr( GainFrame_fx, 1 ) ); /* Q18 */ + } + } + + test(); test(); IF( EQ_16( frGainAttenuate, 1 ) && LE_16( MA_lsp_shb_spacing, 79 /*0.0024f Q15*/ ) ) { @@ -1906,80 +4041,177 @@ void swb_tbe_enc_fx( tmp = add( 26214, mult_r( feedback, 16384 ) ); GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 */ } + hBWE_TD->prev_frGainAtten = frGainAttenuate; move16(); + hBWE_TD->prev_gainFr_SHB_fx = GainFrame_fx; move16(); /* Q18 */ + // if ( GainFrame > 153.0f && st_fx->element_mode >= IVAS_CPE_DFT && hStereoICBWE != NULL ) + test(); + test(); + if ( GT_32( GainFrame_fx, 40108032 /* 153.0f in Q18 */ ) && GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) + { + hStereoICBWE->MSFlag = 1; + move16(); + } /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ tmp = mult_r( 25600 /*400 Q6*/, sd_uq_q_fx ); /* Q6 * Q15 => Q6 */ - IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - tmp1 = mult_r( 6554 /*0.2f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + // sd_uq_q = 1 - 0.7f * ( sd_uq_q * sd_uq_q ); + tmp1 = mult_r( 22938 /*0.7f Q15*/, tmp ); /* Q15, Q6 => Q6 */ L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ } ELSE { - tmp1 = mult_r( 3277 /*0.1f Q15*/, tmp ); /* Q15, Q6 => Q6 */ - L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + tmp1 = mult_r( 6554 /*0.2f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + ELSE + { + tmp1 = mult_r( 3277 /*0.1f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } } /* sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); */ L_tmp = L_min( L_tmp, 8192l /*1.0f Q13*/ ); L_tmp = L_max( L_tmp, 4096l /*0.5f Q13*/ ); /* Q13 */ /* keep the L_tmp; dont overwrite */ - /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ - /* pitch_buf: Q6 */ - pitBufAvg_fx = mult_r( pitch_buf[0], 1311 ); - pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[1], 1311 ) ); - pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[2], 1311 ) ); - pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[3], 1311 ) ); /* Q10 */ + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ + /* pitch_buf: Q6 */ + pitBufAvg_fx = mult_r( pitch_buf[0], 1311 ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[1], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[2], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[3], 1311 ) ); /* Q10 */ - /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ - tmp2 = 5462 /*0.1667f Q15*/; - if ( GT_16( sum2, 4915 /*0.6f Q13*/ ) ) + /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ + tmp2 = 5462 /*0.1667f Q15*/; + move16(); + if ( GT_16( sum2, 4915 /*0.6f Q13*/ ) ) + { + tmp2 = 10912 /*0.333f Q15*/; /* Q15 */ + move16(); + } + voicingBufAvg_fx = shl( mult( tmp2, sum1 ), 2 ); /* Q15 */ + + // if ( voicingBufAvg <= 0.0f && sd_uq_q * pitBufAvg != 0 ) + test(); + IF( voicingBufAvg_fx <= 0 && Mpy_32_16_1( L_tmp, pitBufAvg_fx ) != 0 ) + { + // voicingBufAvg = sd_uq_q * pitBufAvg / 1.001f; + tmp = BASOP_Util_Divide1616_Scale( pitBufAvg_fx, 16400, &tmp_e ); + tmp_e = sub( add( tmp_e, 5 ), 1 ); + L_tmp1 = Mpy_32_16_1( L_tmp, tmp ); + voicingBufAvg_fx = extract_h( L_tmp1 ); + } + // else if ( voicingBufAvg <= 0.0f ) + ELSE IF( voicingBufAvg_fx <= 0 ) + { + // voicingBufAvg = 1.0f; + voicingBufAvg_fx = MAX16B; + move16(); + } + } + + /* high-band gain control in case of BWS */ + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - tmp2 = 10912 /*0.333f Q15*/; /* Q15 */ + IF( st_fx->bwidth_sw_cnt > 0 ) + { + // GainFrame *= ( (float) ( st_fx->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD ); + tmp = i_mult( st_fx->bwidth_sw_cnt, ONE_BY_BWS_TRAN_PERIOD_Q15 ); + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, tmp ); + } } - voicingBufAvg_fx = shl( mult( tmp2, sum1 ), 2 ); /* Q15 */ + /* Controlled gain evolution in SWB for stronger voiced segments */ + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // GainFrame *= sd_uq_q; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, extract_l( L_shl( L_tmp, 2 ) ) ); + } + ELSE + { + /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ + /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + /* 1/voicingBufAvg_fx */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ - /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ - /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + /* sd_uq_q*pitBufAvg */ + L_tmp = Mult_32_16( L_tmp, pitBufAvg_fx ); /* Q13 * Q10 + 1 -16 => Q8 */ + L_tmp = Mult_32_16( L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ +#ifdef BASOP_NOGLOB + tmp = round_fx_o( L_shl_o( L_tmp, 31 - ( 7 - exp ), &Overflow ), &Overflow ); /* Q15 */ +#else + tmp = round_fx( L_shl( L_tmp, 31 - ( 7 - exp ) ) ); /* Q15 */ +#endif + } + tmp = s_min( tmp, 32767 /*1.0f Q15*/ ); + tmp = s_max( tmp, 19661 /*0.6f Q15*/ ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 + Q15 + 1 - 16 : Q18 */ + } - /* 1/voicingBufAvg_fx */ - tmp = 32767; - move16(); - IF( voicingBufAvg_fx > 0 ) + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) { - exp = norm_s( voicingBufAvg_fx ); - tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ + if ( EQ_16( st_fx->rf_mode, 1 ) ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis */ + // GainFrame *= 0.85f; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, 27853 ); + } + } + ELSE + { + test(); + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) || EQ_16( st_fx->rf_mode, 1 ) ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame_fx = Mult_32_16( GainFrame_fx, 27853 /*0.85f Q15*/ ); /* Q18 */ + } + } - /* sd_uq_q*pitBufAvg */ - L_tmp = Mult_32_16( L_tmp, pitBufAvg_fx ); /* Q13 * Q10 + 1 -16 => Q8 */ - L_tmp = Mult_32_16( L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ -#ifdef BASOP_NOGLOB - tmp = round_fx_o( L_shl_o( L_tmp, 31 - ( 7 - exp ), &Overflow ), &Overflow ); /* Q15 */ -#else - tmp = round_fx( L_shl( L_tmp, 31 - ( 7 - exp ) ) ); /* Q15 */ -#endif + /* Quantization of the frame gain parameter */ + IF( st_fx->rf_mode ) + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, &hRF->RF_bwe_gainFr_ind, 0 ); + } + ELSE + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, NULL, ( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) ? 1 : 0 ); } - tmp = s_min( tmp, 32767 /*1.0f Q15*/ ); - tmp = s_max( tmp, 19661 /*0.6f Q15*/ ); - GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 + Q15 + 1 - 16 : Q18 */ + IF( hStereoICBWE != NULL ) + { + push_indice( hBstr, IND_STEREO_ICBWE_MSFLAG, hStereoICBWE->MSFlag, STEREO_ICBWE_MSFLAG_BITS ); + } + /* Backup for the IC BWE parameters */ test(); - IF( EQ_16( st_fx->L_frame, L_FRAME16k ) || EQ_16( st_fx->rf_mode, 1 ) ) + IF( GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) { - /* Compensate for energy increase mismatch due to memory-less synthesis*/ - GainFrame_fx = Mult_32_16( GainFrame_fx, 27853 /*0.85f Q15*/ ); /* Q18 */ + // Check Qs + Copy_Scale_sig_16_32( lpc_shb_fx, hStereoICBWE->lpSHBRef_fx, LPC_SHB_ORDER + 1, 0 ); } - /* Quantization of the frame gain parameter */ - QuantizeSHBframegain_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, &hRF->RF_bwe_gainFr_ind ); - /* Adjust the subframe and frame gain of the synthesized SHB signal */ /* Scale the shaped excitation */ IF( EQ_32( st_fx->extl, FB_TBE ) ) @@ -1988,26 +4220,31 @@ void swb_tbe_enc_fx( if ( GainFrame_fx == 0 ) { tmp = 31; + move16(); } L_tmp = L_shl( GainFrame_fx, tmp ); /* 18 + tmp */ tmp1 = 0; + move16(); FOR( i = 0; i < L_FRAME16k; i++ ) { L_tmp1 = Mult_32_16( L_tmp, GainShape_fx[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ /*White_exc16k_fx[i] = round_fx( L_shl(Mult_32_16( L_tmp1, White_exc16k_fx[i]),(23 - tmp -*Q_white_exc)) );*/ /*18 + tmp +*Q_white_exc -15 + 23 - tmp -*Q_white_exc -16 = 10*/ White_exc16k_fx[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k_fx[i] ) ); /* 18 + tmp +*Q_white_exc -15 -16 */ + move16(); /*Lmax = L_max(Lmax,White_exc16k_fx[i]);*/ tmp1 = s_max( tmp1, abs_s( White_exc16k_fx[i] ) ); /*White_exc16k_fx[i] =32767;*/ /*White_exc16k_fx[i] = shr(White_exc16k_fx[i],5);*/ } *Q_white_exc = sub( add( *Q_white_exc, tmp ), 13 ); /* *Q_white_exc + 18 + tmp -15 -16 */ + move16(); tmp = norm_s( tmp1 ); if ( tmp1 == 0 ) { tmp = 15; + move16(); } FOR( i = 0; i < L_FRAME16k; i++ ) @@ -2019,6 +4256,9 @@ void swb_tbe_enc_fx( move16(); } + hBWE_TD->prev_Env_error = Env_error_fx; + move16(); + /* *Q_white_exc = Q_bwe_exc_mod; move16(); output Qwhiteexc_FB from the GenShapedSHB function*/ st_fx->prev_Q_bwe_syn = Q_bwe_exc; move16(); @@ -2053,16 +4293,15 @@ void swb_tbe_enc_fx( /*--------------------------------------------------------------------------*/ static void EstimateSHBFrameGain_fx( - const Word16 length, /* i : SHB overlap length */ - const Word16 *oriSHB, /* i : target original SHB frame Q_oriSHB */ - const Word16 Q_oriSHB, - const Word16 *synSHB, /* i : shaped SHB excitation Q_synSHB */ - const Word16 Q_synSHB, - Word16 *subgain, /* i : estimate of gain shape Q15 */ - Word32 *GainFrame, /* o : estimat of gain frame Q18 */ - const Word16 *win_shb, /* i : SHB window Q15 */ - const Word16 *subwin_shb_local /* i : SHB subframe window Q15 */ - , + const Word16 length, /* i : SHB overlap length */ + const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ + const Word16 Q_oriSHB, /* i : Q of arget original SHB frame */ + const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ + const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ + Word16 *subgain, /* i : estimate of gain shape Q15 */ + Word32 *GainFrame, /* o : estimat of gain frame Q18 */ + const Word16 *win_shb, /* i : SHB window Q15 */ + const Word16 *subwin_shb_local, /* i : SHB subframe window Q15 */ const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ ) { @@ -2070,7 +4309,7 @@ static void EstimateSHBFrameGain_fx( Word16 i, j, k, l_shb_lahead, l_frame; Word16 join_length, num_join, sig; Word32 mod_syn[L_FRAME16k + L_SHB_LAHEAD]; - Word32 oriNrg = 0, synNrg = 0; + Word32 oriNrg, synNrg; Word16 sum_gain; Word32 frame_gain; Word32 L_tmp; @@ -2079,7 +4318,9 @@ static void EstimateSHBFrameGain_fx( Word16 scaling = 0; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + move16(); /* initilaization */ l_frame = L_FRAME16k; @@ -2088,7 +4329,6 @@ static void EstimateSHBFrameGain_fx( move16(); skip = skip_bands_SWB_TBE; - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { skip = skip_bands_WB_TBE; @@ -2101,7 +4341,6 @@ static void EstimateSHBFrameGain_fx( /* apply gain for each subframe, and store noise output signal using overlap-add*/ set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { sum_gain = 0; @@ -2123,7 +4362,6 @@ static void EstimateSHBFrameGain_fx( move16(); FOR( k = 0; k < length; k++ ) { - L_tmp = L_mult0( subwin_shb_local[k + 1], subgain[i] ); /* Q30 */ sum_gain = round_fx( L_mac0( L_tmp, subwin_shb_local[length - k - 1], subgain[i - 1] ) ); /* Q14 */ mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); @@ -2151,7 +4389,7 @@ static void EstimateSHBFrameGain_fx( sum_gain = mult_r( subwin_shb_local[k + 1], subgain[0] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) { @@ -2159,7 +4397,7 @@ static void EstimateSHBFrameGain_fx( { mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) @@ -2168,21 +4406,21 @@ static void EstimateSHBFrameGain_fx( tmp = round_fx( L_mac0( L_tmp, subwin_shb_local[k + 1], subgain[( i + 1 ) * num_join] ) ); /* Q14 */ mod_syn[j] = L_shl( L_mult( tmp, synSHB[j] ), 1 ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } } FOR( k = 0; k < join_length - length; k++ ) { mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); move32(); /* Q(16+Q_synSHB)*/ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) { tmp = mult_r( subwin_shb_local[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ mod_syn[j] = L_mult( tmp, synSHB[j] ); move32(); /* Q(16+Q_synSHB ) */ - j++; + j = add( j, 1 ); } } /* adjust frame energy */ @@ -2197,10 +4435,10 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[i] ), &Overflow ); /*Q_synSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_synSHB */ #else - sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ - oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ - sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ - synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ + sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ #endif } @@ -2211,9 +4449,9 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( mod_syn[i], &Overflow ); /* Q_oriSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_oriSHB */ #else - oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ - sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ - synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ + oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ + sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ #endif } @@ -2227,8 +4465,8 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ), &Overflow ); /* Q_oriSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_oriSHB */ #else - sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ - oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ + sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ sig = round_fx( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ) ); /* Q_oriSHB */ synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ @@ -2236,8 +4474,7 @@ static void EstimateSHBFrameGain_fx( } IF( EQ_32( oriNrg, MAX_32 ) ) { - scaling = negate( shr( n_subfr_saturation, 1 ) + 1 ); - move16(); + scaling = negate( add( shr( n_subfr_saturation, 1 ), 1 ) ); oriNrg = 0; move32(); FOR( i = 0; i < l_shb_lahead; i++ ) @@ -2287,7 +4524,7 @@ static void EstimateSHBFrameGain_fx( static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) { - Word16 i, j = 0; + Word16 i, j; Word32 sum, L_tmp; sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ @@ -2311,6 +4548,32 @@ static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) } +static Word32 pow_off_pk_corrected_fx( Word16 a[], Word16 len, Word16 step ) +{ + Word16 i, j; + Word32 sum, L_tmp; + + sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ + + j = 0; + move16(); + FOR( i = step; i < len; i += step ) + { + L_tmp = L_shr( L_mult0( a[i], a[i] ), 1 ); /* Q29 */ + sum = L_add( sum, L_tmp ); /* Q29 */ + if ( GT_16( a[i], a[j] ) ) + { + j = i; + move16(); + } + } + L_tmp = L_shr( L_mult0( a[j], a[j] ), 1 ); /* Q29 */ + sum = L_sub( sum, L_tmp ); /* Q29 */ + + return ( sum ); +} + + /*==========================================================================*/ /* FUNCTION : static void EstimateSHBGainShape_fx() */ /*--------------------------------------------------------------------------*/ @@ -2333,15 +4596,15 @@ static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) /* RETURN ARGUMENTS : */ /* _ None */ /*--------------------------------------------------------------------------*/ + static void EstimateSHBGainShape_fx( - const Word16 length, /* i : SHB overlap length */ - const Word16 *oriSHB, /* i : target original SHB frame Q_oriSHB*/ - const Word16 Q_oriSHB, - const Word16 *synSHB, /* i : shaped SHB excitation Q_synSHB*/ - const Word16 Q_synSHB, - Word16 *subgain, /* o : estimate of gain shape Q15*/ - const Word16 *subwin /* i : SHB subframe window Q15*/ - , + const Word16 length, /* i : SHB overlap length */ + const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ + const Word16 Q_oriSHB, /* i : Q of target original SHB frame */ + const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ + const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ + Word16 *subgain, /* o : estimate of gain shape Q15 */ + const Word16 *subwin, /* i : SHB subframe window Q15 */ Word16 *n_subfr_saturation /* o : Number of subframes which saturated while calculating oriNrg */ ) { @@ -2361,8 +4624,12 @@ static void EstimateSHBGainShape_fx( Word16 scaling = 0; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + move32(); + move16(); move16(); + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; move16(); num_gains = NUM_SHB_SUBGAINS; @@ -2374,13 +4641,12 @@ static void EstimateSHBGainShape_fx( num_gains = NUM_SHB_SUBFR / 4; move16(); skip = skip_bands_WB_TBE; - move16(); } /* calculate and normalize the subgain */ oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { @@ -2390,11 +4656,12 @@ static void EstimateSHBGainShape_fx( IF( ( i & 0x1 ) == 0 ) { oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); } j = skip[i]; + move16(); IF( i == 0 ) { FOR( k = 0; k < length / 2; k++ ) @@ -2445,7 +4712,7 @@ static void EstimateSHBGainShape_fx( #endif } } - IF( i == NUM_SHB_SUBFR / 2 - 1 ) + IF( EQ_16( i, NUM_SHB_SUBFR / 2 - 1 ) ) { length_tmp = sub( length2, shr( length, 1 ) ); FOR( ; k < length_tmp; k++ ) @@ -2487,7 +4754,7 @@ static void EstimateSHBGainShape_fx( logic16(); IF( EQ_16( ( i & 0x1 ), 1 ) ) { - L_subgain[i / 2] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + L_subgain[i / 2] = root_a_over_b_fx( oriNrg, shl( Q_oriSHB, 1 ), synNrg, shl( Q_synSHB, 1 ), &n ); move16(); /* Q(31-n) */ norm[i / 2] = n; move16(); @@ -2505,12 +4772,11 @@ static void EstimateSHBGainShape_fx( FOR( i = 0; i < num_gains; i++ ) { oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); - j = join_length * i; - move16(); + j = i_mult2( join_length, i ); FOR( k = 0; k < length; k++ ) { sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ @@ -2563,9 +4829,10 @@ static void EstimateSHBGainShape_fx( move16(); IF( EQ_32( oriNrg, MAX_32 ) ) { - if ( n_subfr_saturation != NULL ) + IF( n_subfr_saturation != NULL ) { *n_subfr_saturation = add( *n_subfr_saturation, 1 ); + move16(); } scaling = -1; move16(); @@ -2599,7 +4866,7 @@ static void EstimateSHBGainShape_fx( #endif } } - L_subgain[i] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + L_subgain[i] = root_a_over_b_fx( oriNrg, shl( Q_oriSHB, 1 ), synNrg, shl( Q_synSHB, 1 ), &n ); move32(); /* Q(31-n) */ n = sub( n, scaling ); norm[i] = n; @@ -2621,22 +4888,24 @@ static void EstimateSHBGainShape_fx( subgain[i] = round_fx( L_shl( L_subgain[i], sub( norm[i], n_max + 1 ) ) ); /* Q(14-n_max) */ L_sum_gain = L_mac0( L_sum_gain, subgain[i], subgain[i] ); /* Q(28-2*n_max) */ #endif + move16(); } /* normalize the subgain */ n = norm_l( L_sum_gain ); L_sum_gain = L_shl( L_sum_gain, n ); - n = sub( 31, add( n, ( sub( 28, n_max * 2 ) ) ) ); + n = sub( 31, add( n, ( sub( 28, shl( n_max, 1 ) ) ) ) ); normFact = Isqrt_lc( L_sum_gain, &n ); FOR( i = 0; i < num_gains; i++ ) { - L_tmp = Mult_32_16( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ + L_tmp = Mpy_32_16_1( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ #ifdef BASOP_NOGLOB subgain[i] = s_max( round_fx_o( L_shl_o( L_tmp, add( n, n_max + 1 ), &Overflow ), &Overflow ), 3277 /*0.1f Q15*/ ); /* Q15 */ #else subgain[i] = s_max( round_fx( L_shl( L_tmp, add( n, n_max + 1 ) ) ), 3277 /*0.1f Q15*/ ); /* Q15 */ #endif + move16(); } return; @@ -2867,33 +5136,223 @@ static void QuantizeSHBsubgains_fx( move16(); /*Q15 */ } - FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) - { - subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; - move16(); - } + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + + hBWE_TD->idxSubGains = idxSubGain; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + } + } + + return; +} + + +/*============================================================*/ +/* FUNCTION : static void QuantizeSHBsubgains_ivas_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Quantize super highband temporal gains */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) extl : extension layer Q0 */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16[])subgains :super highband temporal gains Q15 */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ + +static void QuantizeSHBsubgains_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 subgains[], /* i/o: super highband temporal gains Q15 */ + const Word16 extl /* i : extension layer */ +) +{ + Word16 i, idxSubGain; + Word16 Unit_weights10[NUM_SHB_SUBFR]; + Word16 exp, frac; + Word32 L_tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( extl, WB_TBE ) ) + { + set16_fx( Unit_weights10, 32767, NUM_SHB_SUBFR / 4 ); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + IF( EQ_16( subgains[i], 0 ) ) + { + subgains[i + NUM_SHB_SUBFR / 4] = -18432; + move16(); /* (-72) in Q8 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); /* move16(); */ + /*exp = -1 - exp; */ + exp = sub( -1, exp ); + L_tmp = Mpy_32_16( exp, frac, 24660 ); /* Q13 ; 20.0 * log10(2) in Q12*/ + subgains[i + NUM_SHB_SUBFR / 4] = round_fx( L_shl( L_tmp, 11 ) ); /* Q8 */ + move16(); + } + } + idxSubGain = closest_centroid_lc_fx( subgains + NUM_SHB_SUBFR / 4, HBCB_SubGain5bit_fx, 1 << NUM_BITS_SHB_SUBGAINS ); + Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, subgains, NUM_SHB_SUBFR / 4 ); + + push_indice( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + L_tmp = L_mult( subgains[i], 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + move16(); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16(); /*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR / 2 - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i / 2]; + move16(); + } + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + IF( EQ_16( subgains[i], 0 ) ) + { + subgains[i] = -12288; + move16(); /* (-3) in Q12 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = -1 - exp; */ + exp = sub( -1, exp ); + + L_tmp = Mpy_32_16( exp, frac, 9864 ); /*move32(); // Q16 ; log10(2) in Q15 */ + subgains[i] = round_fx( L_shl( L_tmp, 12 ) ); /*Q12 */ + move16(); + } + } + + idxSubGain = vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + L_tmp = L_mult( subgains[i], 27213 ); /* *3.321928 in Q13 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + move16(); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16(); /*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->idxSubGains = idxSubGain; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * Quant_shb_ener_sf_fx_fx() + * + * Quantize SHB subframe energies + *-------------------------------------------------------------------*/ + +static void Quant_shb_ener_sf_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies */ + Word16 Q_ener ) +{ + Word16 idxSubEner_fx; + Word16 temp_shb_ener_sf_fx; + Word16 exp /*, exp2*/, frac; + Word32 L_tmp1, L_tmp; + Word32 sum; + Word16 tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* shb_ener_sf_fx[0] = log10(0.003125*shb_ener_sf[0:319]); */ + sum = *shb_ener_sf_Q31; /* L_tmp in Q_ener = (2*Q_shb+1) */ - hBWE_TD->idxSubGains = idxSubGain; - move16(); - IF( NE_16( st_fx->codec_mode, MODE2 ) ) - { - push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); - } - } + exp = norm_l( sum ); + frac = Log2_norm_lc( L_shl( sum, exp ) ); + exp = sub( 30, add( exp, Q_ener ) ); /* 30-(exp+Q_ener ) */ + L_tmp1 = Mpy_32_16( exp, frac, 617 ); /* 2466=LOG10(2) in Q11, so answer Ltmp in Q12 */ + + tmp = round_fx( L_shl( L_tmp1, 30 - 14 ) ); /* tmp in Q12 */ + + temp_shb_ener_sf_fx = 0; + move16(); + idxSubEner_fx = usquant_fx( tmp, &temp_shb_ener_sf_fx, 0, 86, shl( 1, NUM_BITS_SHB_ENER_SF ) ); /* 86 = 0.042f in Q11 = Qin-1 */ + /* o: temp_shb_ener_sf_fx in Q12 */ + + /* shb_ener_sf_fx[0] = pow(10.0, temp_shb_ener_sf_fx ); */ + /* = pow(2, 3.321928*temp_shb_ener_sf_fx) */ + L_tmp = L_mult( temp_shb_ener_sf_fx, 27213 ); /* 3.321928 in Q13 -> L_tmp in Q12+Q13+1 = Q26 */ + L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ + L_tmp = Pow2( 14, frac ); + *shb_ener_sf_Q31 = L_shl( L_tmp, exp - 14 + Q_ener ); /* In Q_ener */ + hBWE_TD->idx_shb_fr_gain = idxSubEner_fx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice_fx( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF ); + } return; } /*-------------------------------------------------------------------* - * Quant_shb_ener_sf_fx_fx() + * Quant_shb_ener_sf_ivas_fx() * * Quantize SHB subframe energies *-------------------------------------------------------------------*/ -static void Quant_shb_ener_sf_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ - Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies */ +static void Quant_shb_ener_sf_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies Q_ener */ Word16 Q_ener ) { Word16 idxSubEner_fx; @@ -2906,6 +5365,7 @@ static void Quant_shb_ener_sf_fx( /* shb_ener_sf_fx[0] = log10(0.003125*shb_ener_sf[0:319]); */ sum = *shb_ener_sf_Q31; /* L_tmp in Q_ener = (2*Q_shb+1) */ + move32(); exp = norm_l( sum ); frac = Log2_norm_lc( L_shl( sum, exp ) ); @@ -2925,13 +5385,14 @@ static void Quant_shb_ener_sf_fx( L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ L_tmp = Pow2( 14, frac ); - *shb_ener_sf_Q31 = L_shl( L_tmp, exp - 14 + Q_ener ); /* In Q_ener */ + *shb_ener_sf_Q31 = L_shl( L_tmp, add( sub( exp, 14 ), Q_ener ) ); /* In Q_ener */ + move32(); hBWE_TD->idx_shb_fr_gain = idxSubEner_fx; move16(); IF( NE_16( st_fx->codec_mode, MODE2 ) ) { - push_indice_fx( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF ); + push_indice( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF ); } return; } @@ -2967,6 +5428,43 @@ static void Quant_shb_res_gshape_fx( } } + +/*-------------------------------------------------------------------* + * Quant_shb_res_gshape_ivas_fx() + * + * Quantize SHB gain shapes in residual domain + *-------------------------------------------------------------------*/ + +static void Quant_shb_res_gshape_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ +) +{ + Word16 i, idxSubGain_fx[NB_SUBFR16k]; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; + + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + idxSubGain_fx[i] = usquant_fx( shb_res_gshape_fx[i], + &shb_res_gshape_fx[i], + 2048 /*0.125f Q14*/, /*2048 = 0.125 in Q14 */ + 1024 /*0.125f Q13*/, /*1024 = 0.125 in Q13 */ + shl( 1, NUM_BITS_SHB_RES_GS ) ); + move16(); + + IF( st->codec_mode == MODE2 ) + { + hBWE_TD->idx_res_gs[i] = idxSubGain_fx[i]; + move16(); + } + ELSE + { + push_indice( st->hBstr, IND_SHB_RES_GS1 + i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS ); + } + } +} + + /*==========================================================================*/ /* FUNCTION : static void QuantizeSHBframegain_fx() */ /*--------------------------------------------------------------------------*/ @@ -2986,6 +5484,7 @@ static void Quant_shb_res_gshape_fx( /*--------------------------------------------------------------------------*/ /* */ /*==========================================================================*/ + static void QuantizeSHBframegain_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word32 *GainFrame, /* i/o: Gain Q18 */ @@ -3077,44 +5576,284 @@ static void QuantizeSHBframegain_fx( /* Q_GainFrame = (float) pow(10.0, Q_GainFrame ); */ /* i: Q_GainFrame in Q16 */ - L_tmp = Mult_32_16( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ - L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ + L_tmp = Mult_32_16( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ + L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + Q_GainFrame = Pow2( 30, frac ); + exp = sub( exp, 30 ); + Q_GainFrame = L_shl( Q_GainFrame, exp + 18 ); /* Q18 */ + + hBWE_TD->idxFrameGain = idxFrameGain; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice_fx( st_fx->hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + *rf_gainFrame_ind = idxFrameGain; + } + + IF( EQ_16( st_fx->rf_mode, 1 ) ){ + /*Currently intended for SWB only. Modify for WB is needed later!*/ + IF( EQ_16( hRF->rf_frame_type, RF_NELP ) ){ + *rf_gainFrame_ind = idxFrameGain; /* NELP Frame uses full 5 bits */ +} +ELSE /*RF_ALLPRED, RF_GENPRED, RF_NOPRED modes*/ +{ + IF( *GainFrame <= 327680 /*1.25 in Q18*/ ) /* [0 to 1.25] range --> 0.5*/ + { + *rf_gainFrame_ind = 0; + } + ELSE IF( *GainFrame <= 786432 /*3 in Q18*/ ) /* (1.25 to 3] --> 2 */ + { + *rf_gainFrame_ind = 1; + } + ELSE IF( *GainFrame <= 1572864 /*6 in Q18*/ ) /* (3 to 6] --> 4 */ + { + *rf_gainFrame_ind = 2; + } + ELSE /* (6 to Inf) --> 8 */ + { + *rf_gainFrame_ind = 3; + } +} +} + +*GainFrame = Q_GainFrame; +move32(); /* Q18 */ + +return; +} + + +/*==========================================================================*/ +/* FUNCTION : static void QuantizeSHBframegain_ivas_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : QQuantize super highband frame gain */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 extl i : extension layer */ +/* Word32 extl_brate i : extension layer bitrate */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word32 *GainFrame i/o: Gain Q18 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ + +static void QuantizeSHBframegain_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word32 *GainFrame, /* i/o: Gain Q18 */ + const Word16 extl, /* i : extension layer */ + Word32 extl_brate, /* i : extension layer bitrate */ + Word16 *rf_gainFrame_ind, + const Word16 flag_conservative /* i : flag to indicate more conservative gain quantization */ +) +{ + Word16 idxFrameGain; + Word32 Q_GainFrame; + Word16 Unit_weights1 = 1; + Word16 exp, frac, tmp; + Word32 L_tmp; + Word32 GainFrameLog; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + move16(); + + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( extl, WB_TBE ) ) + { + determine_gain_weights_fx( GainFrame, &( Unit_weights1 ), 1 ); + IF( EQ_32( extl_brate, WB_TBE_0k35 ) ) + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain_LBR_WB, &idxFrameGain, + &Q_GainFrame, SHBCB_FrameGain16_fx ); + test(); + IF( GT_32( Q_GainFrame, L_shl( Mult_32_16( *GainFrame, 17367 ), 1 ) ) && idxFrameGain > 0 ) /* 1.06 = +0.5 dB */ + { + idxFrameGain--; + Q_GainFrame = L_add( SHBCB_FrameGain16_fx[idxFrameGain], 0 ); /* Q18 */ + } + + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->gFrame_WB = idxFrameGain; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain_LBR_WB ); + } + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); + } + } + ELSE + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain, &idxFrameGain, &Q_GainFrame, + SHBCB_FrameGain64_fx ); + + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain ); + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); + } + } + } + ELSE + { + IF( *GainFrame == 0 ) + { + GainFrameLog = -196608; /* Q16 */ + move32(); + } + ELSE + { + exp = norm_l( *GainFrame ); + frac = Log2_norm_lc( L_shl( *GainFrame, exp ) ); + exp = ( 30 - exp - 18 ); + GainFrameLog = Mpy_32_16( exp, frac, 9864 ); + /*GainFrameLog= round_fx(L_shl(L_tmp,12)); //Q12 */ + } + + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* idxFrameGain = (int16_t) usquant( GainFrameLog, &Q_GainFrame, SHB_GAIN_QLOW_1k75, SHB_GAIN_QDELTA_1k75, 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ); */ + exp = norm_s( SHB_GAIN_QDELTA_1k75_FX_15 ); + tmp = div_s( shl( 1, sub( 14, exp ) ), SHB_GAIN_QDELTA_1k75_FX_15 ); + L_tmp = Mpy_32_16_1( L_sub( GainFrameLog, SHB_GAIN_QLOW_1k75_FX ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl( 1, sub( 14, exp ) ) ), sub( 15, exp ) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ) - 1 ) ) + { + idxFrameGain = ( 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ) - 1; + move16(); + } + ELSE + { + if ( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + L_tmp = SHB_GAIN_QLOW_1k75_FX; + move32(); + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_1k75_FX_15 ); + } + ELSE + { + /* idxFrameGain = (int16_t) usquant( GainFrameLog, &Q_GainFrame, SHB_GAIN_QLOW, SHB_GAIN_QDELTA, 1 << NUM_BITS_SHB_FRAMEGAIN ); */ + exp = norm_s( SHB_GAIN_QDELTA_FX_15 ); + tmp = div_s( shl( 1, sub( 14, exp ) ), SHB_GAIN_QDELTA_FX_15 ); + L_tmp = Mpy_32_16_1( L_sub( GainFrameLog, SHB_GAIN_QLOW_FX_16 ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl( 1, sub( 14, exp ) ) ), sub( 15, exp ) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1 ) ) + { + idxFrameGain = ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1; + move16(); + } + ELSE + { + if ( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + L_tmp = SHB_GAIN_QLOW_FX_16; + move32(); + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_FX_15 ); + } + + + WHILE( GT_32( Q_GainFrame, L_add( GainFrameLog, 4866 ) ) && + idxFrameGain != 0 ) + { + idxFrameGain = sub( idxFrameGain, 1 ); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + test(); + test(); + IF( flag_conservative && GT_32( Q_GainFrame, L_add( GainFrameLog, Mpy_32_16_1( SHB_GAIN_QDELTA_FX_16, 13435 /* 0.41 in Q15 */ ) ) ) && idxFrameGain != 0 ) + { + /* be more conservative in the quantization process -> prevent energy overshoot */ + idxFrameGain = sub( idxFrameGain, 1 ); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + /* Q_GainFrame = (float) pow(10.0, Q_GainFrame ); */ + /* i: Q_GainFrame in Q16 */ + L_tmp = Mpy_32_16_1( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ + L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ frac = L_Extract_lc( L_tmp, &exp ); Q_GainFrame = Pow2( 30, frac ); exp = sub( exp, 30 ); Q_GainFrame = L_shl( Q_GainFrame, exp + 18 ); /* Q18 */ - hBWE_TD->idxFrameGain = idxFrameGain; - move16(); - IF( NE_16( st_fx->codec_mode, MODE2 ) ) + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) { - push_indice_fx( st_fx->hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + st_fx->hBWE_TD->idxFrameGain = idxFrameGain; + move16(); + } + ELSE + { + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN_1k75 ); + } + ELSE + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + } + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); } - *rf_gainFrame_ind = idxFrameGain; } IF( EQ_16( st_fx->rf_mode, 1 ) ){ /*Currently intended for SWB only. Modify for WB is needed later!*/ IF( EQ_16( hRF->rf_frame_type, RF_NELP ) ){ *rf_gainFrame_ind = idxFrameGain; /* NELP Frame uses full 5 bits */ + move16(); } ELSE /*RF_ALLPRED, RF_GENPRED, RF_NOPRED modes*/ { - IF( *GainFrame <= 327680 /*1.25 in Q18*/ ) /* [0 to 1.25] range --> 0.5*/ + IF( LE_32( *GainFrame, 327680 /*1.25 in Q18*/ ) ) /* [0 to 1.25] range --> 0.5*/ { *rf_gainFrame_ind = 0; + move16(); } - ELSE IF( *GainFrame <= 786432 /*3 in Q18*/ ) /* (1.25 to 3] --> 2 */ + ELSE IF( LE_32( *GainFrame, 786432 /*3 in Q18*/ ) ) /* (1.25 to 3] --> 2 */ { *rf_gainFrame_ind = 1; + move16(); } - ELSE IF( *GainFrame <= 1572864 /*6 in Q18*/ ) /* (3 to 6] --> 4 */ + ELSE IF( LE_32( *GainFrame, 1572864 /*6 in Q18*/ ) ) /* (3 to 6] --> 4 */ { *rf_gainFrame_ind = 2; + move16(); } ELSE /* (6 to Inf) --> 8 */ { *rf_gainFrame_ind = 3; + move16(); } } } @@ -3227,7 +5966,6 @@ static void singlevectortest_gain_fx( Word16 k, interNum, flag; Word32 meanU, meanQ; Word16 least[4]; - Word32 L_tmp; interNum = 4; move16(); @@ -3237,7 +5975,6 @@ static void singlevectortest_gain_fx( meanU = sum32_fx( inp, dimen ); /* Q18 */ Copy32( codebook + dimen * least[0], recon, dimen ); - L_tmp = L_shl( Mult_32_16( meanU, 18022 ), 1 ); /* Q18 */ index[0] = least[0]; move16(); flag = 0; @@ -3247,7 +5984,8 @@ static void singlevectortest_gain_fx( IF( flag == 0 ) { meanQ = sum32_fx( codebook + dimen * least[k], dimen ); /* Q18 */ - IF( LE_32( meanQ, L_tmp ) ) + /* if ( meanQ <= 1.1 * meanU ) */ + IF( LE_32( Mpy_32_16_1( meanQ, 29789 /* 1/1.1 in Q15*/ ), meanU ) ) { flag = 1; move16(); @@ -3361,18 +6099,20 @@ static void return_M_Least_fx_GainFrame( /*-------------------------------------------------------------------* * Quant_lower_LSF_fx() *-------------------------------------------------------------------*/ + static void Quant_lower_LSF_fx( - const Word16 lsf[], /* i : Input LSFs Q15 */ - Word16 lsf_q[], /* o : Quantized LSFs Q15 */ - Word16 lsf_idx[] /* o : Quantized LSFs indices */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + Word16 lsf_idx[] /* o : Quantized LSFs indices */ ) { Word16 i; - lsf_idx[0] = (Word16) squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size[0] ); + lsf_idx[0] = squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size[0] ); + move16(); FOR( i = 1; i < NUM_Q_LSF; i++ ) { - lsf_idx[i] = (Word16) squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size[i] ); + lsf_idx[i] = squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size[i] ); move16(); lsf_q[i] = add( lsf_q[i - 1], lsf_q[i] ); move16(); @@ -3385,19 +6125,19 @@ static void Quant_lower_LSF_fx( /*-------------------------------------------------------------------* * Quant_mirror_point_fx() *-------------------------------------------------------------------*/ + static Word16 Quant_mirror_point_fx( - const Word16 lsf[], /* i : Input LSFs */ - const Word16 lsf_q[], - Word16 *m /* o : Mirror point */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + const Word16 lsf_q[], /* i : Quantized LSFs Q15 */ + Word16 *m /* o : Mirror point Q15 */ ) { Word16 m_diff; Word16 m_idx; - m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 ); + m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 /* 0.5f in Q15 */ ); - m_idx = (Word16) squant_fx( m_diff, m, mirror_point_q_cb_fx, - MIRROR_POINT_Q_CB_SIZE ); /*move16(); */ + m_idx = squant_fx( m_diff, m, mirror_point_q_cb_fx, MIRROR_POINT_Q_CB_SIZE ); *m = add( lsf_q[NUM_Q_LSF - 1], *m ); move16(); @@ -3405,6 +6145,7 @@ static Word16 Quant_mirror_point_fx( return m_idx; } + /*-------------------------------------------------------------------* * Find_LSF_grid() * @@ -3412,9 +6153,9 @@ static Word16 Quant_mirror_point_fx( *-------------------------------------------------------------------*/ static Word16 Find_LSF_grid_fx( - const Word16 lsf[], /* i : Input LSFs */ - Word16 lsf_q[], /* o : Quantized LSFs */ - const Word16 m /* i : Mirror point */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + const Word16 m /* i : Mirror point Q15 */ ) { Word16 lsf_map[NUM_MAP_LSF]; @@ -3427,6 +6168,7 @@ static Word16 Find_LSF_grid_fx( Word16 I_best = 0; Word16 i, j; Word16 scale; + move16(); Word16 tmp, exp, tmp1; Word32 L_tmp; @@ -3577,59 +6319,443 @@ static void gainFrSmooth_En_fx( Encoder_State *st_fx, move16(); } - test(); - test(); - IF( NE_16( st_fx->last_extl, SWB_TBE ) && NE_16( st_fx->last_extl, FB_TBE ) && LT_16( lsp_spacing, 262 ) ) + test(); + test(); + IF( NE_16( st_fx->last_extl, SWB_TBE ) && NE_16( st_fx->last_extl, FB_TBE ) && LT_16( lsp_spacing, 262 ) ) + { + hBWE_TD->lsp_shb_spacing_fx[0] = lsp_spacing; + move16(); + hBWE_TD->lsp_shb_spacing_fx[1] = lsp_spacing; + move16(); + hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + hBWE_TD->prev_frGainAtten = 1; + move16(); + set16_fx( hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER ); + } + + /* Estimate the moving average LSP spacing */ + tempQ31 = L_mult( hBWE_TD->lsp_shb_spacing_fx[0], 3277 ); /* 0.1f */ + tempQ31 = L_mac( tempQ31, hBWE_TD->lsp_shb_spacing_fx[1], 6553 ); /* 0.2f */ + tempQ31 = L_mac( tempQ31, hBWE_TD->lsp_shb_spacing_fx[2], 9830 ); /* 0.3f */ + *MA_lsp_shb_spacing = mac_r( tempQ31, lsp_spacing, 13107 ); /* 0.4f */ + + hBWE_TD->lsp_shb_spacing_fx[0] = hBWE_TD->lsp_shb_spacing_fx[1]; + move16(); + hBWE_TD->lsp_shb_spacing_fx[1] = hBWE_TD->lsp_shb_spacing_fx[2]; + move16(); + hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + + test(); + test(); + test(); + IF( ( LT_16( lsp_spacing, 262 ) && ( LT_16( *MA_lsp_shb_spacing, 164 ) || EQ_16( hBWE_TD->prev_frGainAtten, 1 ) ) ) || LE_16( lsp_spacing, 105 ) ) + { + *frGainAttenuate = 1; + move16(); + + IF( NE_32( st_fx->total_brate, ACELP_24k40 ) ) + { + Copy( shb_frame_fx, temp_shb_frame, L_FRAME16k + L_SHB_LAHEAD ); + fir_fx( temp_shb_frame, lpc_shb_fx, shb_frame_fx, hBWE_TD->shb_inv_filt_mem_fx, L_FRAME16k + L_SHB_LAHEAD, LPC_SHB_ORDER, 1, 3 ); + } + ELSE + { + set16_fx( hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER ); + } + + test(); + IF( LT_32( lsp_slow_evol_rate, 2147484l /*0.001f Q31*/ ) && LT_32( lsp_fast_evol_rate, 2147484l /*0.001f Q31*/ ) ) + { + *frGainSmoothEn = 1; + move16(); + } + } +} + +#define MAXINT32 MAX_32 +static void first_VQstages_fx( + const Word16 *const *cb, + Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ + Word16 *levels, /* i : number of levels in each stage */ + Word16 stagesVQ, /* i : number of stages */ + Word16 w[], /* i : weights */ + Word16 N, /* i : vector dimension */ + Word16 max_inner, /* i : maximum number of swaps in inner loop */ + Word16 indices_VQstage[] ) +{ + Word16 resid_buf[2 * LSFMBEST * M], *resid[2]; + Word32 dist_buf[2 * LSFMBEST], *dist[2], en; + Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; + Word16 Tmp[M], *pTmp, cs; + Word16 *pTmp_short, idx_buf[2 * LSFMBEST * MAX_VQ_STAGES], parents[LSFMBEST], counter = 0, j, + m, s, c, c2, p_max, *indices[2]; + move16(); + Word16 maxC = LSFMBEST; + move16(); +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); +#endif + + /*float dd[16];*/ + const Word16 *cb_stage, *cbp; + + /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ + indices[0] = idx_buf; + move16(); + indices[1] = idx_buf + maxC * stagesVQ; + move16(); + resid[0] = resid_buf; + move16(); + resid[1] = resid_buf + maxC * N; + move16(); + dist[0] = dist_buf; + move16(); + dist[1] = dist_buf + maxC; + move16(); + + set16_fx( idx_buf, 0, ( const Word16 )( 2 * stagesVQ * maxC ) ); + set16_fx( parents, 0, maxC ); + + /* Set up inital distance vector */ + L_tmp = L_deposit_l( 0 ); + FOR( j = 0; j < N; j++ ) + { +#ifdef BASOP_NOGLOB + L_tmp1 = L_shl_o( L_mult0( u[j], w[j] ), 7, &Overflow ); /*x2.56 + Q8 + Q7 */ +#else /* BASOP_NOGLOB */ + L_tmp1 = L_shl( L_mult0( u[j], w[j] ), 7 ); /*x2.56 + Q8 + Q7 */ +#endif /* BASOP_NOGLOB */ + L_tmp1 = Mult_32_16( L_tmp1, u[j] ); /*x2.56 + Q15 + x2.56 -Q15 */ + L_tmp = L_add( L_tmp, L_tmp1 ); /*Q0 + x2.56 +x2.56 */ + } + set32_fx( dist[1], L_tmp, maxC ); + + /* Set up initial error (residual) vectors */ + pTmp = resid[1]; + move16(); + FOR( c = 0; c < maxC; c++ ) + { + Copy( u, pTmp, N ); + pTmp += N; + } + + /*----------------------------------------------------------------* + * LSF quantization + *----------------------------------------------------------------*/ + + /* Loop over all stages */ + m = 1; + move16(); + FOR( s = 0; s < stagesVQ; s++ ) + { + /* set codebook pointer to point to first stage */ + cbp = cb[s]; + + /* save pointer to the beginning of the current stage */ + cb_stage = cbp; + + /* swap pointers to parent and current nodes */ + pTmp_short = indices[0]; + indices[0] = indices[1]; + move16(); + indices[1] = pTmp_short; + move16(); + + pTmp = resid[0]; + resid[0] = resid[1]; + move16(); + resid[1] = pTmp; + move16(); + + pTmp32 = dist[0]; + dist[0] = dist[1]; + move32(); + dist[1] = pTmp32; + move32(); + + /* p_max points to maximum distortion node (worst of best) */ + p_max = 0; + move16(); + + /* set distortions to a large value */ + set32_fx( dist[1], MAXINT32, maxC ); + + FOR( j = 0; j < levels[s]; j++ ) + { + /* compute weighted codebook element and its energy */ + FOR( c2 = 0; c2 < N; c2++ ) + { + Tmp[c2] = shl( mult( w[c2], cbp[c2] ), 2 ); /* Q8 + x2.56 -Q15 +Q2 */ + move16(); + } + + en = L_mult( cbp[0], Tmp[0] ); + + FOR( c2 = 1; c2 < N; c2++ ) + { + en = L_mac( en, cbp[c2], Tmp[c2] ); /*x2.56 + x2.56 + Q-5 +Q1 */ + } + cbp += N; + move16(); + + /* iterate over all parent nodes */ + FOR( c = 0; c < m; c++ ) + { + pTmp = &resid[0][c * N]; + move16(); + L_tmp = L_mult( pTmp[0], Tmp[0] ); + FOR( c2 = 1; c2 < N; c2++ ) + { + L_tmp = L_mac( L_tmp, pTmp[c2], Tmp[c2] ); /* */ + } + + L_tmp = L_add( dist[0][c], L_sub( en, L_shl( L_tmp, 1 ) ) ); + + IF( LE_32( L_tmp, dist[1][p_max] ) ) + { + /* replace worst */ + dist[1][p_max] = L_tmp; + move32(); + indices[1][p_max * stagesVQ + s] = j; + move16(); + parents[p_max] = c; + move16(); + + /* limit number of times inner loop is entered */ + IF( LT_16( counter, max_inner ) ) + { + counter = add( counter, 1 ); + IF( LT_16( counter, max_inner ) ) + { + /* find new worst */ + p_max = maximum_32_fx( dist[1], maxC, &f_tmp ); + } + ELSE + { + /* find minimum distortion */ + p_max = minimum_32_fx( dist[1], maxC, &f_tmp ); + } + } + } + } + } + + /*------------------------------------------------------------* + * Compute error vectors for each node + *------------------------------------------------------------*/ + cs = 0; + move16(); + FOR( c = 0; c < maxC; c++ ) + { + /* subtract codebook entry from the residual vector of the parent node */ + pTmp = resid[1] + c * N; + move16(); + Copy( resid[0] + parents[c] * N, pTmp, N ); + Vr_subt( pTmp, cb_stage + ( indices[1][cs + s] ) * N, pTmp, N ); + + /* get indices that were used for parent node */ + Copy( indices[0] + parents[c] * stagesVQ, indices[1] + cs, s ); + cs = add( cs, stagesVQ ); + } + + m = maxC; + move16(); + } + + Copy( indices[1], indices_VQstage, maxC * stagesVQ ); + + return; +} + +static Word16 dotp_loc( + const Word16 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n /* i : vector length */ +) +{ + Word16 i; + Word32 suma; + Word16 guarded_bits = find_guarded_bits_fx( n ); + suma = L_shr( Mpy_32_16_1( y[0], x[0] ), guarded_bits ); + + FOR( i = 1; i < n; i++ ) + { + suma = L_add( suma, L_shr( Mpy_32_16_1( y[i], x[i] ), guarded_bits ) ); + } + suma = L_shl_sat( suma, guarded_bits ); + + return extract_h( suma ); +} + +static void LVQQuant_BWE_LSF_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs Q15 */ + Word16 Q_lsfs_fx[], /* o : quanitzed LSFs Q15 */ + Word16 nbits ) +{ + + Word16 lsf_fx[LPC_SHB_ORDER]; + Word16 lsf_q_fx[LPC_SHB_ORDER]; + Word16 i, c2, dim1 = 6; + move16(); + Word16 levels[1], numbits_VQ; + Word16 c2_fx_temp; + + Word16 w_fx[8] = { 5120, 5120, 2048, 2048, 2048, 1024, 1024, 1024 }; /* Q10 */ + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 cand_fx[LPC_SHB_ORDER], quant_fx[LPC_SHB_ORDER], e_fx[2], ftmp_fx; + const Word16 *cb_stage_fx; + Word16 indices_firstVQ[LSFMBEST]; + + Word16 Idx, idx_lead, idx_scale; + UWord32 LVQ_index; + Word16 dd_fx[LATTICE_DIM], cv_out_fx[LATTICE_DIM]; + Word16 bits_lvq, predictor_bits, empty_bits; + + empty_bits = 0; /* This is the difference to 21 bits, if we want lower number of bits */ + move16(); + nbits = sub( nbits, empty_bits ); /* THIS IS TO SIMULATE DIFFERENT NUMBER OF input BITS - should be removed */ + move16(); + c2 = sub( NUM_BITS_SHB_MSLVQ, nbits ); + move16(); + numbits_VQ = config_LSF_BWE[c2 * 3]; + move16(); + levels[0] = config_LSF_BWE[c2 * 3 + 1]; + move16(); + predictor_bits = config_LSF_BWE[c2 * 3 + 2]; + move16(); + IF( LT_16( nbits, 19 ) ) + { + cb_stage_fx = cb_LSF_BWE_fx[1]; + } + ELSE + { + cb_stage_fx = cb_LSF_BWE_fx[0]; + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + /* remove mean */ + v_sub_16( lsf_fx, SHB_LSF_mean_fx, Q_lsfs_fx, LPC_SHB_ORDER ); + + /* 6D multi-stage 6bit coding */ + first_VQstages_fx( &cb_stage_fx, Q_lsfs_fx, levels, 1, w_fx, dim1, 3000, indices_firstVQ ); + + + /* 8D MSLVQ coding */ + bits_lvq = sub( sub( nbits, numbits_VQ ), predictor_bits ); + Copy( SHB_LSF_mean_fx, cand_fx, LPC_SHB_ORDER ); + + Idx = indices_firstVQ[0]; + move16(); + + v_add_16( cand_fx, cb_stage_fx + Idx * dim1, cand_fx, dim1 ); + + /* LVQ quantization */ + Copy( cand_fx, quant_fx, LPC_SHB_ORDER ); + + v_sub_16( lsf_fx, cand_fx, dd_fx, LATTICE_DIM ); + + mslvq_ivas_16( dd_fx, quant_fx, cv_out_fx, &idx_lead, &idx_scale, w_fx, 0, ( nbits < 19 ), bits_lvq ); + + IF( EQ_16( idx_scale, -1 ) ) + { + set16_fx( cv_out_fx, 0, LATTICE_DIM ); + } + v_add_16( cand_fx, quant_fx, cand_fx, LATTICE_DIM ); + + /* arrange the LSF candidate vector prior to selection to an ascending order*/ + v_sort( cand_fx, 0, LPC_SHB_ORDER - 1 ); + + set16_fx( Q_lsfs_fx, 0, LPC_SHB_ORDER ); + /* mvr2r( mean_lsf, Q_lsfs, LPC_SHB_ORDER ); */ + + v_add_16( Q_lsfs_fx, cb_stage_fx + Idx * dim1, Q_lsfs_fx, dim1 ); + + /* write VQ indexes */ + push_indice( hBstr, IND_SHB_LSF, Idx, numbits_VQ ); + + /* write MSLVQ index */ + LVQ_index = index_lvq_SHB_fx( idx_lead, idx_scale, bits_lvq, cv_out_fx, ( nbits < 19 ) ); + + IF( GT_16( bits_lvq, 15 ) ) + { + push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) & ( 0xffff >> 1 ) ), 15 ); + push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) >> 15 ) & ( 0xffff >> 1 ), bits_lvq - 15 ); + } + ELSE + { + push_indice( hBstr, IND_SHB_LSF, (Word16) LVQ_index, bits_lvq ); + } + + v_add_16( Q_lsfs_fx, quant_fx, lsf_q_fx, LATTICE_DIM ); /* quantized mean removed data for first 8 dim*/ + + /* predict last 2 components */ + IF( predictor_bits == 0 ) + { + lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, LastCoefPred_0bit_fx, LATTICE_DIM ); + move16(); + lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_0bit_fx[LATTICE_DIM + 1], LATTICE_DIM ); + move16(); + } + ELSE + { + v_sub_16( &lsf_fx[LATTICE_DIM], &SHB_LSF_mean_fx[LATTICE_DIM], &lsf_q_fx[LATTICE_DIM], 2 ); + + FOR( i = 0; i < 2; i++ ) + { + ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM]; + + e_fx[i] = mult( ftmp_fx, ftmp_fx ); + move16(); + + ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i + LATTICE_DIM + 1], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM + 1]; + + e_fx[i] = add_sat( e_fx[i], mult( ftmp_fx, ftmp_fx ) ); + move16(); + } + + c2_fx_temp = minimum_fx( e_fx, 2, &ftmp_fx ); + + lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp], LATTICE_DIM ); + move16(); + + lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp + LATTICE_DIM + 1], LATTICE_DIM ); + move16(); + + push_indice( hBstr, IND_SHB_LSF, c2, 1 ); + } + + if ( empty_bits > 0 ) { - hBWE_TD->lsp_shb_spacing_fx[0] = lsp_spacing; - move16(); - hBWE_TD->lsp_shb_spacing_fx[1] = lsp_spacing; - move16(); - hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; - move16(); - hBWE_TD->prev_frGainAtten = 1; - move16(); - set16_fx( hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER ); + push_indice( hBstr, IND_SHB_LSF, 0, empty_bits ); } - /* Estimate the moving average LSP spacing */ - tempQ31 = L_mult( hBWE_TD->lsp_shb_spacing_fx[0], 3277 ); /* 0.1f */ - tempQ31 = L_mac( tempQ31, hBWE_TD->lsp_shb_spacing_fx[1], 6553 ); /* 0.2f */ - tempQ31 = L_mac( tempQ31, hBWE_TD->lsp_shb_spacing_fx[2], 9830 ); /* 0.3f */ - *MA_lsp_shb_spacing = mac_r( tempQ31, lsp_spacing, 13107 ); /* 0.4f */ + v_add_16( SHB_LSF_mean_fx, lsf_q_fx, lsf_q_fx, LPC_SHB_ORDER ); - hBWE_TD->lsp_shb_spacing_fx[0] = hBWE_TD->lsp_shb_spacing_fx[1]; - move16(); - hBWE_TD->lsp_shb_spacing_fx[1] = hBWE_TD->lsp_shb_spacing_fx[2]; - move16(); - hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; - move16(); + v_sort( lsf_q_fx, 0, LPC_SHB_ORDER - 1 ); - test(); - test(); - test(); - IF( ( LT_16( lsp_spacing, 262 ) && ( LT_16( *MA_lsp_shb_spacing, 164 ) || EQ_16( hBWE_TD->prev_frGainAtten, 1 ) ) ) || LE_16( lsp_spacing, 105 ) ) + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) { - *frGainAttenuate = 1; + Q_lsfs_fx[i] = sub_sat( 16384 /* 0.5f in Q15 */, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); move16(); - - IF( NE_32( st_fx->total_brate, ACELP_24k40 ) ) - { - Copy( shb_frame_fx, temp_shb_frame, L_FRAME16k + L_SHB_LAHEAD ); - fir_fx( temp_shb_frame, lpc_shb_fx, shb_frame_fx, hBWE_TD->shb_inv_filt_mem_fx, L_FRAME16k + L_SHB_LAHEAD, LPC_SHB_ORDER, 1, 3 ); - } - ELSE - { - set16_fx( hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER ); - } - - test(); - IF( LT_32( lsp_slow_evol_rate, 2147484l /*0.001f Q31*/ ) && LT_32( lsp_fast_evol_rate, 2147484l /*0.001f Q31*/ ) ) - { - *frGainSmoothEn = 1; - move16(); - } } + + return; } /*-------------------------------------------------------------------* @@ -3702,6 +6828,84 @@ static void Quant_BWE_LSF_fx( return; } + +static void Quant_BWE_LSF_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + const Word16 codec_mode, /* i : codec mode */ + const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs Q15 */ + Word16 Q_lsfs_fx[], /* o : quanitzed LSFs Q15 */ + const Word32 extl_brate /* i : extension layer bit rate */ +) +{ + Word16 lsf_fx[LPC_SHB_ORDER]; + Word16 lsf_q_fx[LPC_SHB_ORDER]; + Word16 lsf_idx[NUM_Q_LSF]; + Word16 i; + Word16 m_idx; + Word16 m_fx; + Word16 grid_idx; + + IF( EQ_32( extl_brate, SWB_TBE_1k75 ) ) + { + LVQQuant_BWE_LSF_fx( hBstr, lsf_shb_fx, Q_lsfs_fx, NUM_BITS_SHB_MSLVQ ); + } + ELSE + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + Quant_lower_LSF_fx( lsf_fx, lsf_q_fx, lsf_idx ); + + FOR( i = 0; i < NUM_Q_LSF; i++ ) + { + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->lsf_idx[i] = lsf_idx[i]; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_LSF, lsf_idx[i], lsf_q_num_bits[i] ); + } + } + + m_idx = Quant_mirror_point_fx( lsf_fx, lsf_q_fx, &m_fx ); + + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->m_idx = m_idx; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_MIRROR, m_idx, MIRROR_POINT_BITS ); + } + + grid_idx = Find_LSF_grid_fx( lsf_fx, lsf_q_fx, m_fx ); + + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->grid_idx = grid_idx; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_GRID, grid_idx, NUM_LSF_GRID_BITS ); + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + Q_lsfs_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + } + + return; +} + /*-------------------------------------------------------------------* * fb_tbe_enc() * @@ -3830,6 +7034,168 @@ void fb_tbe_enc_fx( return; } + +void fb_tbe_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : input speech at 48 kHz sample rate Q0 */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part Q_fb_exc */ + Word16 Q_fb_exc ) +{ + Word16 ratio; + Word16 tmp_vec[L_FRAME48k]; + Word16 idxGain; + Word16 input_fhb_new[L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS )]; + Word16 input_fhb[L_FRAME48k]; + Word16 Sample_Delay_HP; + Word32 fb_exc_energy, temp2; + Word32 L_tmp; + Word16 tmp, tmp1, tmp2, exp, exp2, exp_norm; + Word16 s_max_value, exp_temp, i; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + s_max_value = 0; + move16(); + FOR( i = 0; i < L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ); i++ ) + { + s_max_value = s_max( s_max_value, abs_s( new_input[i - NS2SA( 48000, DELAY_FIR_RESAMPL_NS )] ) ); + } + exp_temp = norm_s( s_max_value ); + if ( s_max_value == 0 ) + { + exp_temp = 15; + move16(); + } + + Copy_Scale_sig( new_input - NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), input_fhb_new, L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), exp_temp ); + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + elliptic_bpf_48k_generic_fx( input_fhb_new, &exp_temp, tmp_vec, hBWE_TD->elliptic_bpf_2_48k_mem_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, full_band_bpf_2_fx ); + } + ELSE + { + elliptic_bpf_48k_generic_fx( input_fhb_new + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), &exp_temp, tmp_vec, hBWE_TD->elliptic_bpf_2_48k_mem_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, full_band_bpf_2_fx ); + } + + test(); + IF( GT_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_SCE ) ) + { + + IF( EQ_16( st->L_frame, L_FRAME ) ) + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ) - L_FRAME48k / 2; + move16(); + } + ELSE + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ) - L_FRAME48k / 2; + move16(); + } + } + ELSE + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2; + move16(); + } + + IF( NE_16( st->last_extl, FB_TBE ) ) + { + set16_fx( hBWE_TD->old_input_fhb_fx, 0, Sample_Delay_HP ); + hBWE_TD->old_input_fhb_fx_Q = 0; + move16(); + set16_fx( tmp_vec, 0, L_FRAME16k ); + } + Copy_Scale_sig( hBWE_TD->old_input_fhb_fx, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP, sub( exp_temp, hBWE_TD->old_input_fhb_fx_Q ) ); + hBWE_TD->old_input_fhb_fx_Q = exp_temp; + move16(); + Copy( hBWE_TD->old_input_fhb_fx, input_fhb, Sample_Delay_HP ); + Copy( tmp_vec, input_fhb + Sample_Delay_HP, sub( L_FRAME48k, Sample_Delay_HP ) ); + Copy( tmp_vec + L_FRAME48k - Sample_Delay_HP, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP ); + temp2 = sum2_fx_mod( input_fhb, L_FRAME48k / 2 ); /* Q(2*Q_input_fhb-8) */ +#ifdef BASOP_NOGLOB + temp2 = L_add_o( temp2, L_shl_o( hBWE_TD->prev_fb_energy_fx, sub( sub( add( exp_temp, exp_temp ), 8 ), hBWE_TD->prev_fb_energy_fx_Q ), &Overflow ), &Overflow ); /* Q(2*(exp_temp)-8) */ +#else + temp2 = L_add( temp2, L_shl( hBWE_TD->prev_fb_energy_fx, sub( sub( add( exp_temp, exp_temp ), 8 ), hBWE_TD->prev_fb_energy_fx_Q ) ) ); /* Q(2*(exp_temp)-8) */ +#endif + hBWE_TD->prev_fb_energy_fx = sum2_fx_mod( input_fhb + L_FRAME48k / 2, L_FRAME48k / 2 ); /*Q(2*(Q_input_fhb)-8) */ + move32(); + hBWE_TD->prev_fb_energy_fx_Q = sub( add( exp_temp, exp_temp ), 8 ); + move16(); + fb_exc_energy = sum2_fx_mod( fb_exc, L_FRAME16k ); /* Q(2*Q_fb_exc-8) */ + + /*ratio = (float) sqrt( temp2 / fb_exc_energy );*/ + L_tmp = L_max( 1, temp2 ); /*Q(2*(exp_temp)-8)*/ + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 31, sub( add( exp_temp, exp_temp ), 8 ) ), exp ); /* (L_tmp in Q(2*(exp_temp)-8))*/ + + exp2 = norm_l( fb_exc_energy ); + tmp2 = extract_h( L_shl( fb_exc_energy, exp2 ) ); + tmp1 = sub( add( Q_fb_exc, Q_fb_exc ), 8 ); /*1 - 9*/ + exp2 = sub( sub( 31, tmp1 ), exp2 ); /* (L_tmp in Q(2*(exp_temp)-8))*/ + + exp = sub( exp2, exp ); /* Denormalize and substract */ + IF( GT_16( tmp2, tmp ) ) + { + tmp2 = shr( tmp2, 1 ); + exp = add( exp, 1 ); + } + IF( 0 != tmp ) + { + tmp = div_s( tmp2, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp)*/ +#ifdef BASOP_NOGLOB + L_tmp = L_max( L_shr_o( L_tmp, sub( 31, exp ), &Overflow ), 0x1 ); /* Q0 */ +#else + L_tmp = L_max( L_shr( L_tmp, sub( 31, exp ) ), 0x1 ); /* Q0 */ +#endif + } + ELSE + { + L_tmp = 0; + move32(); + } + + /* idxGain = (short)( log2_f ((float)ratio) + 0.5f ); + idxGain = max( 0, min(15,idxGain) ); */ + ratio = 0; + move16(); + IF( GE_32( L_tmp, 32768 ) ) + { + idxGain = 15; + move16(); + } + ELSE + { + ratio = extract_l( L_tmp ); + exp_norm = norm_s( ratio ); + idxGain = sub( 14, exp_norm ); + idxGain = s_max( 0, idxGain ); + } + test(); + test(); + IF( GT_16( idxGain, 2 ) && LT_16( idxGain, 15 ) && GT_16( ratio, add( shl( 2, sub( idxGain, 1 ) ), shl( 2, sub( idxGain, 2 ) ) ) ) ) + { + idxGain = add( idxGain, 1 ); + } + + /* ratio = (float)(1 << idxGain);*/ + IF( EQ_16( st->codec_mode, MODE2 ) ) + { + hBWE_TD->idxGain = idxGain; + move16(); + } + ELSE + { + push_indice( st->hBstr, IND_FB_SLOPE, idxGain, 4 ); + } + + return; +} void tbe_write_bitstream_fx( Encoder_State *st_fx /* i/o: encoder state structure */ ) @@ -3953,3 +7319,41 @@ void TBEreset_enc_fx( } } } + +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * InitSWBencBufferStates() + * + * Initialize SWB buffer states + *-------------------------------------------------------------------*/ + +void InitSWBencBufferStates_fx( + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + Word16 *shb_speech /* o : SHB target signal (6-14kHz) at 16kHz */ +) +{ + IF( shb_speech != NULL ) + { + set16_fx( shb_speech, 0, L_FRAME16k ); + } + + set16_fx( hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( hBWE_TD->mem_shb_res_fx, 0, MAX_LEN_MA_FILTER ); + set16_fx( hBWE_TD->old_EnvSHBres_fx, 0, L_FRAME4k ); + hBWE_TD->old_mean_EnvSHBres_fx = 0; + hBWE_TD->prev_enr_EnvSHBres_fx = 1; /*1.0f in Q0*/ + hBWE_TD->prev_enr_EnvSHBres_e = 31; + hBWE_TD->prev_shb_env_tilt_fx = 0; + hBWE_TD->prev_pow_exc16kWhtnd_fx = 32767; /*1.0f in Q15*/ + hBWE_TD->prev_mix_factor_fx = 32767; /*1.0f in Q15*/ + hBWE_TD->prev_Env_error_fx = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + return; +} +#endif diff --git a/lib_enc/tcx_ltp_enc_fx.c b/lib_enc/tcx_ltp_enc_fx.c index 32e44d84ad3f7ece511bd302c3113f4fec47200d..6d9ae393b09cb8486681e549d6b2d72491dd7518 100644 --- a/lib_enc/tcx_ltp_enc_fx.c +++ b/lib_enc/tcx_ltp_enc_fx.c @@ -274,6 +274,226 @@ static void tcx_ltp_pitch_search( } } +static void tcx_ltp_pitch_search_ivas_fx( + const Word16 pitch_ol, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *index, + Word16 *norm_corr, + const Word16 len, + const Word16 *wsp, // Qx + const Word16 pitmin, + const Word16 pitfr1, + const Word16 pitfr2, + const Word16 pitmax, + const Word16 pitres, + const Word16 check_border_case, + Word16 *border_case ) +{ + Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp; + Word32 cor_max, cor[256], *pt_cor, temp; + Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + delta = 16; + move16(); + if ( EQ_16( pitres, 6 ) ) + { + delta = 8; + move16(); + } + + t0_min = sub( pitch_ol, shr( delta, 1 ) ); + t0_max = sub( add( t0_min, delta ), 1 ); + + IF( LT_16( t0_min, pitmin ) ) + { + t0_min = pitmin; + move16(); + t0_max = sub( add( t0_min, delta ), 1 ); + } + + IF( GT_16( t0_max, pitmax ) ) + { + t0_max = pitmax; + move16(); + t0_min = add( sub( t0_max, delta ), 1 ); + } + + t_min = sub( t0_min, L_INTERPOL1 ); + t_max = add( t0_max, L_INTERPOL1 ); + + /* normalize wsp */ + s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) ); + s_wsp = sub( s_wsp, 4 ); + FOR( t = negate( t_max ); t < len; t++ ) + { + wsp2[t + t_max] = shl( wsp[t], s_wsp ); // Q(x + s_wsp) + move16(); + } + wsp = wsp2 + t_max; + + pt_cor = cor; + + FOR( t = t_min; t <= t_max; t++ ) + { + *pt_cor = dot( wsp, wsp - t, len ); // 2*(x + s_wsp) + pt_cor++; + } + + pt_cor = cor + L_INTERPOL1; + cor_max = L_add( *pt_cor++, 0 ); + t1 = t0_min; + move16(); + + FOR( t = add( t0_min, 1 ); t <= t0_max; t++ ) + { + IF( GT_32( *pt_cor, cor_max ) ) + { + cor_max = *pt_cor; + move32(); + t1 = t; + move16(); + } + pt_cor++; + } + + temp = dot( wsp, wsp, len ); // 2*(x + s_wsp) + s = norm_l( temp ); + temp_e = negate( s ); + temp_m = extract_h( L_shl( temp, s ) ); // Q(2*(x + s_wsp) - temp_e - 16) + + temp = dot( wsp - t1, wsp - t1, len ); // 2*(x + s_wsp) + s = norm_l( temp ); + temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) ); // //Q = 4*(x + s_wsp) + s - temp_e - 47 + temp_e = sub( temp_e, s ); + + temp_m = Sqrt16( temp_m, &temp_e ); + + if ( temp_m == 0 ) + { + temp_m = 1; + move16(); + } + s = sub( norm_l( cor_max ), 1 ); + temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m ); + temp_e = sub( negate( s ), temp_e ); + +#ifdef BASOP_NOGLOB + *norm_corr = shl_o( temp_m, temp_e, &Overflow ); +#else + BASOP_SATURATE_WARNING_OFF_EVS + *norm_corr = shl( temp_m, temp_e ); + BASOP_SATURATE_WARNING_ON_EVS +#endif + + test(); + IF( check_border_case && EQ_16( t1, t0_min ) ) + { + Word32 tmpCor; + FOR( t = t1 - L_INTERPOL1; t < t1; t++ ) + { + tmpCor = dot( wsp, wsp - t, len ); + IF( GT_32( tmpCor, cor_max ) ) + { + *border_case = 1; + move16(); + break; + } + } + } + + IF( GE_16( t1, pitfr1 ) ) + { + *pitch_int = t1; + move16(); + *pitch_fr = 0; + move16(); + + *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ), + sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) ); + + return; + } + + /*------------------------------------------------------------------* + * Search fractional pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + pt_cor = cor + sub( L_INTERPOL1, t0_min ); + t0 = t1; + move16(); + + step = 1; + move16(); + if ( GE_16( t0, pitfr2 ) ) + { + step = 2; + move16(); + } + fraction = step; + move16(); + + IF( EQ_16( t0, t0_min ) ) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + } + ELSE /* Process negative fractions */ + { + t0 = sub( t0, 1 ); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + + FOR( i = add( fraction, step ); i < pitres; i += step ) + { + temp = interpolate_corr( &pt_cor[t0], i, pitres ); + + IF( GT_32( temp, cor_max ) ) + { + cor_max = L_add( temp, 0 ); + fraction = i; + move16(); + } + } + } + + FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */ + { + temp = interpolate_corr( &pt_cor[t1], i, pitres ); + + IF( GT_32( temp, cor_max ) ) + { + cor_max = L_add( temp, 0 ); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pitch_int = t0; + move16(); + *pitch_fr = fraction; + move16(); + + IF( GE_16( t0, pitfr2 ) ) + { + *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ), + sub( pitfr2, pitmin ), pitres ) ), + shr( fraction, 1 ) ); + } + ELSE + { + *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction ); + } +} + static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index ) { @@ -340,6 +560,71 @@ static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_fra move16(); } +static void tcx_ltp_find_gain_ivas_fx( Word16 *speech /*Qx*/, Word16 *pred_speech /*Qx*/, Word16 L_frame, Word16 *gain, Word16 *gain_index ) +{ + Word32 corr, ener; + Word16 i, g, s1, s2, tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + s1 = sub( getScaleFactor16( speech, L_frame ), 4 ); + s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 ); + + /* Find gain */ + corr = L_deposit_l( 0 ); + ener = L_deposit_l( 1 ); + + FOR( i = 0; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + tmp = shl_sat( pred_speech[i], s2 ); // Qx + s2 + corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp ); // 2*Qx + s1 + s2 + ener = L_mac0_sat( ener, tmp, tmp ); // 2*(Qx+s2) +#else + tmp = shl( pred_speech[i], s2 ); + corr = L_mac0( corr, shl( speech[i], s1 ), tmp ); + ener = L_mac0( ener, tmp, tmp ); +#endif + } + + s1 = sub( 1, add( s1, s2 ) ); + s2 = sub( 1, shl( s2, 1 ) ); + + tmp = sub( norm_l( corr ), 1 ); + corr = L_shl( corr, tmp ); + s1 = sub( s1, tmp ); + + tmp = norm_l( ener ); + ener = L_shl( ener, tmp ); + s2 = sub( s2, tmp ); + +#ifdef BASOP_NOGLOB + g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) ); +#else + g = divide1616( round_fx( corr ), round_fx( ener ) ); +#endif + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + g = shl_o( g, sub( s1, s2 ), &Overflow ); /*Q15*/ +#else /* BASOP_NOGLOB */ + g = shl( g, sub( s1, s2 ) ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + /* Quantize gain */ + g = shr_sat( sub_sat( g /*Q15*/, 0x1000 ), 13 ); // Q0 + g = s_max( g, -1 ); + + *gain_index = g; + move16(); + + /* Dequantize gain */ + *gain = imult1616( add( g, 1 ), 0x1400 ); /*Q15*/ + move16(); +} + void tcx_ltp_encode_fx( Word16 tcxltp_on, Word8 tcxOnly, Word16 tcxMode, @@ -646,3 +931,421 @@ void tcx_ltp_encode_fx( Word16 tcxltp_on, *norm_corr_past = norm_corr; move16(); } + +void tcx_ltp_encode_ivas_fx( + Encoder_State *st, + const Word16 tcxMode, + const Word16 L_frame, + Word16 *speech_fx, + Word16 *speech_ltp_fx, + const Word16 *wsp_fx, + const Word16 Top[], + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *A_fx, + const Word16 disable_ltp, + const Word16 element_mode ) +{ + Word16 i, n; + Word16 ltp_on, tcxOnly, L_subfr, SideInfoOnly, delta; + Word16 si_gain_fx; // Q15 + Word16 alpha_fx, step_fx; // Q15 + Word16 norm_corr_fx; // Q15 + Word16 border_case; + Word16 tempFlatness_fx; // Q7 + Word16 maxEnergyChange_fx; // Q7 + Word16 pred_speech_fx[L_FRAME_PLUS]; // Qspeech + Word16 buf_zir_fx[M + L_FRAME_PLUS / 4], *zir_fx; // Qspeech + Word16 Aest_fx[M + 1]; + Word16 exponent; + Word16 sqr; + Flag Overflow = 0; + move32(); + + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + tcxOnly = st->tcxonly; + move16(); + L_subfr = L_SUBFR; + move16(); + SideInfoOnly = extract_l( GT_32( st->sr_core, 25600 ) ); + move16(); + + /* Reset memory if past frame is acelp */ + IF( st->last_core == ACELP_CORE ) + { + hTcxEnc->tcxltp_pitch_int_past = L_frame; + move16(); + hTcxEnc->tcxltp_pitch_int_past = 0; + move16(); + hTcxEnc->tcxltp_pitch_int_past = 0; + move16(); + } + + /* By default, LTP is off */ + ltp_param[0] = 0; + move16(); + norm_corr_fx = 0; + move16(); + border_case = 0; + move16(); + + test(); + IF( hTcxEnc->tcxltp || SideInfoOnly ) + { + Word16 nPrevSubblocks; + Word8 isTCX10 = 0; + move16(); + + /* Find pitch lag */ + IF( EQ_16( st->pit_res_max, 6 ) ) + { + delta = 8; + move16(); + } + ELSE + { + delta = 16; + move16(); + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IF( LT_16( abs_s( sub( Top[0], Top[1] ) ), shr( delta, 1 ) ) ) + { + /* estimates are close enough and stable, take the artihmetic mean as estimate */ + tcx_ltp_pitch_search_ivas_fx( shr( add( Top[0], Top[1] ), 1 ), &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case ); + } + ELSE + { + /* pitch jumps between half frames, calc ltp for both estimates, choose the better one */ + Word16 pitch_int_2[2]; + Word16 pitch_fr_2[2]; + Word16 norm_corr_2_fx[2]; + Word16 pit_param_2[2]; + + FOR( i = 0; i < 2; i++ ) + { + tcx_ltp_pitch_search_ivas_fx( Top[i], &pitch_int_2[i], &pitch_fr_2[i], &pit_param_2[i], &norm_corr_2_fx[i], L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case ); + } + + IF( GT_16( norm_corr_2_fx[1], norm_corr_2_fx[0] ) ) + { + i = 1; + move16(); + } + ELSE + { + i = 0; + move16(); + } + + hTcxEnc->tcxltp_pitch_int = pitch_int_2[i]; + move16(); + hTcxEnc->tcxltp_pitch_fr = pitch_fr_2[i]; + move16(); + ltp_param[1] = pit_param_2[i]; + move16(); + norm_corr_fx = norm_corr_2_fx[i]; + } + } + ELSE + { + Word16 tmp; + IF( GT_16( element_mode, EVS_MONO ) ) + { + tmp = 1; + } + ELSE + { + tmp = 0; + } + move16(); + tcx_ltp_pitch_search_ivas_fx( Top[1], &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, tmp, &border_case ); + } + + if ( border_case ) + { + norm_corr_fx = 0; + move16(); + } + + // nPrevSubblocks = ( 1 + min( NSUBBLOCKS, (int16_t) ceil( 0.5f + NSUBBLOCKS * ( 1.0f * ( hTcxEnc->tcxltp_pitch_int ) / L_frame ) ) ) ); + nPrevSubblocks = extract_h( L_add( L_mac( 32768, NSUBBLOCKS, div_s( hTcxEnc->tcxltp_pitch_int, L_frame ) ), 65535 ) ); // 0.5f Q16 //65535( 1.Q16 - 1) added to get the ceil + nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 ); + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + tempFlatness_fx = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( st->hTranDet, NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q7 + maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10, + NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q7 + } + ELSE + { + tempFlatness_fx = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( st->hTranDet, NSUBBLOCKS, nPrevSubblocks ); + maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10, + NSUBBLOCKS, nPrevSubblocks ); + } + + /* Switch LTP on */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( + ( tcxOnly == 0 ) && + EQ_16( tcxMode, TCX_20 ) && + GT_16( mult( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x2000 ) && /*mult returns Q15*/ + LT_16( tempFlatness_fx, 448 /*3.5f Q7*/ ) ) || + ( EQ_16( tcxOnly, 1 ) && + EQ_16( tcxMode, TCX_10 ) && + GT_16( s_max( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x4000 ) && + LT_16( maxEnergyChange_fx, 448 /*3.5f Q7*/ ) ) || + ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */ + EQ_16( tcxOnly, 1 ) && + GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) && + L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr_fx, 1 ) ) ), hTcxEnc->tcxltp_pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */ + ) || + ( EQ_16( tcxOnly, 1 ) && + EQ_16( tcxMode, TCX_20 ) && + GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) && + ( LT_16( tempFlatness_fx, 768 /*6.0f Q7*/ ) || + ( LT_16( tempFlatness_fx, 896 /*7.0f Q7*/ ) && + LT_16( maxEnergyChange_fx, 2816 /*22.0f Q7*/ ) ) ) ) ) + { + IF( disable_ltp == 0 ) + { + ltp_param[0] = 1; + move16(); + } + } + + /* hysteresis for stable ltp prediction */ + ltp_on = 0; + move16(); + + test(); + test(); + test(); + test(); + test(); + + exponent = 15; + move16(); + sqr = Sqrt16( hTcxEnc->tcxltp_on_mem, &exponent ); + move16(); + sqr = shl_sat( sqr, exponent ); + IF( ( EQ_16( tcxOnly, 1 ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) && ( GT_16( ( mult( sqr, mult( ( norm_corr_fx ), 29492 ) ) ), 14419 ) && ( LT_16( tempFlatness_fx, 768 ) || ( LT_16( tempFlatness_fx, 896 ) && LT_16( maxEnergyChange_fx, 2816 ) ) ) ) ) ) // 0.9f Q15, 6.0f Q7, 7.0f Q7, 22.0f Q7 + { + ltp_on = 1; + move16(); + } + + test(); + IF( EQ_16( tcxOnly, 1 ) && EQ_16( ltp_param[0], 1 ) ) + { + /* increase ltp counter */ + hTcxEnc->tcxltp_on_mem = s_min( 5, add( hTcxEnc->tcxltp_on_mem, 1 ) ); + move16(); + } + ELSE IF( EQ_16( ltp_on, 1 ) ) + { + /* hysteresis takes effect, decrease counter */ + hTcxEnc->tcxltp_on_mem = s_max( 0, sub( hTcxEnc->tcxltp_on_mem, 1 ) ); + move16(); + ltp_param[0] = ltp_on; + move16(); + } + ELSE + { + /* no ltp in this frame, reset counter */ + hTcxEnc->tcxltp_on_mem = 0; + move16(); + } + } + + /* Find predicted signal */ + predict_signal( speech_fx, pred_speech_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, L_frame ); + + /* Find gain */ + tcx_ltp_find_gain_ivas_fx( speech_fx, pred_speech_fx, L_frame, &hTcxEnc->tcxltp_gain, <p_param[2] ); + + IF( ltp_param[0] ) + { + /* Total number of bits for LTP */ + IF( add( ltp_param[2], 1 ) ) /* hTcxEnc->tcxltp_gain > 0 */ + { + *ltp_bits = 12; + move16(); + } + ELSE /* hTcxEnc->tcxltp_gain <= 0 -> turn off LTP */ + { + ltp_param[0] = 0; + move16(); + } + } + + IF( !ltp_param[0] ) + { + /* No LTP -> set everything to zero */ + hTcxEnc->tcxltp_pitch_int = L_frame; + move16(); + hTcxEnc->tcxltp_pitch_fr = 0; + move16(); + ltp_param[1] = 0; + move16(); + set16_fx( pred_speech_fx, 0, L_frame ); + hTcxEnc->tcxltp_gain = 0; + move16(); + ltp_param[2] = 0; + move16(); + + test(); + IF( hTcxEnc->tcxltp || SideInfoOnly ) + { + *ltp_bits = 1; + move16(); + } + ELSE + { + *ltp_bits = 0; + move16(); + } + } + + si_gain_fx = 0; + move16(); + + IF( SideInfoOnly ) + { + si_gain_fx = hTcxEnc->tcxltp_gain; + move16(); + hTcxEnc->tcxltp_gain = 0; + move16(); + } + + IF( speech_ltp_fx != NULL ) + { + test(); + IF( hTcxEnc->tcxltp_gain_past == 0 && hTcxEnc->tcxltp_gain == 0 ) + { + Copy( speech_fx, speech_ltp_fx, L_subfr ); + } + ELSE IF( hTcxEnc->tcxltp_gain_past == 0 ) + { + alpha_fx = 0; + move16(); + + step_fx = shl( 2, norm_s( L_subfr ) ); + IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 ) + { + step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ ); + } + + FOR( n = 0; n < L_subfr; n++ ) + { + speech_ltp_fx[n] = sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, mult_ro( alpha_fx, pred_speech_fx[n], &Overflow ), &Overflow ), &Overflow ); + move16(); + alpha_fx = add_sat( alpha_fx, step_fx ); + } + } + ELSE + { + IF( A_fx == NULL ) + { + tcx_ltp_get_lpc( speech_fx - L_frame, L_frame, Aest_fx, M ); + A_fx = Aest_fx; + } + + IF( hTcxEnc->tcxltp_gain > 0 ) + { + predict_signal( speech_fx - M, buf_zir_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, M ); + } + ELSE + { + set16_fx( buf_zir_fx, 0, M ); + } + + FOR( n = 0; n < M; n++ ) + { + buf_zir_fx[n] = add_sat( sub_sat( speech_ltp_fx[n - M], speech_fx[n - M] ), mult_r( hTcxEnc->tcxltp_gain, buf_zir_fx[n] ) ); + move16(); + } + + zir_fx = buf_zir_fx + M; + set16_fx( zir_fx, 0, L_subfr ); + + Syn_filt_s( 0, A_fx, M, zir_fx, zir_fx, L_subfr, buf_zir_fx, 0 ); + + alpha_fx = 0x7FFF; // 1.f Q15 + move16(); + step_fx = shl( 4, norm_s( L_subfr ) ); + IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 ) + { + step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ ); + } + + FOR( n = shr( L_subfr, 1 ); n < L_subfr; n++ ) + { + zir_fx[n] = mult_r( zir_fx[n], alpha_fx ); + move16(); + alpha_fx = sub( alpha_fx, step_fx ); + } + + FOR( n = 0; n < L_subfr; n++ ) + { + speech_ltp_fx[n] = add_o( sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, pred_speech_fx[n], &Overflow ), &Overflow ), zir_fx[n], &Overflow ); + move16(); + } + } + + test(); + IF( SideInfoOnly || hTcxEnc->tcxltp_gain == 0 ) + { + FOR( n = L_subfr; n < L_frame; n++ ) + { + speech_ltp_fx[n] = speech_fx[n]; + move16(); + } + } + ELSE + { + FOR( n = L_subfr; n < L_frame; n++ ) + { + speech_ltp_fx[n] = sub_o( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ), &Overflow ); + move16(); + } + } + } + + /* Update */ + hTcxEnc->tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int; + move16(); + hTcxEnc->tcxltp_pitch_fr_past = hTcxEnc->tcxltp_pitch_fr; + move16(); + hTcxEnc->tcxltp_gain_past = hTcxEnc->tcxltp_gain; + move16(); + + IF( SideInfoOnly ) + { + hTcxEnc->tcxltp_gain = si_gain_fx; + move16(); + } + + hTcxEnc->tcxltp_norm_corr_past = norm_corr_fx; + move16(); + + return; +} diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index 45ef64e1e344a815df2b0a6fb399c199f5fbf14b..f377bfb0db9644558725649d7739f19a4cd1ea50 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1506,125 +1506,111 @@ int16_t tcx_res_Q_spec( } +#ifdef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* - * ProcessIGF() + * ProcessIGF_ivas_fx() * * *---------------------------------------------------------------------*/ -#if 0 // Not Tested: Some dependency void ProcessIGF_ivas_fx( - IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ - Encoder_State *st, /**< in: Encoder state */ - Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ - Word16 *pMDCTSpectrum_e, - Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ - Word16 *pPowerSpectrum_e, - Word16 isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ - Word16 isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ - Word16 frameno /**< in: flag indicating index of current subframe */ + Encoder_State *st, /* i : Encoder state */ + Word32 *pMDCTSpectrum, /* i : MDCT spectrum (*q_spectrum) */ + const Word32 *pITFMDCTSpectrum, /* i : MDCT spectrum fir ITF */ + Word16 *q_spectrum, /* i/o: Q of spectrum */ + Word32 *pPowerSpectrum, /* i : MDCT^2 + MDST^2 spectrum, or estimate (*q_powerSpec) */ + Word16 *q_powerSpec, /* i/o: Q of power spectrum */ + const Word16 isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const Word16 frameno, /* i : flag indicating index of current subframe */ + const Word16 sp_aud_decision0, /* i : first stage switching decision */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ ) { - Word16 igfGridIdx; - Word16 isIndepFlag; - Word16 bsBits; - Word16 bsStart; - BSTR_ENC_HANDLE hBstr = st->hBstr; + Word16 igfGridIdx, isIndepFlag, bsBits, pBsStart, curr_order; + Word16 predictionGain; + Word16 A[ITF_MAX_FILTER_ORDER + 1]; + Word16 q_A; + IGF_ENC_INSTANCE_HANDLE hIGFEnc = st->hIGFEnc; + BSTR_ENC_HANDLE hBstr = st->hBstr; isIndepFlag = 1; move16(); test(); - IF( isTransition && isTCX20 ) + IF( st->last_core == ACELP_CORE && isTCX20 ) { igfGridIdx = IGF_GRID_LB_TRAN; move16(); } + ELSE IF( isTCX20 ) + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } ELSE { - IF( isTCX20 ) - { - igfGridIdx = IGF_GRID_LB_NORM; - move16(); - } - ELSE + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + if ( EQ_16( frameno, 1 ) ) { - /* It is short block */ - igfGridIdx = IGF_GRID_LB_SHORT; + isIndepFlag = 0; move16(); - if ( EQ_16( frameno, 1 ) ) - { - isIndepFlag = 0; - move16(); - } } } + IGFSaveSpectrumForITF_ivas_fx( hIGFEnc, igfGridIdx, pITFMDCTSpectrum ); - IGFEncApplyMono_fx( hInstance, /**< in: instance handle of IGF Encoder */ - igfGridIdx, /**< in: IGF grid index */ - st, /**< in: Encoder state */ - pMDCTSpectrum, /**< in: MDCT spectrum */ - *pMDCTSpectrum_e, - pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ - *pPowerSpectrum_e, - isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - isTNSActive, /**< in: flag indicating if the TNS is active */ - ( st->last_core == ACELP_CORE ) ); - { - const Word32 tns_predictionGain = st->hIGFEnc->tns_predictionGain; - const Word16 startLine = st->hIGFEnc->infoStartLine; - const Word16 endLine = st->hIGFEnc->infoStopLine; - const Word16 maxOrder = 8; - const Word32 *spec_before = st->hIGFEnc->spec_be_igf; - Word16 curr_order = 0; - Word16 A[ITF_MAX_FILTER_ORDER + 1]; - Word16 Q_A; - Word16 predictionGain = 0; - Word16 *flatteningTrigger = &( st->hIGFEnc->flatteningTrigger ); - - ITF_Detect_fx( spec_before, startLine, endLine, maxOrder, A, &Q_A, &predictionGain, &curr_order, shl( st->hIGFEnc->spec_be_igf_e, 1 ) ); - *flatteningTrigger = 0; - test(); - IF( LT_32( tns_predictionGain, 9646899l /*1.15 Q23*/ ) && - LT_16( predictionGain, 147 /*1.15 Q7*/ ) ) - { - *flatteningTrigger = 1; - } - } - - // IVAS_CODE_BITSTREAM - bsStart = hBstr->next_ind_fx; + IGFEncApplyMono_ivas_fx( st, igfGridIdx, pMDCTSpectrum, sub( Q31, *q_spectrum ), pPowerSpectrum, sub( Q31, *q_powerSpec ), isTCX20, st->hTcxEnc->fUseTns[frameno], sp_aud_decision0, vad_hover_flag ); + curr_order = 0; move16(); - hInstance->infoTotalBitsPerFrameWritten = 0; + predictionGain = 0; move16(); - IF( isTCX20 ) + q_A = 0; + move16(); + + ITF_Detect_ivas_fx( hIGFEnc->spec_be_igf, hIGFEnc->infoStartLine, hIGFEnc->infoStopLine, 8 /*maxOrder*/, A, &q_A, &predictionGain, &curr_order, sub( 31, hIGFEnc->spec_be_igf_e ) ); + + test(); + IF( LT_32( L_deposit_l( hIGFEnc->tns_predictionGain ), 9646899 /* 1.15 in Q23 */ ) && LT_32( L_deposit_l( predictionGain ), 9646899 /* 1.15 in Q23 */ ) ) { - IGFEncWriteBitstream_fx( hInstance, NULL, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + hIGFEnc->flatteningTrigger = 1; + move16(); } ELSE { - IGFEncWriteBitstream_fx( hInstance, st->hBstr, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + hIGFEnc->flatteningTrigger = 0; + move16(); } -#ifndef IVAS_CODE_BITSTREAM - bsBits = sub( hBstr->next_ind_fx, bsStart ); - IF( !isTCX20 ) + hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + + IF( isTCX20 ) { - IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot, hBstr->ind_list ); + IGFEncWriteBitstream_ivas_fx( hIGFEnc, NULL, &hIGFEnc->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); } -#else - PMT( "New bit stream implementation to be checked" ) - bsBits = sub( hBstr->next_ind_fx, bsStart ); - IF( !isTCX20 ) + ELSE { - IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot_fx, hBstr->ind_list_fx ); + pBsStart = hBstr->nb_ind_tot; + move16(); + + IGFEncWriteBitstream_ivas_fx( hIGFEnc, hBstr, &hIGFEnc->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + + bsBits = sub( hBstr->nb_ind_tot, pBsStart ); + IGFEncConcatenateBitstream( hIGFEnc, bsBits, hBstr ); } -#endif + return; } #endif + + +/*---------------------------------------------------------------------* + * ProcessIGF() + * + * + *---------------------------------------------------------------------*/ void ProcessIGF( Encoder_State *st, /* i : Encoder state */ float *pMDCTSpectrum, /* i : MDCT spectrum */ diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index b64532e69816a5374c4443de056e1758ce65b6bd..cef9e3066157fa14291decf36385bddde4f3525d 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -689,6 +689,225 @@ Word16 SQ_gain_fx( /* output: SQ gain */ return tmp16; } +Word16 SQ_gain_estimate_fx( /* output: SQ gain */ + Word32 x[], /* input: vector to quantize */ + Word16 x_e, /* input: exponent */ + Word16 nbitsSQ, /* input: number of bits targeted */ + Word16 lg, /* input: vector size (2048 max) */ + Word16 *gain_e ) /* output: SQ gain exponent */ +{ + Word16 i, iter, max_iter, lg_4, s, tmp16; + Word32 ener, tmp32; + Word32 target, fac, offset; + Word32 en[N_MAX / 4]; + Word32 tmp = 0, tmpp = 0; + move32(); + move32(); + + /* tmp = 0.5f * (float) log10( (float) lg / (float) NORM_MDCT_FACTOR ) + + 0.94f; lowest gain + expected value of the quantization noise energy per quadruple (log10(4/12)) in Q16*/ + /* tmpp = 0.5f * (float) log10( (float) lg / (float) NORM_MDCT_FACTOR ) * log2(10) in Q16 */ + SWITCH( lg ) + { + case 80: + tmp = 171876; + tmpp = -32768; + move32(); + move32(); + BREAK; + case 100: + tmp = 182424; + tmpp = -22219; + move32(); + move32(); + BREAK; + case 160: + tmp = 204644; + tmpp = 0; + move32(); + BREAK; + case 200: + tmp = 215192; + tmpp = 10549; + move32(); + move32(); + BREAK; + case 240: + tmp = 223812; + tmpp = 19168; + move32(); + move32(); + BREAK; + case 300: + tmp = 234361; + tmpp = 29717; + move32(); + move32(); + BREAK; + case 320: + tmp = 237412; + tmpp = 32768; + move32(); + move32(); + BREAK; + case 400: + tmp = 247960; + tmpp = 43317; + move32(); + move32(); + BREAK; + case 480: + tmp = 256580; + tmpp = 51936; + move32(); + move32(); + BREAK; + case 600: + tmp = 267128; + tmpp = 62485; + move32(); + move32(); + BREAK; + case 640: + tmp = 270180; + tmpp = 65536; + move32(); + move32(); + BREAK; + case 800: + tmp = 280728; + tmpp = 76085; + move32(); + move32(); + BREAK; + case 960: + tmp = 289348; + tmpp = 84704; + move32(); + move32(); + BREAK; + case 1200: + tmp = 299896; + tmpp = 95253; + move32(); + move32(); + BREAK; + case 1440: + tmp = 308516; + tmpp = 103872; + move32(); + move32(); + BREAK; + case 1800: + tmp = 319064; + tmpp = 114422; + move32(); + move32(); + BREAK; + case 2048: + tmp = 325167; + tmpp = 120523; + move32(); + move32(); + BREAK; + default: + assert( 0 ); + } + + lg_4 = shr( lg, 2 ); + + /* SNR of quadruples for unit step quantizer and lowest possible gain */ + FOR( i = 0; i < lg_4; i++ ) + { + /* normalization */ + s = 15; + move16(); + + tmp16 = norm_l( x[0] ); + if ( x[0] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[1] ); + if ( x[1] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[2] ); + if ( x[2] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[3] ); + if ( x[3] != 0 ) + s = s_min( s, tmp16 ); + + s = sub( s, 2 ); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l( 1 ); + + tmp16 = extract_h( L_shl( x[0], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[1], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[2], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[3], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + s = shl( sub( x_e, s ), 1 ); + + /* log */ + tmp32 = L_add_sat( BASOP_Util_Log2( ener ), L_shl_sat( L_deposit_l( s ), 25 ) ); /* log2, 6Q25 */ + en[i] = L_add_sat( L_shr( tmp32, 9 ), tmp ); /* 15Q16 */ + move32(); + x += 4; + } + + /* SQ scale: 4 bits / 6 dB per quadruple */ + target = L_mult( 0x3FC8, sub( nbitsSQ, shr( lg, 4 ) ) ); /* 0x3FC8 -> 0.15*log2(10) */ + fac = L_add( 4005789, 0 ); /* -> 18.4f*log2(10); */ + offset = 3997967; /*fac - fac / (float) ( 2 << max_iter )*/ + move32(); + max_iter = 8; + move16(); + /* find offset, resolution similar to SQ gain quantizer resolution (92dB range, 0.719db resolution) */ + FOR( iter = 0; iter < max_iter; iter++ ) + { + fac = L_shr( fac, 1 ); + offset = L_sub( offset, fac ); + ener = L_deposit_l( 0 ); + + FOR( i = 0; i < lg_4; i++ ) + { + tmp32 = L_sub( en[i], offset ); + + /* avoid SV with 1 bin of amp < 0.5f */ + IF( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 0.3*log2(10); */ + { + ener = L_add( ener, tmp32 ); + } + + /* if SNR is above target -> break and increase offset */ + IF( GT_32( ener, target ) ) + { + offset = L_add( offset, fac ); + BREAK; + } + } + } + + offset = L_sub( L_shr( offset, 1 ), tmpp ); /* tmpp -> minGainInv*log2(10) */ + *gain_e = add( extract_h( offset ), 1 ); + move16(); + offset = L_sub( L_and( offset, 0xFFFF ), 0x10000 ); + tmp16 = extract_h( BASOP_Util_InvLog2( L_shl( offset, 9 ) ) ); + + /* return gain */ + + return tmp16; +} + void tcx_scalar_quantization_fx( Word32 *x, /* i: input coefficients */ Word16 x_e, /* i: exponent */ @@ -779,11 +998,314 @@ Word16 tcx_scalar_quantization_rateloop_fx( Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) */ Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) */ Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ - const Word8 tcxonly, - CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ -) + const Word8 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ +) +{ + const Word16 iter_max = 4; + Word16 sqBits; + Word16 stopFlag; + Word8 ubfound, lbfound; + Word16 ub, ub_e, lb, lb_e; + Word16 shift, shiftInv; + Word16 iter; + Word16 sqGain, sqGain_e; + Word16 w_lb, w_ub; + const Word16 kDampen = 10; + Word16 old_stopFlag; + Word16 old_nEncoded; + Word16 old_sqBits; + Word16 mod_adjust0, mod_adjust1; + Word16 inv_target, inv_target_e; + const Word16 kMargin = 0x7AE1; /* 0.96 */ + const Word16 kMarginInv = 0x42AB; /* 1/0.96 (1Q14) */ + Word16 tmp, fac1, fac2; + Word32 tmp32; + Word16 lastnz; + + + /* Init */ + sqGain = *gain; + move16(); + sqGain_e = *gain_e; + move16(); + stopFlag = *stop; + move16(); + ubfound = 0; + move16(); + lbfound = 0; + move16(); + shift = 0x41DE; /* 10^(1/80), 1Q14 */ + move16(); + shiftInv = 0x78D7; /* 10^(-1/40) */ + move16(); + lb = lb_e = 0; + move16(); + ub = ub_e = 0; + move16(); + w_lb = 0; + move16(); + w_ub = 0; + move16(); + lastnz = *lastnz_out; + move16(); + old_stopFlag = stopFlag; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_sqBits = sqBits_in_noStop; + move16(); + + sqBits = sqBits_in; + move16(); + + mod_adjust0 = extract_l( L_shr( L_max( 0x10000, L_sub( 0x24CCD, L_mult( 0x0052, target ) ) ), 3 ) ); /* 2Q13 */ + mod_adjust1 = div_s( 0x2000, mod_adjust0 ); /* 0Q15 */ + + inv_target_e = 15; + move16(); + inv_target = Inv16( target, &inv_target_e ); + + fac1 = shl( mult( mult( kMarginInv, mod_adjust0 ), inv_target ), 1 ); /* 2Q13 */ + fac2 = mult( mult( kMargin, mod_adjust1 ), inv_target ); + + /* Loop */ + FOR( iter = 0; iter < iter_max; iter++ ) + { + IF( EQ_16( tcxRateLoopOpt, 2 ) ) + { + /* Ajust sqGain */ + IF( stopFlag != 0 ) + { + lbfound = 1; + move16(); + lb = sqGain; + move16(); + lb_e = sqGain_e; + move16(); + w_lb = add( sub( stopFlag, target ), kDampen ); + + IF( ubfound != 0 ) + { + /* common exponent for addition */ + sqGain_e = s_max( lb_e, ub_e ); + + /* multiply and add */ + tmp32 = L_shr( L_mult( lb, w_ub ), sub( sqGain_e, lb_e ) ); + tmp32 = L_add( tmp32, L_shr( L_mult( ub, w_lb ), sub( sqGain_e, ub_e ) ) ); + + /* convert to normalized 16 bit */ + tmp = norm_l( tmp32 ); +#ifdef BASOP_NOGLOB + sqGain = round_fx_sat( L_shl( tmp32, tmp ) ); +#else + sqGain = round_fx( L_shl( tmp32, tmp ) ); +#endif + sqGain_e = sub( sqGain_e, tmp ); + + /* divide */ + sqGain = BASOP_Util_Divide1616_Scale( sqGain, add( w_ub, w_lb ), &tmp ); + sqGain_e = add( sqGain_e, tmp ); + } + ELSE + { + tmp = round_fx( L_shl( L_mult( stopFlag, fac1 ), add( inv_target_e, 15 ) ) ); + sqGain = mult( sqGain, sub( tmp, sub( mod_adjust0, 0x2000 ) ) ); + sqGain = normalize16( sqGain, &sqGain_e ); + sqGain_e = add( sqGain_e, 2 ); + } + } + ELSE + { + ubfound = 1; + move16(); + ub = sqGain; + move16(); + ub_e = sqGain_e; + move16(); + w_ub = add( sub( target, sqBits ), kDampen ); + + IF( lbfound != 0 ) + { + /* common exponent for addition */ + sqGain_e = s_max( lb_e, ub_e ); + + /* multiply and add */ + tmp32 = L_shr( L_mult( lb, w_ub ), sub( sqGain_e, lb_e ) ); + tmp32 = L_add( tmp32, L_shr( L_mult( ub, w_lb ), sub( sqGain_e, ub_e ) ) ); + + /* convert to normalized 16 bit */ + tmp = norm_l( tmp32 ); +#ifdef BASOP_NOGLOB + sqGain = round_fx_sat( L_shl_sat( tmp32, tmp ) ); +#else + sqGain = round_fx( L_shl( tmp32, tmp ) ); +#endif + sqGain_e = sub( sqGain_e, tmp ); + + /* divide */ + sqGain = BASOP_Util_Divide1616_Scale( sqGain, add( w_ub, w_lb ), &tmp ); + sqGain_e = add( sqGain_e, tmp ); + } + ELSE + { + tmp = round_fx( L_shl( L_mult( sqBits, fac2 ), add( inv_target_e, 15 ) ) ); + sqGain = mult( sqGain, sub( tmp, add( mod_adjust1, (Word16) 0x8000 ) ) ); + sqGain = normalize16( sqGain, &sqGain_e ); + } + } + } + ELSE /* tcxRateLoopOpt != 2 */ + { + + /* Ajust sqGain */ + IF( stopFlag != 0 ) + { + lbfound = 1; + move16(); + lb = sqGain; + move16(); + lb_e = sqGain_e; + move16(); + + IF( ubfound != 0 ) + { + sqGain = mult( lb, ub ); + sqGain_e = add( lb_e, ub_e ); + sqGain = Sqrt16( sqGain, &sqGain_e ); + } + ELSE + { + shift = shl( mult( shift, shift ), 1 ); + shiftInv = mult( shiftInv, shiftInv ); + + sqGain = mult( sqGain, shift ); + sqGain = normalize16( sqGain, &sqGain_e ); + sqGain_e = add( sqGain_e, 1 ); + } + } + ELSE + { + ubfound = 1; + move16(); + ub = sqGain; + move16(); + ub_e = sqGain_e; + move16(); + + IF( lbfound != 0 ) + { + sqGain = mult( lb, ub ); + sqGain_e = add( lb_e, ub_e ); + sqGain = Sqrt16( sqGain, &sqGain_e ); + } + ELSE + { + sqGain = mult( sqGain, shiftInv ); + sqGain = normalize16( sqGain, &sqGain_e ); + + shift = shl( mult( shift, shift ), 1 ); + shiftInv = mult( shiftInv, shiftInv ); + } + } + } + + /* Quantize spectrum */ + tcx_scalar_quantization_fx( x, x_e, xq, L_frame, sqGain, sqGain_e, offset, memQuantZeros_fx, tcxonly ); + + /* Estimate bitrate */ + stopFlag = 1; + move16(); + if ( tcxRateLoopOpt > 0 ) + { + stopFlag = 0; + move16(); + } + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, + hm_cfg ); + + IF( tcxRateLoopOpt > 0 ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( GE_16( *nEncoded, old_nEncoded ) ) && ( GE_16( stopFlag, old_stopFlag ) ) ) || + ( ( GT_16( *nEncoded, old_nEncoded ) ) && ( ( stopFlag == 0 ) && ( old_stopFlag > 0 ) ) ) || + ( ( stopFlag == 0 ) && ( old_stopFlag == 0 ) ) ) + { + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_stopFlag = stopFlag; + move16(); + old_sqBits = sqBits; + move16(); + *lastnz_out = lastnz; + move16(); + } + } + } /* for ( iter=0 ; iter 0 ) + { + /* Quantize spectrum */ + tcx_scalar_quantization_fx( x, x_e, xq, L_frame, *gain, *gain_e, offset, memQuantZeros_fx, tcxonly ); + + /* Output */ + *nEncoded = old_nEncoded; + move16(); + sqBits = old_sqBits; + move16(); + *stop = old_stopFlag; + move16(); + } + ELSE + { + /* Output */ + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + *stop = stopFlag; + move16(); + *lastnz_out = lastnz; + move16(); + } + + + return sqBits; +} + +Word16 tcx_scalar_quantization_rateloop_ivas_fx( + Word32 *x, /* i : input coefficients Q = 31 - x_e*/ + Word16 x_e, /* i : exponent Q0*/ + Word16 *xq, /* o : quantized coefficients Q0*/ + Word16 L_frame, /* i : frame length Q0*/ + Word16 *gain, /* i/o: quantization gain Q = gaine_e*/ + Word16 *gain_e, /* i/o: gain exponent Q0*/ + Word16 offset, /* i : rounding offset (deadzone) Q0*/ + Word8 const *memQuantZeros_fx, /* i : coefficients to be set to 0 Q0*/ + Word16 *lastnz_out, /* i/o: last nonzero coeff index Q0*/ + Word16 target, /* i : target number of bits Q0*/ + Word16 *nEncoded, /* o : number of encoded coeff Q0*/ + Word16 *stop, /* i/o: stop param Q0*/ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) Q0*/ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) Q0*/ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word16 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg, /* i : configuration of the context-based harmonic model */ + const Word16 iter_max, + const Word16 element_mode ) { - const Word16 iter_max = 4; Word16 sqBits; Word16 stopFlag; Word8 ubfound, lbfound; @@ -793,19 +1315,83 @@ Word16 tcx_scalar_quantization_rateloop_fx( Word16 sqGain, sqGain_e; Word16 w_lb, w_ub; const Word16 kDampen = 10; + move16(); Word16 old_stopFlag; Word16 old_nEncoded; Word16 old_sqBits; Word16 mod_adjust0, mod_adjust1; Word16 inv_target, inv_target_e; - const Word16 kMargin = 0x7AE1; /* 0.96 */ + const Word16 kMargin = 0x7AE1; /* 0.96 */ + move16(); const Word16 kMarginInv = 0x42AB; /* 1/0.96 (1Q14) */ + move16(); Word16 tmp, fac1, fac2; Word32 tmp32; - Word16 lastnz; + Word16 lastnz, saturated, minSqGain = 0; + move16(); /* Init */ + saturated = 0; + move16(); + /* minSqGain = (float) sqrt( (float) NORM_MDCT_FACTOR / (float) L_frame ); in Q14*/ + SWITCH( L_frame ) + { + case 80: + minSqGain = 23170; + BREAK; + case 100: + minSqGain = 20724; + BREAK; + case 160: + minSqGain = 16384; + BREAK; + case 200: + minSqGain = 14654; + BREAK; + case 240: + minSqGain = 13377; + BREAK; + case 300: + minSqGain = 11965; + BREAK; + case 320: + minSqGain = 11585; + BREAK; + case 400: + minSqGain = 10362; + BREAK; + case 480: + minSqGain = 9459; + BREAK; + case 600: + minSqGain = 8461; + BREAK; + case 640: + minSqGain = 8192; + BREAK; + case 800: + minSqGain = 7327; + BREAK; + case 960: + minSqGain = 6689; + BREAK; + case 1200: + minSqGain = 5983; + BREAK; + case 1440: + minSqGain = 5461; + BREAK; + case 1800: + minSqGain = 4885; + BREAK; + case 2048: + minSqGain = 4579; + BREAK; + default: + assert( 0 ); + } + move16(); sqGain = *gain; move16(); sqGain_e = *gain_e; @@ -853,7 +1439,7 @@ Word16 tcx_scalar_quantization_rateloop_fx( /* Loop */ FOR( iter = 0; iter < iter_max; iter++ ) { - IF( EQ_16( tcxRateLoopOpt, 2 ) ) + IF( GE_16( tcxRateLoopOpt, 2 ) ) { /* Ajust sqGain */ IF( stopFlag != 0 ) @@ -865,7 +1451,8 @@ Word16 tcx_scalar_quantization_rateloop_fx( lb_e = sqGain_e; move16(); w_lb = add( sub( stopFlag, target ), kDampen ); - + saturated = 0; + move16(); IF( ubfound != 0 ) { /* common exponent for addition */ @@ -890,13 +1477,13 @@ Word16 tcx_scalar_quantization_rateloop_fx( } ELSE { - tmp = round_fx( L_shl( L_mult( stopFlag, fac1 ), add( inv_target_e, 15 ) ) ); + tmp = round_fx_sat( L_shl_sat( L_mult( stopFlag, fac1 ), add( inv_target_e, 15 ) ) ); sqGain = mult( sqGain, sub( tmp, sub( mod_adjust0, 0x2000 ) ) ); sqGain = normalize16( sqGain, &sqGain_e ); sqGain_e = add( sqGain_e, 2 ); } } - ELSE + ELSE IF( saturated == 0 ) { ubfound = 1; move16(); @@ -934,6 +1521,22 @@ Word16 tcx_scalar_quantization_rateloop_fx( sqGain = mult( sqGain, sub( tmp, add( mod_adjust1, (Word16) 0x8000 ) ) ); sqGain = normalize16( sqGain, &sqGain_e ); } + + Word16 shift_tmp = s_max( sqGain_e, 1 ); + test(); + IF( LT_16( shl( sqGain, sub( sqGain_e, shift_tmp ) ), shl( minSqGain, sub( 1, shift_tmp ) ) ) && EQ_16( tcxRateLoopOpt, 3 ) ) + { + sqGain = minSqGain; + move16(); + sqGain_e = 1; + move16(); + saturated = 1; + move16(); + } + } + ELSE + { + break; /* we cannot go any lower anyway*/ } } ELSE /* tcxRateLoopOpt != 2 */ @@ -992,7 +1595,7 @@ Word16 tcx_scalar_quantization_rateloop_fx( } /* Quantize spectrum */ - tcx_scalar_quantization_fx( x, x_e, xq, L_frame, sqGain, sqGain_e, offset, memQuantZeros_fx, tcxonly ); + tcx_scalar_quantization_ivas_fx( x, x_e, xq, L_frame, sqGain, sqGain_e, offset, memQuantZeros_fx, tcxonly ); /* Estimate bitrate */ stopFlag = 1; @@ -1003,12 +1606,19 @@ Word16 tcx_scalar_quantization_rateloop_fx( move16(); } - sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( xq, L_frame, - &lastnz, - nEncoded, target, &stopFlag, - hm_cfg ); + IF( GT_16( element_mode, EVS_MONO ) ) + { + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( xq, L_frame, &lastnz, nEncoded, target, &stopFlag, 0, hm_cfg ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, + hm_cfg ); + } - IF( tcxRateLoopOpt > 0 ) + IF( GE_16( tcxRateLoopOpt, 1 ) ) { test(); test(); @@ -1036,10 +1646,10 @@ Word16 tcx_scalar_quantization_rateloop_fx( } } /* for ( iter=0 ; iter 0 ) + IF( GE_16( tcxRateLoopOpt, 1 ) ) { /* Quantize spectrum */ - tcx_scalar_quantization_fx( x, x_e, xq, L_frame, *gain, *gain_e, offset, memQuantZeros_fx, tcxonly ); + tcx_scalar_quantization_ivas_fx( x, x_e, xq, L_frame, *gain, *gain_e, offset, memQuantZeros_fx, tcxonly ); /* Output */ *nEncoded = old_nEncoded; @@ -1073,6 +1683,7 @@ void QuantizeGain( Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedG Word32 tmp32; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif #ifdef BASOP_NOGLOB @@ -1082,16 +1693,17 @@ void QuantizeGain( Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedG #endif ener_e = 15 - 5 - 7; move16(); - IF( n >= 1024 ) + IF( GE_16( n, 1024 ) ) { /*reduce precision for avoiding overflow*/ ener = mult_r( shl( n, 4 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); ener_e = 15 - 4 - 7; + move16(); } BASOP_Util_Sqrt_InvSqrt_MantExp( ener, ener_e, &ener, &ener_e, &enerInv, &enerInv_e ); gain = mult( *pGain, ener ); - gain_e = *pGain_e + ener_e; + gain_e = add( *pGain_e, ener_e ); assert( gain > 0 ); @@ -1106,7 +1718,7 @@ void QuantizeGain( Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedG move16(); } - if ( quantizedGain > 127 ) + if ( GT_16( quantizedGain, 127 ) ) { quantizedGain = 127; move16(); @@ -1844,13 +2456,209 @@ void tcx_encoder_memory_update_fx( } } +#ifdef IVAS_FLOAT_FIXED +void tcx_encoder_memory_update_ivas_fx( + Word16 *wsig, /* i : target weighted signal, Q_new */ + Word16 *xn_buf, /* i/o: mdct output buffer/time domain weigthed synthesis, Q_new */ + Word16 L_frame_glob, /* i: global frame length */ + const Word16 *Ai, /* i: Unquantized (interpolated) LPC coefficients, Q12 */ + const Word16 *A, /* i: Quantized LPC coefficients, Q = 14 - norm_s(A[0]) */ + Word16 preemph, /* i: preemphasis factor, Q15 */ + LPD_state *LPDmem, /* i/o: coder memory state */ + Encoder_State *st, + Word16 *synthout, /* Q_new */ + Word16 Q_new ) +{ + Word16 tmp; + Word16 buf[1 + M + LFAC + L_FRAME_PLUS]; + Word16 *synth; + + + /* Output synth */ + Copy( xn_buf, synthout, L_frame_glob ); + + + /* Update synth */ + synth = buf + M + 1; + Copy( LPDmem->syn, buf, M + 1 ); + + Copy( xn_buf, synth, L_frame_glob ); + Copy( synth + sub( L_frame_glob, M + 1 ), LPDmem->syn, M + 1 ); + + IF( st->tcxonly == 0 ) + { + /* Update weighted synthesis */ + Residu3_fx( Ai + imult1616( sub( st->nb_subfr, 1 ), ( M + 1 ) ), synth + sub( L_frame_glob, 1 ), &tmp, 1, 0 ); + LPDmem->mem_w0 = sub_sat( wsig[sub( L_frame_glob, 1 )], tmp ); + move16(); + } + + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-( M + 1 )]; + move16(); + E_UTIL_f_preemph2( Q_new - 1, synth - M, preemph, add( M, L_frame_glob ), &tmp ); + + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn, M ); + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn2, M ); + Copy( synth + sub( L_frame_glob, L_SYN_MEM ), LPDmem->mem_syn_r, L_SYN_MEM ); + + test(); + IF( st->tcxonly == 0 || LE_16( L_frame_glob, L_FRAME16k ) ) + { + /* Update excitation */ + IF( LT_16( L_frame_glob, L_EXC_MEM ) ) + { + Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub( L_EXC_MEM, L_frame_glob ) ); + Residu3_fx( A, synth, LPDmem->old_exc + sub( L_EXC_MEM, L_frame_glob ), L_frame_glob, 1 ); + } + ELSE + { + Residu3_fx( A, synth + sub( L_frame_glob, L_EXC_MEM ), LPDmem->old_exc, L_EXC_MEM, 1 ); + } + } +} +#endif + /*--------------------------------------------------------------- * Residual Quantization *--------------------------------------------------------------*/ -/* Returns: number of bits used (including "bits") Q0 */ -Word16 tcx_ari_res_Q_spec_fx( +/* Returns: number of bits used (including "bits") Q0 */ +Word16 tcx_ari_res_Q_spec_fx( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +) +{ + Word16 i, j, num_zeros; + Word16 zeros[L_FRAME_PLUS]; + Word16 fac_p, sign; + Word32 thres, x_Q_m, x_Q_p; + Word32 L_tmp, L_tmp2; + Word16 s, s2; + + + /* Limit the number of residual bits */ + target_bits = s_min( target_bits, NPRM_RESQ ); + + + /* Requantize the spectrum line-by-line */ + /* fac_m = deadzone * 0.5f; + fac_p = 0.5f - fac_m; */ + num_zeros = 0; + move16(); + + s = sub( add( gain_e, x_Q_e ), x_orig_e ); + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, target_bits ) ) /* no bits left */ + { + BREAK; + } + + IF( x_Q[i] != 0 ) + { + sign = x_fac[i]; + move16(); + if ( signs[i] != 0 ) + sign = negate( sign ); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult( sign, deadzone ); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + L_tmp = L_mac( L_tmp, sign, (Word16) 0x8000 ); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_m, gain ), s ) ) ); + L_tmp2 = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_p, gain ), s ) ) ); + + IF( LT_32( L_tmp, L_tmp2 ) ) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add( bits, 1 ); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add( num_zeros, 1 ); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r( 1417339264l /*2*0.33f Q31*/, deadzone, 21627 /*2*0.33f Q15*/ ); /* Q16 */ + target_bits = sub( target_bits, 1 ); /* reserve 1 bit for the check below */ + + s = sub( gain_e, x_orig_e ); + s2 = sub( x_Q_e, 1 ); + FOR( j = 0; j < num_zeros; j++ ) + { + IF( GE_16( bits, target_bits ) ) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_mult( fac_p, x_fac[i] ); /* Q31 */ + + IF( GT_32( L_abs( x_orig[i] ), L_shl( Mpy_32_16_1( thres, gain ), s ) ) ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = sub( 1, signs[i] ); + move16(); + bits = add( bits, 1 ); + + L_tmp = L_shr( thres, s2 ); + if ( signs[i] ) + L_tmp = L_negate( L_tmp ); + x_Q[i] = L_tmp; + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + } + } + + + return bits; +} + +Word16 tcx_ari_res_Q_spec_ivas_fx( const Word32 x_orig[], /* i: original spectrum Q31-e */ Word16 x_orig_e, /* i: original spectrum exponent Q0 */ const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ @@ -1883,6 +2691,102 @@ Word16 tcx_ari_res_Q_spec_fx( fac_p = 0.5f - fac_m; */ num_zeros = 0; move16(); + s = sub( add( gain_e, x_Q_e ), x_orig_e ); + IF( x_fac == NULL ) + { + FOR( i = 0; i < L_frame; ++i ) + { + IF( GE_16( bits, target_bits ) ) /* no bits left */ + { + BREAK; + } + + IF( x_Q[i] != 0 ) + { + sign = shl( sub( 1, shl( signs[i], 1 ) ), Q14 ); + move16(); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult( sign, deadzone ); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + L_tmp = L_mac( L_tmp, sign, (Word16) 0x8000 ); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_m, gain ), s ) ) ); + L_tmp2 = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_p, gain ), s ) ) ); + + IF( LT_32( L_tmp, L_tmp2 ) ) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add( bits, 1 ); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add( num_zeros, 1 ); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r( 1417339264l /*2*0.33f Q31*/, deadzone, 21627 /*2*0.33f Q15*/ ); /* Q16 */ + target_bits = sub( target_bits, 1 ); /* reserve 1 bit for the check below */ + + s = sub( gain_e, x_orig_e ); + s2 = sub( x_Q_e, 1 ); + FOR( j = 0; j < num_zeros; j++ ) + { + IF( GE_16( bits, target_bits ) ) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_shl( fac_p, Q15 ); /* Q31 */ + + IF( GT_32( L_abs( x_orig[i] ), L_shl( Mpy_32_16_1( thres, gain ), s ) ) ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = sub( 1, signs[i] ); + move16(); + bits = add( bits, 1 ); + + L_tmp = L_shr( thres, s2 ); + if ( signs[i] ) + L_tmp = L_negate( L_tmp ); + x_Q[i] = L_tmp; + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + } + } + + return bits; + } s = sub( add( gain_e, x_Q_e ), x_orig_e ); FOR( i = 0; i < L_frame; i++ ) @@ -2210,6 +3114,175 @@ Word16 tcx_res_Q_spec_fx( return bits; } + +Word16 tcx_res_Q_spec_ivas_fx( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] /* 1Q14 */ +) +{ + Word16 i; + Word16 fac_m, fac_p; + Word32 tmp1, tmp2; + Word16 s, s2, lf_deemph_factor; + Word16 c; + Word32 thres; + + + /* Limit the number of residual bits */ + sqTargetBits = s_min( sqTargetBits, NPRM_RESQ ); + + /* Requantize the spectrum line-by-line */ + fac_m = shr( sq_round, 1 ); + fac_p = sub( 0x4000, fac_m ); + + /* exponent difference of x_orig and x_Q * sqGain */ + s = sub( x_orig_e, add( x_Q_e, sqGain_e ) ); + + lf_deemph_factor = 0x4000; + move16(); + s2 = sub( x_Q_e, 1 ); + + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, sub( sqTargetBits, kMaxEstimatorUndershoot ) ) ) + { + fac_m = 0; + move16(); + fac_p = 0; + move16(); + + IF( GE_16( bits, s_min( NPRM_RESQ, add( sqTargetBits, kMaxEstimatorOvershoot ) ) ) ) + { + BREAK; + } + } + + test(); + test(); + IF( ( x_Q[i] != 0 ) && ( ( lf_deemph_factors == NULL ) || ( GT_16( lf_deemph_factors[i], 0x2000 ) ) ) ) + { + tmp1 = L_add( x_orig[i], 0 ); + tmp2 = Mpy_32_16_1( x_Q[i], sqGain ); + if ( s > 0 ) + tmp2 = L_shr( tmp2, s ); + if ( s < 0 ) + tmp1 = L_shl( tmp1, s ); + + if ( lf_deemph_factors != NULL ) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + IF( LT_32( tmp1, tmp2 ) ) + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + + if ( x_Q[i] > 0 ) + tmp1 = L_mult( fac_m, lf_deemph_factor ); + if ( x_Q[i] < 0 ) + tmp1 = L_mult( fac_p, lf_deemph_factor ); + x_Q[i] = L_sub( x_Q[i], L_shr( tmp1, s2 ) ); + move32(); + } + ELSE + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + if ( x_Q[i] > 0 ) + tmp1 = L_mult( fac_p, lf_deemph_factor ); + if ( x_Q[i] < 0 ) + tmp1 = L_mult( fac_m, lf_deemph_factor ); + x_Q[i] = L_add( x_Q[i], L_shr( tmp1, s2 ) ); + move32(); + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + c = sub( 21627 /*0.66f Q15*/, mult_r( sq_round, 21627 /*0.66f Q15*/ ) ); + + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, sub( sqTargetBits, 2 ) ) ) + { + BREAK; + } + + test(); + test(); + IF( ( x_Q[i] == 0 ) && ( ( lf_deemph_factors == NULL ) || ( GT_16( lf_deemph_factors[i], 0x2000 ) ) ) ) + { + if ( lf_deemph_factors != NULL ) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + thres = L_mult( c, lf_deemph_factor ); // Q31 + Word16 shift_tmp = s_max( sqGain_e, x_orig_e ); + + tmp1 = Mpy_32_16_1( thres, sqGain ); + + IF( GT_32( L_shl( x_orig[i], sub( x_orig_e, shift_tmp ) ), L_shl( tmp1, sub( sqGain_e, shift_tmp ) ) ) ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + x_Q[i] = L_shl( thres, sub( 1, x_Q_e ) ); + move32(); + } + ELSE IF( L_add( L_shl( x_orig[i], sub( x_orig_e, shift_tmp ) ), L_shl( tmp1, sub( sqGain_e, shift_tmp ) ) ) < 0 ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + + x_Q[i] = L_shl( L_negate( thres ), sub( 1, x_Q_e ) ); + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + } + } + } + + /*Be sure that every possible bits are initialized*/ + FOR( i = bits; i < NPRM_RESQ; i++ ) + { + prm[i] = 0; + move16(); + } + + return bits; +} + void ProcessIGF_fx( IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ Encoder_State *st, /**< in: Encoder state */ @@ -2345,3 +3418,69 @@ void attenuateNbSpectrum_fx( Word16 L_frame, Word32 *spectrum ) att = mult_r( att, att ); } } + +#if 0 +void mdct_preShaping_fx( + Word16 x[], + const Word16 lg, + const Word16 gains[] ) +{ + Word16 i, j, k, l; + Word16 g; + Word16 m, n, k1, k2; + + j = 0; /* not counted, is included in ptr init */ + /* FDNS_NPTS = 64 !!! */ + k = idiv1616( lg, FDNS_NPTS ); + m = lg % FDNS_NPTS; + move16(); + IF( m ) + { + IF( LE_16( m, ( FDNS_NPTS / 2 ) ) ) + { + n = idiv1616( FDNS_NPTS, m ); + k1 = k; + move16(); + k2 = add( k, 1 ); + } + ELSE + { + n = idiv1616( FDNS_NPTS, sub( FDNS_NPTS, m ) ); + k1 = add( k, 1 ); + k2 = k; + } + FOR( i = 0; i < lg; ) + { + IF( j % n ) + { + k = k1; + } + ELSE + { + k = k2; + } + g = 1.f / gains[j++]; // Q15 + + /* Limit number of loops, if end is reached */ + k = min( k, lg - i ); + FOR( l = 0; l < k; l++ ) + { + x[i++] = mult( x[i++], g ); + } + } + } + ELSE + { + FOR( i = 0; i < lg; ) + { + g = 1.f / gains[j++]; // Q15 + FOR( l = 0; l < k; l++ ) + { + x[i++] = mult( x[i++], g ); + } + } + } + + return; +} +#endif diff --git a/lib_enc/tns_base_enc_fx.c b/lib_enc/tns_base_enc_fx.c index 9798a1eaa00a00caba2c74a6ca9c01862d181ce8..a703085a88b2f63b5c4ce80754a27d309f6201b3 100644 --- a/lib_enc/tns_base_enc_fx.c +++ b/lib_enc/tns_base_enc_fx.c @@ -311,6 +311,205 @@ Word16 DetectTnsFilt_fx( STnsConfig const *pTnsConfig, return ( pTnsData->nFilters > 0 ); } +#ifdef IVAS_FLOAT_FIXED +void CalculateTnsFilt_fx( + STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + const Word32 pSpectrum[], /* i : MDCT spectrum Qx*/ + STnsData *pTnsData, /* o : TNS data struct */ + Word16 *predictionGain /* o : TNS prediction gain Q7*/ +) +{ + Word16 idx0, idx1, nSubdivisions, iSubdivisions, spectrumLength; + STnsFilter *pFilter; + Word16 iStartLine, n, i, iEndLine, tmp, headroom, shift, lag; + Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */ + Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 iFilter = 0; + move16(); + const Word16 *pWindow; + Word32 L_tmp, tmp32; + + /* Calculate norms for each spectrum part */ + + FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ ) + { +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + idx0 = pTnsConfig->iFilterBorders[iFilter + 1]; + move16(); + idx1 = pTnsConfig->iFilterBorders[iFilter]; + move16(); + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + move16(); + assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS ); + + FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ ) + { + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) ); + + tmp = sub( idx1, idx0 ); + iStartLine = imult1616( tmp, iSubdivisions ); + iEndLine = add( iStartLine, tmp ); + + if ( EQ_16( nSubdivisions, 3 ) ) + iStartLine = mult( iStartLine, 0x2AAB ); + iStartLine = add( iStartLine, idx0 ); + + if ( EQ_16( nSubdivisions, 3 ) ) + iEndLine = mult( iEndLine, 0x2AAB ); + iEndLine = add( iEndLine, idx0 ); + + /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/ + headroom = getScaleFactor32( &pSpectrum[iStartLine], sub( iEndLine, iStartLine ) ); + + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm( pSpectrum + iStartLine, headroom, sub( iEndLine, iStartLine ), &shift ); + + /* Check threshold HLM_MIN_NRG */ + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + tmp32 = L_sub( L_shl_o( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ), &Overflow ), 3277l /*HLM_MIN_NRG Q7*/ ); +#else /* BASOP_NOGLOB */ + tmp32 = L_sub( L_shl( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ) ), 3277l /*HLM_MIN_NRG Q7*/ ); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + + /* get pre-shift for autocorrelation */ + tmp = sub( shift, norm_l( L_tmp ) ); /* exponent for normalized L_tmp */ + tmp = shr( sub( 1, tmp ), 1 ); /* pre-shift to apply before autocorrelation */ + shifts[iFilter][iSubdivisions] = s_min( tmp, headroom ); + move16(); + + /* calc normalization factor */ + facs[iFilter][iSubdivisions] = 0; + move16(); + facs_e[iFilter][iSubdivisions] = 0; + move16(); + + if ( tmp32 > 0 ) + { + facs[iFilter][iSubdivisions] = 0x7FFF; + move16(); /* normalization not needed for one subdivision */ + } + + test(); + IF( ( tmp32 > 0 ) && ( GT_16( nSubdivisions, 1 ) ) ) + { + move16(); + facs_e[iFilter][iSubdivisions] = shl( sub( tmp, shifts[iFilter][iSubdivisions] ), 1 ); + move16(); + tmp = sub( 1, shl( tmp, 1 ) ); /* exponent of autocorrelation */ + L_tmp = L_shl_sat( L_tmp, sub( shift, tmp ) ); /* shift L_tmp to that exponent */ + + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + move16(); + facs[iFilter][iSubdivisions] = div_s( 0x2000, round_fx_sat( L_tmp ) ); /* L_tmp is >= 0x2000000 */ + } + } + } + /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */ + FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ ) + { +#define RXX_E ( 3 ) + Word32 rxx[TNS_MAX_FILTER_ORDER + 1]; + Word16 tmpbuf[350]; + + set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 ); + + idx0 = pTnsConfig->iFilterBorders[iFilter + 1]; + move16(); + idx1 = pTnsConfig->iFilterBorders[iFilter]; + move16(); + spectrumLength = sub( idx1, idx0 ); + pFilter = pTnsData->filter + iFilter; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + move16(); + FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ ) + { + IF( facs[iFilter][iSubdivisions] == 0 ) + { + BREAK; + } + + + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) ); + + iStartLine = imult1616( spectrumLength, iSubdivisions ); + iEndLine = add( iStartLine, spectrumLength ); + + if ( EQ_16( nSubdivisions, 3 ) ) + iStartLine = mult( iStartLine, 0x2AAB ); + iStartLine = add( iStartLine, idx0 ); + + if ( EQ_16( nSubdivisions, 3 ) ) + iEndLine = mult( iEndLine, 0x2AAB ); + iEndLine = add( iEndLine, idx0 ); + + + move16(); + shift = shifts[iFilter][iSubdivisions]; + + move16(); + pWindow = tnsAcfWindow_fx; + + n = sub( iEndLine, iStartLine ); + assert( n < (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) ); + FOR( i = 0; i < n; i++ ) + { + tmpbuf[i] = round_fx_sat( L_shl_sat( pSpectrum[iStartLine + i], shift ) ); + move16(); + } + + FOR( lag = 0; lag <= pTnsConfig->maxOrder; lag++ ) + { + n = sub( sub( iEndLine, lag ), iStartLine ); + + L_tmp = L_deposit_l( 0 ); + FOR( i = 0; i < n; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_mac0_sat( L_tmp, tmpbuf[i], tmpbuf[i + lag] ); +#else + L_tmp = L_mac0( L_tmp, tmpbuf[i], tmpbuf[i + lag] ); +#endif + } + + if ( lag != 0 ) + L_tmp = Mpy_32_16_1( L_tmp, *pWindow++ ); + + L_tmp = Mpy_32_16_1( L_tmp, facs[iFilter][iSubdivisions] ); + L_tmp = L_shl( L_tmp, facs_e[iFilter][iSubdivisions] ); + + rxx[lag] = L_add( rxx[lag], L_tmp ); + move32(); + } + } + + IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */ + { + pFilter->spectrumLength = spectrumLength; + move16(); + /* Limit the maximum order to spectrum length/4 */ + GetFilterParameters( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter ); + } + } + if ( predictionGain ) + { + assert( pTnsConfig->nMaxFilters == 1 ); + move16(); + *predictionGain = pTnsData->filter->predictionGain; + } + + return; +} +#endif Word16 DetectTnsFilt_ivas_fx( STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ Word32 const pSpectrum[], /* i : MDCT spectrum Q=Qx */ @@ -627,6 +826,52 @@ Word16 EncodeTnsData_fx( STnsConfig const *pTnsConfig, STnsData const *pTnsData, return TNS_NO_ERROR; } +void EncodeTnsData_ivas_fx( + STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + STnsData const *pTnsData, /* i : TNS data struct (quantized param) */ + Word16 *stream, /* o : internal data stream Q0*/ + Word16 *pnSize, /* o : number of written parameters Q0*/ + Word16 *pnBits /* o : number of written bits Q0*/ +) +{ + *pnSize = 0; + move16(); + move16(); + *pnBits = 0; + + IF( GT_16( pTnsConfig->nMaxFilters, 1 ) ) + { + IF( pTnsConfig->allowTnsOnWhite ) + { + IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) ) + { + GetParameters_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits ); + } + ELSE + { + GetParameters_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits ); + } + } + ELSE + { + IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) ) + { + GetParameters_fx( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits ); + } + ELSE + { + GetParameters_fx( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits ); + } + } + } + ELSE + { + GetParameters_fx( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits ); + } + + return; +} + Word16 WriteTnsData_fx( STnsConfig const *pTnsConfig, Word16 const *stream, Word16 *pnSize, Encoder_State *st, Word16 *pnBits ) { diff --git a/lib_enc/transient_detection.c b/lib_enc/transient_detection.c index dea0296adf688e5e6c5c038074fd34141fa8da5d..eeeadfb1a45b319a22bcc1fbea8cca2d9224bb10 100644 --- a/lib_enc/transient_detection.c +++ b/lib_enc/transient_detection.c @@ -43,7 +43,10 @@ #include #include "wmc_auto.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#include "ivas_prot_fx.h" +#endif /*---------------------------------------------------------------* * Local constants *---------------------------------------------------------------*/ @@ -56,7 +59,6 @@ #define THR_LOW 4.25f #define THR_LOW_STEP 1.0f - /*---------------------------------------------------------------* * Local function prototypes *---------------------------------------------------------------*/ @@ -71,7 +73,6 @@ static void CalculateSubblockEnergies( const float *input, const int16_t nSample static void RunTransientDetector( TransientDetector *pTransientDetector ); static void GetAttackForTCXDecision( const float *pSubblockNrg, const float *pAccSubblockNrg, const int16_t nSubblocks, const int16_t nPastSubblocks, const float attackRatioThreshold, int16_t *pbIsAttackPresent, int16_t *pAttackIndex ); - /*-------------------------------------------------------------------* * InitTransientDetection() * @@ -92,6 +93,7 @@ void InitTransientDetection( /* Init the TCX Short/Long transient detector. */ InitTransientDetector( &hTranDet->subblockEnergies, nTCXDelay, NSUBBLOCKS, GetAttackForTCXDecision, 8.5f, &hTranDet->transientDetector ); + hTranDet->transientDetector.CheckSubblocksForAttack_fx = GetAttackForTCXDecision_fx; /* We need two past subblocks for the TCX TD and NSUBBLOCKS+1 for the temporal flatness measure for the TCX LTP. */ if ( ext_mem_flag ) @@ -249,7 +251,6 @@ void RunTransientDetection( return; } - static uint16_t isLongTermTransient( const float frameTFM, float *lastTFM ) @@ -485,7 +486,6 @@ static void GetAttackForTCXDecision( return; } - static void InitDelayBuffer( const int16_t nFrameLength, const int16_t nDelay, @@ -579,7 +579,6 @@ static float InlineFilter( return 0.375f * inValue - 0.5f * firState1 + 0.125f * firState2; } - static void HighPassFilter( const float *input, const int16_t length, @@ -603,7 +602,6 @@ static void HighPassFilter( return; } - static void RunTransientDetector( TransientDetector *pTransientDetector ) { @@ -624,7 +622,6 @@ static void RunTransientDetector( return; } - static void UpdateDelayBuffer( const float *input, const int16_t nSamplesAvailable, @@ -649,7 +646,6 @@ static void UpdateDelayBuffer( return; } - static void UpdateSubblockEnergies( const float *input, const int16_t nSamplesAvailable, @@ -676,7 +672,6 @@ static void UpdateSubblockEnergies( return; } - /* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ static void UpdatedAndStoreAccWindowNrg( float newWindowNrgF, @@ -773,7 +768,73 @@ static void CalculateSubblockEnergies( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void set_transient_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE structure */ + Word16 currFlatness[] /* i/o: current flatness */ +) +{ + Word16 n, attackIsPresent; + Word16 currFlatnessMax; + Encoder_State **sts; + + sts = hCPE->hCoreCoder; + + /* for DFT/TD based stereo ,map avg. flatness to individual stereo channels (M/S or X/Y) */ + maximum_fx( currFlatness, CPE_CHANNELS, &currFlatnessMax ); + attackIsPresent = 0; + move16(); + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + attackIsPresent = s_max( attackIsPresent, sts[n]->hTranDet->transientDetector.bIsAttackPresent ); + } + + set16_fx( currFlatness, currFlatnessMax, CPE_CHANNELS ); + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + sts[n]->hTranDet->transientDetector.bIsAttackPresent = attackIsPresent; + move16(); + } + + IF( hCPE->hStereoDft != NULL ) + { + IF( hCPE->hStereoDft->attackPresent ) + { + hCPE->hStereoDft->wasTransient = 1; + move16(); + } + ELSE IF( hCPE->hStereoDft->wasTransient ) + { + hCPE->hStereoDft->wasTransient = 0; + move16(); + } + + hCPE->hStereoDft->attackPresent = attackIsPresent; + move16(); + hCPE->hStereoDft->hItd->currFlatness_fx = 0; + move16(); + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + hCPE->hStereoDft->hItd->currFlatness_fx = s_max( hCPE->hStereoDft->hItd->currFlatness_fx, currFlatness[n] ); + } + } + + IF( hCPE->hStereoMdct != NULL ) + { + hCPE->hStereoMdct->hItd->currFlatness_fx = 0; + move16(); + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + hCPE->hStereoMdct->hItd->currFlatness_fx = s_max( hCPE->hStereoMdct->hItd->currFlatness_fx, currFlatness[n] ); + } + } + + return; +} +#else void set_transient_stereo( CPE_ENC_HANDLE hCPE, /* i : CPE structure */ float currFlatness[] /* i/o: current flatness */ @@ -832,13 +893,14 @@ void set_transient_stereo( return; } - +#endif /*-------------------------------------------------------------------* * transient_analysis() * * *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED /*! r: preliminary flag to force ACELP */ int16_t transient_analysis( TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ @@ -928,3 +990,4 @@ int16_t transient_analysis( return prel_force_td != 0; } +#endif diff --git a/lib_enc/transient_detection_fx.c b/lib_enc/transient_detection_fx.c index 6fd743a99c6d516c9ff7422af91932dfabc7fc2f..7000b6fbee742e411a4fcc5cbfac013726264b9a 100644 --- a/lib_enc/transient_detection_fx.c +++ b/lib_enc/transient_detection_fx.c @@ -12,8 +12,9 @@ #include #include #include -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ /* Exponent of attack threshold. Picked according to current threshold values. */ #define ATTACKTHRESHOLD_E 4 @@ -26,6 +27,14 @@ #define MIN_BLOCK_ENERGY ( (Word32) 1 ) +#ifdef IVAS_FLOAT_FIXED +#define MIN_BLOCK_ENERGY_FX 107 +#define THR_HIGH_FX 17408 /* 8.5f in Q11 */ +#define THR_NORM_HIGH_FX 16384 /* 8 in Q11 */ +#define THR_NORM_LOW_FX 9216 /* 4.5f in Q11 */ +#define THR_LOW_FX 8704 /* 4.25f in Q11 */ +#define THR_LOW_STEP_FX ONE_IN_Q11 /* 1 in Q11 */ +#endif /************************************************/ /* */ @@ -42,6 +51,10 @@ static void UpdateSubblockEnergies( Word16 const *input, Word16 nSamplesAvailabl static void CalculateSubblockEnergies( Word16 const *input, Word16 nSamplesAvailable, SubblockEnergies *pSubblockEnergies ); static void RunTransientDetector( TransientDetector *pTransientDetector ); +static void CalculateSubblockEnergies_ivas_fx( Word16 const *input, Word16 nSamplesAvailable, SubblockEnergies *pSubblockEnergies ); + +static void UpdateSubblockEnergies_ivas_fx( Word16 const *input, Word16 nSamplesAvailable, SubblockEnergies *pSubblockEnergies ); + /************************************************/ /* */ /* Functions that define transient detectors */ @@ -128,6 +141,82 @@ static void GetAttackForTCXDecision( Word32 const *pSubblockNrg, Word32 const *p } +#ifdef IVAS_FLOAT_FIXED +void GetAttackForTCXDecision_fx( Word32 const *pSubblockNrg, Word32 const *pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 *pbIsAttackPresent, Word16 *pAttackIndex ) +{ + Word16 i; + Word16 bIsAttackPresent, attackIndex; + Word16 attackRatioThreshold_1_5; + + (void) nPastSubblocks; + (void) nSubblocks; + assert( nSubblocks >= NSUBBLOCKS ); + assert( nPastSubblocks >= 2 ); + + /* attackRatioThreshold_1_5 = attackRatioThreshold * 1.5, exponent is ATTACKTHRESHOLD_E+1 */ + attackRatioThreshold_1_5 = add( shr( attackRatioThreshold, 2 ), shr( attackRatioThreshold, 1 ) ); + + move16(); + move16(); + bIsAttackPresent = FALSE; + attackIndex = 0; + /* Search for the last attack in the subblocks */ + if ( s_or( (Word16) GT_32( L_shr( pSubblockNrg[-1], ATTACKTHRESHOLD_E ), Mpy_32_16_1( pAccSubblockNrg[-1], attackRatioThreshold ) ), + L_sub( L_shr( pSubblockNrg[-2], ATTACKTHRESHOLD_E ), Mpy_32_16_1( pAccSubblockNrg[-2], attackRatioThreshold ) ) > 0 ) ) + { + move16(); + bIsAttackPresent = TRUE; + } + + FOR( i = 0; i < NSUBBLOCKS; i++ ) + { + IF( GT_32( L_shr( pSubblockNrg[i], ATTACKTHRESHOLD_E ), Mpy_32_16_1( pAccSubblockNrg[i], attackRatioThreshold ) ) ) + { + if ( i < 6 ) + { + move16(); + bIsAttackPresent = TRUE; + } + + if ( s_and( (Word16) NE_16( attackIndex, 2 ), (Word16) NE_16( attackIndex, 6 ) ) ) + { + move16(); + attackIndex = i; + } + } + ELSE /* no attack, but set index anyway in case of strong energy increase */ + { + IF( s_and( ( (Word16) GT_32( L_shr( pSubblockNrg[i], 1 + ATTACKTHRESHOLD_E ), Mpy_32_16_1( pSubblockNrg[sub( i, 1 )], attackRatioThreshold_1_5 ) ) ), + ( L_sub( L_shr( pSubblockNrg[i], 1 + ATTACKTHRESHOLD_E ), Mpy_32_16_1( pSubblockNrg[sub( i, 2 )], attackRatioThreshold_1_5 ) ) > 0 ) ) ) + { + + if ( s_and( (Word16) NE_16( attackIndex, 2 ), (Word16) NE_16( attackIndex, 6 ) ) ) + { + move16(); + attackIndex = i; + } + } + } + } + /* avoid post-echos on click sounds (very short transients) due to TNS aliasing */ + if ( EQ_16( attackIndex, 4 ) ) + { + move16(); + attackIndex = 7; + } + if ( EQ_16( attackIndex, 5 ) ) + { + move16(); + attackIndex = 6; + } + + move16(); + move16(); + *pAttackIndex = attackIndex; + *pbIsAttackPresent = bIsAttackPresent; +} + +#endif /** Initialize TCX transient detector. * See InitTransientDetector_fx for definition of parameters. */ @@ -227,6 +316,44 @@ Word16 GetTCXAvgTemporalFlatnessMeasure_fx( struct TransientDetection const *pTr return i; } +Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ) +{ + Word16 i; + TransientDetector const *pTransientDetector; + SubblockEnergies const *pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const *pSubblockNrgChange; + Word32 sumTempFlatness; + Word16 nTotBlocks; + + /* Initialization */ + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + nDelay = pTransientDetector->nDelay; + move16(); + nRelativeDelay = sub( pSubblockEnergies->nDelay, nDelay ); + pSubblockNrgChange = NULL; + nTotBlocks = add( nCurrentSubblocks, nPrevSubblocks ); + + assert( nTotBlocks > 0 ); + + sumTempFlatness = L_deposit_l( 0 ); + + assert( ( nPrevSubblocks <= nRelativeDelay ) && ( nCurrentSubblocks <= NSUBBLOCKS + nDelay ) ); + + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[sub( nRelativeDelay, nPrevSubblocks )]; // subblockNrgChange Q7 + FOR( i = 0; i < nTotBlocks; i++ ) + { + sumTempFlatness = L_add( sumTempFlatness, L_deposit_l( pSubblockNrgChange[i] ) ); + } + + /* exponent = AVG_FLAT_E */ + i = div_l( L_shl( sumTempFlatness, 16 - 15 + SUBBLOCK_NRG_CHANGE_E - AVG_FLAT_E ), nTotBlocks ); // Q7 + + return i; +} + Word16 GetTCXMaxenergyChange_fx( struct TransientDetection const *pTransientDetection, const Word8 isTCX10, const Word16 nCurrentSubblocks, @@ -410,6 +537,58 @@ void RunTransientDetection_fx( Word16 const *input, Word16 nSamplesAvailable, Tr } +#ifdef IVAS_FLOAT_FIXED +void RunTransientDetection_ivas_fx( + const Word16 *input_fx, /* i : input signal Q: -1 */ + const Word16 length, /* i : frame length */ + TRAN_DET_HANDLE hTranDet /* i/o: transient detection handle */ +) +{ + + Word16 filteredInput_fx[L_FRAME_MAX]; + SubblockEnergies *pSubblockEnergies = &hTranDet->subblockEnergies; + TransientDetector *pTransientDetector = &hTranDet->transientDetector; + + Word32 e0_fx, e1_fx; + + assert( ( input_fx != NULL ) && ( hTranDet != NULL ) && ( pSubblockEnergies != NULL ) && ( pTransientDetector != NULL ) ); + + /* Variable initializations */ + HighPassFilter( input_fx, length, &pSubblockEnergies->firState1, &pSubblockEnergies->firState2, filteredInput_fx ); + + + /* Update subblock energies. */ + Scale_sig( filteredInput_fx, L_FRAME_MAX, 8 ); + Scale_sig32( pSubblockEnergies->subblockNrg, NSUBBLOCKS + MAX_TD_DELAY, 3 ); + Scale_sig32( pSubblockEnergies->accSubblockNrg, NSUBBLOCKS + MAX_TD_DELAY + 1, 3 ); + Scale_sig( pSubblockEnergies->subblockNrgChange, NSUBBLOCKS + MAX_TD_DELAY, 3 ); + UpdateSubblockEnergies_ivas_fx( filteredInput_fx, length, pSubblockEnergies ); + Scale_sig32( pSubblockEnergies->subblockNrg, NSUBBLOCKS + MAX_TD_DELAY, -3 ); + Scale_sig32( pSubblockEnergies->accSubblockNrg, NSUBBLOCKS + MAX_TD_DELAY + 1, -3 ); + Scale_sig( pSubblockEnergies->subblockNrgChange, NSUBBLOCKS + MAX_TD_DELAY, -3 ); + + /* Run transient detectors. */ + RunTransientDetector( pTransientDetector ); + + /* Update the delay buffer. */ + UpdateDelayBuffer( filteredInput_fx, length, &hTranDet->delayBuffer ); + + /* compute ramp up flag */ + pSubblockEnergies->ramp_up_flag = ( ( pSubblockEnergies->ramp_up_flag << 1 ) & 0x0003 ); + Word16 exp = 0, exp1 = 0; + e0_fx = dotp_fx( filteredInput_fx + length / 2, filteredInput_fx + length / 2, pSubblockEnergies->pDelayBuffer->nSubblockSize / 2, &exp ); + e0_fx = BASOP_Util_Add_Mant32Exp( 1, exp, e0_fx, exp, &exp1 ); // exponent: exp1 + e1_fx = L_sub( pSubblockEnergies->subblockNrg[pSubblockEnergies->nDelay + 4], L_shr( e0_fx, 31 - exp1 ) ); // exponent: 31, Q: 0 + IF( BASOP_Util_Cmp_Mant32Exp( e0_fx, exp1, e1_fx, 31 ) > 0 ) + { + pSubblockEnergies->ramp_up_flag = s_or( pSubblockEnergies->ramp_up_flag, 0x0001 ); + move16(); + } + + return; +} + +#endif #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * isLongTermTransient_fx() @@ -899,6 +1078,31 @@ static void UpdateSubblockEnergies( Word16 const *input, Word16 nSamplesAvailabl CalculateSubblockEnergies( input, nSamplesAvailable, pSubblockEnergies ); } +static void UpdateSubblockEnergies_ivas_fx( Word16 const *input, Word16 nSamplesAvailable, SubblockEnergies *pSubblockEnergies ) +{ + Word16 i; + + + assert( ( pSubblockEnergies->nDelay >= 0 ) && ( pSubblockEnergies->nDelay + NSUBBLOCKS <= (int) sizeof( pSubblockEnergies->subblockNrg ) / (int) sizeof( pSubblockEnergies->subblockNrg[0] ) ) ); + assert( pSubblockEnergies->nPartialDelay <= pSubblockEnergies->pDelayBuffer->nDelay ); + /* At least one block delay is required when subblock energy change is required */ + assert( pSubblockEnergies->nDelay >= 1 ); + + /* Shift old subblock energies */ + FOR( i = 0; i < pSubblockEnergies->nDelay; i++ ) + { + move32(); + move32(); + move16(); + pSubblockEnergies->subblockNrg[i] = pSubblockEnergies->subblockNrg[i + NSUBBLOCKS]; + pSubblockEnergies->accSubblockNrg[i] = pSubblockEnergies->accSubblockNrg[i + NSUBBLOCKS]; + pSubblockEnergies->subblockNrgChange[i] = pSubblockEnergies->subblockNrgChange[i + NSUBBLOCKS]; + } + + /* Compute filtered subblock energies for the new samples */ + CalculateSubblockEnergies_ivas_fx( input, nSamplesAvailable, pSubblockEnergies ); +} + /* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ static void UpdatedAndStoreAccWindowNrg( Word32 newWindowNrgF, Word32 *pAccSubblockNrg, Word16 facAccSubblockNrg, Word32 *pOutAccWindowNrgF ) { @@ -1036,6 +1240,128 @@ static void CalculateSubblockEnergies( Word16 const *input, Word16 nSamplesAvail pSubblockEnergies->firState1 = firState1; pSubblockEnergies->firState2 = firState2; } + +static void CalculateSubblockEnergies_ivas_fx( Word16 const *input, Word16 nSamplesAvailable, SubblockEnergies *pSubblockEnergies ) +{ + DelayBuffer *pDelayBuffer; + Word16 nSubblockSize; + Word16 nDelay; + Word16 nPartialDelay; + Word16 *delayBuffer; + Word16 facAccSubblockNrg; + Word32 *pSubblockNrg; + Word32 *pAccSubblockNrg; + Word16 *pSubblockNrgChange; + Word32 *pAccSubblockTmp; + Word16 nWindows; + Word16 w, k, k2, tmp; + Word16 firState1, firState2; + Word32 w0, w1; + Word32 accu; + + move16(); + pDelayBuffer = pSubblockEnergies->pDelayBuffer; + facAccSubblockNrg = pSubblockEnergies->facAccSubblockNrg; + + move16(); + move16(); + move16(); + nSubblockSize = pDelayBuffer->nSubblockSize; + nDelay = pSubblockEnergies->nDelay; + nPartialDelay = pSubblockEnergies->nPartialDelay; + + delayBuffer = &pDelayBuffer->buffer[sub( pDelayBuffer->nDelay, nPartialDelay )]; + pSubblockNrg = &pSubblockEnergies->subblockNrg[nDelay]; + pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nDelay]; + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nDelay]; + + move16(); + move16(); + /* nWindows = (nSamplesAvailable + nPartialDelay) / nSubblockSize */ + nWindows = shr( div_s( add( nSamplesAvailable, nPartialDelay ), shl( nSubblockSize, 7 ) ), 8 ); + firState1 = pSubblockEnergies->firState1; + firState2 = pSubblockEnergies->firState2; + pAccSubblockTmp = &pAccSubblockNrg[nWindows]; + + IF( nWindows > 0 ) + { + /* Process left over samples from the previous frame. */ + accu = L_add( 109568, 0 ); // 107 in Q10 + assert( ( SUBBLOCK_NRG_E & 1 ) == 0 ); + FOR( k = 0; k < nPartialDelay; k++ ) + { + tmp = shr( delayBuffer[k], SUBBLOCK_NRG_E / 2 ); + accu = L_mac0( accu, tmp, tmp ); + } + + /* Process new samples in the 0. subblock. */ + w = sub( nSubblockSize, nPartialDelay ); + assert( ( SUBBLOCK_NRG_E & 1 ) == 0 ); + FOR( k = 0; k < w; k++ ) + { + tmp = shr( input[k], SUBBLOCK_NRG_E / 2 ); +#ifdef BASOP_NOGLOB + accu = L_mac0_sat( accu, tmp, tmp ); +#else + accu = L_mac0( accu, tmp, tmp ); +#endif + } + + move32(); + pSubblockNrg[0] = accu; // Q10 + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg( pSubblockNrg[0], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[0] ); + + FOR( w = 1; w < nWindows; w++ ) + { + accu = L_add( 109568, 0 ); // 107 in Q10 + /* Process new samples in the w. subblock. */ + k2 = add( k, nSubblockSize ); + assert( ( SUBBLOCK_NRG_E & 1 ) == 0 ); + FOR( ; k < k2; k++ ) + { + tmp = shr( input[k], SUBBLOCK_NRG_E / 2 ); +#ifdef BASOP_NOGLOB + accu = L_mac0_sat( accu, tmp, tmp ); +#else + accu = L_mac0( accu, tmp, tmp ); +#endif + } + move32(); + pSubblockNrg[w] = accu; + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg( pSubblockNrg[w], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[w] ); + } + + /* Calculate energy change for each block. */ + FOR( w = 0; w < nWindows; w++ ) + { + w0 = L_add( pSubblockNrg[w], 0 ); + w1 = L_add( pSubblockNrg[sub( w, 1 )], 0 ); + + IF( GT_32( w0, w1 ) ) + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale( w0, w1, &k ); + } + ELSE + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale( w1, w0, &k ); + } + move16(); + pSubblockNrgChange[w] = MAX_16; + IF( LT_16( k, 5 ) ) + { + move16(); + pSubblockNrgChange[w] = shr( k2, sub( 5, k ) ); + } + } + } + + move16(); + move16(); + pSubblockEnergies->firState1 = firState1; + pSubblockEnergies->firState2 = firState2; +} #ifdef IVAS_CODE /*-------------------------------------------------------------------* * set_transient_stereo() @@ -1101,7 +1427,7 @@ void set_transient_stereo( return; } - +#endif /*-------------------------------------------------------------------* * transient_analysis() * @@ -1109,93 +1435,145 @@ void set_transient_stereo( *-------------------------------------------------------------------*/ /*! r: preliminary flag to force ACELP */ -int16_t transient_analysis( - TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ - const float cor_map_LT[], /* i : LT correlation map */ - const float multi_harm_limit /* i : multi harminic threshold */ -) +Word16 transient_analysis_ivas_fx( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const Word16 cor_map_LT[], /* i : LT correlation map Q_cor_map */ + Word16 Q_cor_map, + const Word16 multi_harm_limit, /* i : multi harmonic threshold Q_multi_harm_limit */ + Word16 Q_multi_harm_limit ) { - const float *pSubblockNrg; - float accSubblockNrgRev[NSUBBLOCKS]; /* store acc Nrg in reversed signal */ - float *pTmp; /* point to acc Nrg */ - int16_t offset; - int16_t i; - float thr_fwd; - float thr_rev; - const int16_t nRelativeDelay = hTranDet->subblockEnergies.nDelay - hTranDet->transientDetector.nDelay; - int16_t prel_force_td; - float cor_map_LT_sum; - - pTmp = &accSubblockNrgRev[NSUBBLOCKS - 1]; - offset = nRelativeDelay - 4; + const Word32 *pSubblockNrg; + Word32 accSubblockNrgRev_fx[NSUBBLOCKS]; + Word32 *pTmp_fx; + Word16 offset; + Word16 i; + Word16 thr_fwd_fx; + Word16 thr_rev_fx; + const Word16 nRelativeDelay = sub( hTranDet->subblockEnergies.nDelay, hTranDet->transientDetector.nDelay ); + Word16 prel_force_td; + Word32 cor_map_LT_sum = 0; + move16(); + + /* Set pointer to the reverse accumulator buffer */ + pTmp_fx = &accSubblockNrgRev_fx[NSUBBLOCKS - 1]; + offset = sub( nRelativeDelay, 4 ); prel_force_td = FALSE; + move16(); + + cor_map_LT_sum = sum16_32_fx( cor_map_LT, L_FFT / 2 ); + + thr_fwd_fx = THR_NORM_HIGH_FX; // THR_NORM_HIGH_FX is in Q11 Format + move16(); + Word16 shift = 0; + move16(); + /* Q_cor_map: cor_map_LT is in Q_cor_map format */ + /* Q_multi_harm_limit: multi_harm_limit is in Q_multi_harm_limit format */ + IF( GT_16( Q_cor_map, Q_multi_harm_limit ) ) + { + shift = sub( Q_cor_map, Q_multi_harm_limit ); + + if ( GT_32( L_shr( cor_map_LT_sum, shift ), L_deposit_l( mult( multi_harm_limit, 26214 ) ) ) ) // 26214 is 0.8 in Q15 format + { + thr_fwd_fx = THR_HIGH_FX; // THR_HIGH_FX is in Q11 Format + move16(); + } + } + ELSE + { + shift = sub( Q_multi_harm_limit, Q_cor_map ); - /* summation of the LT correlation map */ - cor_map_LT_sum = sum_f( cor_map_LT, L_FFT / 2 ); /* Note maybe BE optimized by computing inside noise_est */ + if ( GT_32( cor_map_LT_sum, L_deposit_l( shr( mult( multi_harm_limit, 26214 ), shift ) ) ) ) // 26214 is 0.8 in Q15 format + { + thr_fwd_fx = THR_HIGH_FX; // THR_HIGH_FX is in Q11 Format + move16(); + } + } - thr_fwd = THR_NORM_HIGH; - if ( cor_map_LT_sum > multi_harm_limit * 0.8f ) + thr_rev_fx = THR_LOW_FX; // THR_LOW_FX is in Q11 Format + move16(); + IF( GT_16( Q_cor_map, Q_multi_harm_limit ) ) { - thr_fwd = THR_HIGH; + shift = sub( Q_cor_map, Q_multi_harm_limit ); + + if ( GT_32( L_shr( cor_map_LT_sum, shift ), L_deposit_l( mult( multi_harm_limit, 19661 ) ) ) ) // 19661 is 0.6 in Q15 format + { + thr_rev_fx = THR_NORM_LOW_FX; // THR_NORM_LOW_FX is in Q11 Format + move16(); + } } - thr_rev = THR_LOW; - if ( cor_map_LT_sum > multi_harm_limit * 0.6f ) + ELSE { - thr_rev = THR_NORM_LOW; + shift = sub( Q_multi_harm_limit, Q_cor_map ); + + if ( GT_32( cor_map_LT_sum, L_deposit_l( shr( mult( multi_harm_limit, 19661 ), shift ) ) ) ) // 19661 is 0.6 in Q15 format + { + thr_rev_fx = THR_NORM_LOW_FX; // THR_NORM_LOW_FX is in Q11 Format + move16(); + } } - /* forward attack analysis */ - for ( i = -2; i < 7; i++ ) + /* Forward attack analysis */ + FOR( i = -2; i < 7; i++ ) { - if ( hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i] > hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i] * thr_fwd ) + IF( BASOP_Util_Cmp_Mant32Exp( hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i], thr_fwd_fx ), add( hTranDet->subblockEnergies.accSubblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0001; + prel_force_td = s_or( prel_force_td, 0x0001 ); } } - if ( prel_force_td == 0 && hTranDet->transientDetector.prev_bIsAttackPresent == 1 ) + + test(); + IF( prel_force_td == 0 && EQ_16( hTranDet->transientDetector.prev_bIsAttackPresent, 1 ) ) { - /* release analysis */ + /* Release analysis */ pSubblockNrg = hTranDet->transientDetector.pSubblockEnergies->subblockNrg; - set_zero( accSubblockNrgRev, NSUBBLOCKS ); - for ( i = NSUBBLOCKS - 1; i > -1; i-- ) + set32_fx( accSubblockNrgRev_fx, 0, NSUBBLOCKS ); + + FOR( i = NSUBBLOCKS - 1; i > -1; i-- ) { - if ( i == NSUBBLOCKS - 1 ) + + IF( EQ_16( i, NSUBBLOCKS - 1 ) ) { - accSubblockNrgRev[i] = pSubblockNrg[i + offset]; + accSubblockNrgRev_fx[i] = pSubblockNrg[i + offset]; + move32(); } - else + ELSE { - accSubblockNrgRev[i] = *pTmp; - *pTmp *= hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg; - if ( pSubblockNrg[i + offset] > *pTmp ) + accSubblockNrgRev_fx[i] = *pTmp_fx; + *pTmp_fx = Mpy_32_16_1( *pTmp_fx, hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg ); + move32(); + if ( GT_32( pSubblockNrg[i + offset], *pTmp_fx ) ) { - *pTmp = pSubblockNrg[i + offset]; + *pTmp_fx = pSubblockNrg[i + offset]; + move32(); } } } /* -3 check */ - if ( pSubblockNrg[1 + offset] > accSubblockNrgRev[1] * thr_rev ) + test(); + IF( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[1 + offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[1], thr_rev_fx ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0002; + prel_force_td = s_or( prel_force_td, 0x0002 ); + move16(); } /* -4 check */ - if ( prel_force_td == 0 && pSubblockNrg[offset] > accSubblockNrgRev[0] * thr_rev ) + test(); + IF( prel_force_td == 0 && BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[0], thr_rev_fx ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - if ( pSubblockNrg[offset] > accSubblockNrgRev[0] * ( thr_rev + THR_LOW_STEP ) ) + + IF( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[0], add( thr_rev_fx, THR_LOW_STEP_FX ) ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0004; + prel_force_td = s_or( prel_force_td, 0x0004 ); } - else if ( ( hTranDet->subblockEnergies.ramp_up_flag & 0x0002 ) != 0 ) + ELSE IF( ( s_and( hTranDet->subblockEnergies.ramp_up_flag, 0x0002 ) ) != 0 ) { - prel_force_td |= 0x0008; + prel_force_td = s_or( prel_force_td, 0x0008 ); } } } + return prel_force_td != 0; } - -#endif diff --git a/lib_enc/updt_enc.c b/lib_enc/updt_enc.c index 088b8b49499b524ae0ec71e2862322e346cb2557..ded37c0a8bc2fdb74b088dac64565eb227832943 100644 --- a/lib_enc/updt_enc.c +++ b/lib_enc/updt_enc.c @@ -39,6 +39,11 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#include "prot_fx_enc.h" +#include "ivas_prot_fx.h" +#endif #include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -146,6 +151,7 @@ void updt_enc( return; } +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * updt_IO_switch() * @@ -278,7 +284,7 @@ void updt_IO_switch_enc( return; } - +#endif /*-------------------------------------------------------------------* * updt_enc_common() @@ -293,7 +299,6 @@ void updt_enc_common( /*---------------------------------------------------------------------* * Updates - main main codec parameters *---------------------------------------------------------------------*/ - st->last_sr_core = st->sr_core; st->last_codec_mode = st->codec_mode; st->last_L_frame = st->L_frame; @@ -455,3 +460,225 @@ void updt_enc_common( return; } + + +#ifdef IVAS_FLOAT_FIXED +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + /*---------------------------------------------------------------------* + * Updates - main main codec parameters + *---------------------------------------------------------------------*/ + st->last_sr_core = st->sr_core; + move32(); + st->last_codec_mode = st->codec_mode; + move16(); + st->last_L_frame = st->L_frame; + move16(); + st->last_core = st->core; + move16(); + + st->last_total_brate = st->total_brate; + move32(); + st->last_bits_frame_nominal = st->bits_frame_nominal; + move16(); + st->last_core_brate = st->core_brate; + move32(); + st->last_extl = st->extl; + move16(); + st->last_input_bwidth = st->input_bwidth; + move16(); + st->last_bwidth = st->bwidth; + move16(); + st->last_coder_type_raw = st->coder_type_raw; + move16(); + + test(); + IF( GT_32( st->core_brate, SID_2k40 ) && st->hDtxEnc != NULL ) + { + st->hDtxEnc->last_active_brate = st->total_brate; + move32(); + } + + IF( st->hBWE_TD != NULL ) + { + IF( EQ_16( st->core, HQ_CORE ) ) + { + /* in the HQ core, coder_type is not used so it could have been set to anything */ + st->hBWE_TD->prev_coder_type = GENERIC; + move16(); + } + ELSE + { + st->hBWE_TD->prev_coder_type = st->coder_type; + move16(); + } + } + + test(); + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( GT_32( st->core_brate, SID_2k40 ) ) + { + IF( EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( GE_16( st->hTdCngEnc->act_cnt, BUF_DEC_RATE ) ) + { + st->hTdCngEnc->act_cnt = 0; + move16(); + } + st->hTdCngEnc->act_cnt = add( st->hTdCngEnc->act_cnt, 1 ); + move16(); + + test(); + IF( EQ_16( st->hTdCngEnc->act_cnt, BUF_DEC_RATE ) && st->hTdCngEnc->ho_hist_size > 0 ) + { + st->hTdCngEnc->ho_hist_size = sub( st->hTdCngEnc->ho_hist_size, 1 ); + move16(); + } + } + + test(); + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( GE_16( ++( st->hTdCngEnc->act_cnt2 ), MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->act_cnt2 = MIN_ACT_CNG_UPD; + move16(); + } + + test(); + test(); + test(); + test(); + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + Word32 cng_att_fx32 = 0; + + apply_scale( &cng_att_fx32, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); + + st->hTdCngEnc->CNG_att_fx = extract_l( L_shr( cng_att_fx32, Q16 ) ); // Q23 + } + } + } + + test(); + test(); + test(); + IF( ( EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) && st->hDtxEnc->first_CNG == 0 && EQ_16( st->cng_type, LP_CNG ) ) + { + st->hDtxEnc->first_CNG = 1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the counter of initialization frames + * Limit the max number of init. frames + *-----------------------------------------------------------------*/ + + IF( LT_16( st->ini_frame, MAX_FRAME_COUNTER ) ) + { + st->ini_frame = add( st->ini_frame, 1 ); + } + + /* synchronisation of CNG seeds */ + test(); + test(); + IF( st->hTdCngEnc != NULL && NE_32( st->core_brate, FRAME_NO_DATA ) && NE_32( st->core_brate, SID_2k40 ) && NE_16( st->core, AMR_WB_CORE ) ) + { + Random( &( st->hTdCngEnc->cng_seed ) ); + Random( &( st->hTdCngEnc->cng_ener_seed ) ); + } + + /*---------------------------------------------------------------------* + * Updates - MODE2 + *---------------------------------------------------------------------*/ + + test(); + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + st->codec_mode = MODE2; + move16(); + + st->sr_core = getCoreSamplerateMode2( EVS_MONO, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, 0 ); + move16(); + + Word16 exp; + st->L_frame = BASOP_Util_Divide3232_Scale( st->sr_core, FRAMES_PER_SEC, &exp ); + st->L_frame = shr( st->L_frame, sub( 15, exp ) ); + move16(); + + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + } + ELSE + { + + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + } + + st->igf = getIgfPresent_fx( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode ); + } + + /* update FER clas */ + IF( NE_16( st->core, AMR_WB_CORE ) ) + { + st->last_clas = st->clas; + move16(); + } + + /* Update Core */ + core_encode_update_ivas_fx( st ); + + /*---------------------------------------------------------------------* + * RF mode updates + *---------------------------------------------------------------------*/ + + IF( st->rf_mode ) + { + IF( st->hSC_VBR != NULL ) + { + IF( st->hRF->rf_frame_type == RF_NELP ) + { + st->hSC_VBR->last_nelp_mode = 1; + move16(); + } + ELSE + { + st->hSC_VBR->last_nelp_mode = 0; + move16(); + } + } + } + + st->rf_mode_last = st->rf_mode; + move16(); + + IF( st->Opt_RF_ON ) + { + st->L_frame = L_FRAME; + st->rf_mode = 1; + move16(); + move16(); + } + + /*---------------------------------------------------------------------* + * Other updates + *---------------------------------------------------------------------*/ + + test(); + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem = st->hTcxEnc->tcxltp_norm_corr_past; + } + + return; +} +#endif diff --git a/lib_enc/vad.c b/lib_enc/vad.c index e920caae56e3ae1d44c8252ba230e880d994baca..0ba928ad35502da29aebe420c52b4c01e04dac91 100644 --- a/lib_enc/vad.c +++ b/lib_enc/vad.c @@ -74,7 +74,7 @@ * * VAD initializations *---------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void wb_vad_init( VAD_HANDLE hVAD /* i/o: VAD data handle */ ) @@ -120,13 +120,13 @@ void wb_vad_init( return; } - +#endif /*-----------------------------------------------------------------* * sing_thr_snr_acc() * * accumulate snr_sum with significance thresholds *-----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void sign_thr_snr_acc( float *snr_sum, float snr, @@ -144,13 +144,13 @@ static void sign_thr_snr_acc( return; } - +#endif /*-----------------------------------------------------------------* * dtx_hangover_addition() * * accumulate snr_sum with significance thresholds *-----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED int16_t dtx_hangover_addition( Encoder_State *st, /* i/o: encoder state structure */ const int16_t vad_flag, /* i : VAD flag */ @@ -309,14 +309,14 @@ int16_t dtx_hangover_addition( return flag_dtx; } - +#endif /*-----------------------------------------------------------------* * wb_vad() * * Voice Activity Detector *-----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED int16_t wb_vad( Encoder_State *st, /* i/o: encoder state structure */ const float fr_bands[], /* i : per band input energy (contains 2 vectors) */ @@ -1097,3 +1097,4 @@ int16_t wb_vad( return flag; } +#endif diff --git a/lib_enc/vad_fx.c b/lib_enc/vad_fx.c index d0356f518e67567e254099f52c41e7fad7ee3de4..6723304c71f5fdebe1f216aa28f029cdb4965445 100644 --- a/lib_enc/vad_fx.c +++ b/lib_enc/vad_fx.c @@ -137,6 +137,8 @@ void wb_vad_init_ivas_fx( VAD_HANDLE hVAD /* i/o: VAD data handle */ ) { + hVAD->L_snr_sum_vad_fx = 0; + move32(); hVAD->hangover_cnt = 0; move16(); /* Hangover counter initialized to 0 */ hVAD->nb_active_frames = ACTIVE_FRAMES_FX; @@ -195,8 +197,6 @@ void wb_vad_init_ivas_fx( move16(); hVAD->trigger_SID = 0; move16(); - hVAD->snr_sum_vad = 0; - move16(); hVAD->hangover_terminate_flag = 0; move16(); return; @@ -431,7 +431,208 @@ Word16 dtx_hangover_addition_fx( return flag_dtx; } +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_dtx_hangover_addition_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 number of DTX-HO frames CLDFB wants to reduce */ + Word16 *vad_hover_flag_ptr, + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + Word16 *rem_dtx_ho ) +{ + Word16 hangover_short_dtx; + Word16 flag_dtx; + Word16 tmp; + if ( hNoiseEst == NULL ) + { + hNoiseEst = st_fx->hNoiseEst; + move16(); + } + + if ( hVAD == NULL ) + { + move16(); + hVAD = st_fx->hVAD; + } + + + flag_dtx = 0; + move16(); + + /* Determine initial hangover length */ + hangover_short_dtx = 2; + move16(); + + test(); + test(); + if ( ( ( LT_16( lp_snr, ( 16 * 256 ) ) ) && ( NE_16( st_fx->input_bwidth, NB ) ) ) || ( GT_16( hVAD->prim_act_he_fx, 31130 ) ) ) /*.95*Q15*/ + { + hangover_short_dtx = 3; + move16(); + } + + /* Adjust hangover according to activity history */ + if ( GT_16( hVAD->vad_prim_cnt_16, 12 ) ) /* 12 requires roughly > 80% primary activity */ + { + hangover_short_dtx = add( hangover_short_dtx, 2 ); + } + + if ( GT_16( hVAD->vad_flag_cnt_50, 40 ) ) /* 40 requires roughtly > 80% flag activity */ + { + hangover_short_dtx = add( hangover_short_dtx, 5 ); + } + + /* Keep hangover_short lower than maximum hangover count */ + if ( GT_16( hangover_short_dtx, HANGOVER_LONG_FX - 1 ) ) + { + hangover_short_dtx = ( HANGOVER_LONG_FX - 1 ); + move16(); + } + + /* Only allow short HO if not sufficient active frames in clean speech*/ + + tmp = 3; + move16(); /* default for EVS*/ + if ( EQ_16( st_fx->core, AMR_WB_CORE ) ) + { + tmp = 2; + move16(); /* default for AMRWBIO*/ + } + + /* need to be a bit stricter with the DTXHO in very clean WB, SWB cond for EVS12k8VAD section */ + test(); + test(); + if ( ( NE_16( st_fx->input_bwidth, NB ) ) /* WB or SWB or FB */ + && ( NE_16( st_fx->core, AMR_WB_CORE ) ) && ( GT_16( lp_snr, 25 * 256 ) ) ) + { + tmp = 2; + move16(); + } + + /* limit dtx hangover addition up to "tmp" frames in clean cond */ + IF( tmp != 0 ) + { + test(); + test(); + test(); + if ( ( GT_16( hangover_short_dtx, tmp ) ) && ( ( LT_16( hVAD->vad_prim_cnt_16, 7 ) ) || ( ( GT_16( lp_snr, ( 16 * 256 ) ) ) && ( LT_16( hVAD->prim_act_he_fx, 27853 ) ) /*0.85f*2^15 */ + ) ) ) + { + hangover_short_dtx = tmp; + move16(); + } + } + + + /* hangover adjustment from combined FFT+CLDFBVAD */ + IF( NE_16( st_fx->core, AMR_WB_CORE ) ) + { + hangover_short_dtx = sub( hangover_short_dtx, cldfb_subtraction ); + hangover_short_dtx = s_max( hangover_short_dtx, 0 ); + } + IF( vad_flag != 0 ) /* Speech present */ + { + flag_dtx = 1; + move16(); + + /* Add hangover after sufficient # of active frames or sufficient activity during last second */ + test(); + if ( ( GE_16( hVAD->nb_active_frames, ACTIVE_FRAMES_FX ) ) || ( GT_16( hVAD->vad_flag_cnt_50, 45 ) ) ) /* 45 requires roughly > 90% flag activity */ + { + hVAD->hangover_cnt_dtx = 0; + move16(); + } + /* inside HO period */ + test(); + if ( ( LT_16( hVAD->hangover_cnt_dtx, HANGOVER_LONG_FX ) ) && ( hVAD->hangover_cnt_dtx != 0 ) ) + { + hVAD->hangover_cnt_dtx = add( hVAD->hangover_cnt_dtx, 1 ); + } + hVAD->hangover_terminate_flag = 0; + move16(); /* float fix FIX_HO_TERMINATE */ + + /* Music hangover when music detected */ + test(); + test(); + test(); + if ( ( GT_16( hVAD->prim_act_he_fx, 31129 ) ) && ( GT_16( hNoiseEst->Etot_lp_fx, 40 * 256 ) ) && ( GT_16( hVAD->vad_prim_cnt_16, 14 ) ) && ( GT_16( hVAD->vad_flag_cnt_50, 48 ) ) ) /* 45 requires roughly > 95% flag activity */ + { + hVAD->hangover_cnt_music = 0; + move16(); + } + + /* inside Music HO period */ + test(); + if ( ( LT_16( hVAD->hangover_cnt_music, HANGOVER_LONG_MUSIC_FX ) ) && ( hVAD->hangover_cnt_music != 0 ) ) + { + hVAD->hangover_cnt_music = add( hVAD->hangover_cnt_music, 1 ); + move16(); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + if ( LT_16( hVAD->hangover_cnt_dtx, HANGOVER_LONG_FX ) ) /* inside HO period */ + { + hVAD->hangover_cnt_dtx = add( hVAD->hangover_cnt_dtx, 1 ); + move16(); + } + if ( LT_16( hVAD->hangover_cnt_music, HANGOVER_LONG_MUSIC_FX ) ) /* inside HO period */ + { + hVAD->hangover_cnt_music = add( hVAD->hangover_cnt_music, 1 ); + move16(); + } + + /* fast terminate DTX hangover if st->hangover_terminate_flag is set */ + IF( hVAD->hangover_terminate_flag != 0 ) + { + hVAD->hangover_cnt = HANGOVER_LONG_FX; + move16(); + hVAD->hangover_cnt_dtx = HANGOVER_LONG_FX; + move16(); + hVAD->hangover_terminate_flag = 0; + move16(); + /* Only shorten music hangover when low energy frames */ + if ( LT_16( hNoiseEst->Etot_lp_fx, 20 * 256 ) ) + { + hVAD->hangover_cnt_music = HANGOVER_LONG_MUSIC_FX; + move16(); + } + } + + if ( LE_16( hVAD->hangover_cnt_dtx, hangover_short_dtx ) ) /* "hard" hangover */ + { + flag_dtx = 1; + move16(); + } + + if ( LE_16( hVAD->hangover_cnt_music, 15 ) ) /* "hard" hangover music */ + { + flag_dtx = 1; + move16(); + } + } + + + test(); + + IF( flag_dtx != 0 && st_fx->localVAD == 0 ) + { + *vad_hover_flag_ptr = 1; + move16(); + if ( rem_dtx_ho != NULL ) + { + *rem_dtx_ho = s_max( sub( hangover_short_dtx, hVAD->hangover_cnt_dtx ), 0 ); + move16(); + } + } + + return flag_dtx; +} +#endif /*-----------------------------------------------------------------* * wb_vad() * @@ -1766,6 +1967,20 @@ Word16 wb_vad_ivas_fx( #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif + Word16 L_msnr_e = 0, L_mssnr_e = 0, L_mssnr_hov_e = 0, L_msnr18_e = 0, L_msnr19_e = 0; + move16(); /*L_msnr_e*/ + move16(); /*L_mssnr_e*/ + move16(); /*L_mssnr_hov_e*/ + move16(); /*L_msnr18_e*/ + move16(); /*L_msnr19_e*/ + move16(); /*Overflow*/ + move32(); /*L_mssnr*/ + move16(); /*thr1*/ + move16(); /*thr2*/ + move16(); /*nk*/ + move16(); /*nc*/ + move16(); /*th_clean*/ + move16(); /*flag*/ if ( hNoiseEst == NULL ) { @@ -2165,31 +2380,43 @@ Word16 wb_vad_ivas_fx( tmp = s_min( tmp, 16384 ); /* Q13, ftmp = min(ftmp, 2.0f); */ tmp1 = s_min( tmp1, 16384 ); /* Q13, ftmp1 = min(ftmp1, 2.0f); */ - L_msnr = L_deposit_l( tmp ); /*msnr = 1*tmp;*/ + Word16 norm_tmp = norm_l( tmp ); + Word32 scaled_tmp = L_shl( tmp, norm_tmp ); /*13+norm_tmp*/ + L_msnr = scaled_tmp; + move32(); + L_msnr_e = sub( 18, norm_tmp ); FOR( j = 1; j < stmp; j++ ) { /* Q13*Q13 +1 -16 +2 = Q13 */ - L_msnr = L_shl( Mult_32_16( L_msnr, tmp ), 2 ); /*Q13 , msnr *= ftmp;*/ + L_msnr = Mult_32_32( L_msnr, scaled_tmp ); /*L_msnr_e , msnr *= ftmp;*/ } - L_mssnr = L_add( L_mssnr, L_msnr ); /*Q13 mssnr += msnr;*/ + L_msnr_e = imult1616( L_msnr_e, stmp ); + L_mssnr = BASOP_Util_Add_Mant32Exp( L_mssnr, L_mssnr_e, L_msnr, L_msnr_e, &L_mssnr_e ); /*L_mssnr_e mssnr += msnr;*/ - if ( EQ_16( i, 18 ) ) + IF( EQ_16( i, 18 ) ) { - L_msnr18 = L_add( L_msnr, 0 ); /*Q13 msnr18 = msnr; */ + L_msnr18 = L_add( L_msnr, 0 ); /*L_msnr_e msnr18 = msnr; */ + L_msnr18_e = L_msnr_e; + move16(); } - if ( EQ_16( i, 19 ) ) + IF( EQ_16( i, 19 ) ) { - L_msnr19 = L_add( L_msnr, 0 ); /* Q13 , msnr19 = msnr; */ + L_msnr19 = L_add( L_msnr, 0 ); /* L_msnr_e , msnr19 = msnr; */ + L_msnr19_e = L_msnr_e; + move16(); } - L_msnr = L_deposit_l( tmp1 ); /* Q13, msnr = 1*tmp1 ;*/ - + norm_tmp = norm_l( tmp1 ); + scaled_tmp = L_shl( tmp1, norm_tmp ); /*13+norm_tmp*/ + L_msnr = scaled_tmp; + L_msnr_e = sub( 18, norm_tmp ); FOR( j = 1; j < stmp; j++ ) { - L_msnr = L_shl( Mult_32_16( L_msnr, tmp1 ), 2 ); /*Q13 msnr *= ftmp1;*/ + L_msnr = Mult_32_32( L_msnr, scaled_tmp ); /*L_msnr_e msnr *= ftmp1;*/ } - L_mssnr_hov = L_add( L_mssnr_hov, L_msnr ); /*Q13 mssnr_hov += msnr; */ + L_msnr_e = imult1616( L_msnr_e, stmp ); + L_mssnr_hov = BASOP_Util_Add_Mant32Exp( L_mssnr_hov, L_mssnr_hov_e, L_msnr, L_msnr_e, &L_mssnr_hov_e ); /*L_mssnr_hov_e mssnr_hov += msnr; */ /* recompute after he1 modifications */ /* snr[i] = fr_enr / st->bckr[i] = L_tmp1/st->bckr[i];*/ @@ -2278,12 +2505,16 @@ Word16 wb_vad_ivas_fx( { /* mssnr = (mssnr + 3*(msnr18 + msnr19)) * 0.77f; */ /* mssnr = (mssnr*.77f + 2.31f*(msnr18 + msnr19)); */ - L_tmp1 = Mult_32_16( L_mssnr, 25231 ); /* Q13+Q15+1-16 --> Q13 */ - L_tmp = Mult_32_16( L_shl( L_add( L_msnr18, L_msnr19 ), 2 ), 18924 ); /* Q(13+2)+Q(15-2)+1-16 --> Q13 */ - L_tmp = L_add( L_tmp1, L_tmp ); - if ( GT_32( L_tmp, L_mssnr ) ) + Word16 L_tmp_e; + L_tmp1 = Mult_32_16( L_mssnr, 25231 ); /* Q13+Q15+1-16 --> L_mssnr_e */ + L_tmp = Mult_32_16( BASOP_Util_Add_Mant32Exp( L_msnr18, L_msnr18_e, L_msnr19, L_msnr19_e, &L_tmp_e ), 18924 ); /* Q(31-L_tmp1_e)+Q(15-2)+1-16 -->exp= L_msnr_e +2*/ + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp1, L_mssnr_e, L_tmp, add( L_tmp_e, 2 ), &L_tmp_e ); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, L_mssnr, L_mssnr_e ), 1 ) ) { L_mssnr = L_tmp; + L_mssnr_e = L_tmp_e; + move32(); + move16(); } } ELSE IF( ( snr_idx != 0 ) && GT_16( nb_sig_snr, 13 ) ) @@ -2291,9 +2522,9 @@ Word16 wb_vad_ivas_fx( L_tmp = -126976; move32(); /* -15.5 Q13 */ L_tmp = L_mac0( L_tmp, 80, lp_snr ); /* 2.5f(Q5)*lp_snr(Q8) - 15.5f */ - if ( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ + IF( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ { - L_mssnr = L_add( L_mssnr, L_tmp ); /* mssnr += 2.5f*lp_snr - 15.5f; */ + L_mssnr = BASOP_Util_Add_Mant32Exp( L_mssnr, L_mssnr_e, L_tmp, 18, &L_mssnr_e ); /* mssnr += 2.5f*lp_snr - 15.5f; */ } } @@ -2482,7 +2713,7 @@ Word16 wb_vad_ivas_fx( flag_he1 = 0; move16(); - IF( GT_32( L_mssnr, L_vad_thr ) ) + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_mssnr, L_mssnr_e, L_vad_thr, 18 ), 1 ) ) { flag_he1 = 1; move16(); /* he1 primary decision */ @@ -2544,7 +2775,7 @@ Word16 wb_vad_ivas_fx( test(); IF( flag_he1 == 0 && hVAD->soft_hangover > 0 ) { - IF( GT_32( L_mssnr_hov, L_vad_thr ) ) + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_mssnr_hov, L_mssnr_hov_e, L_vad_thr, 18 ), 1 ) ) { flag_he1 = 1; move16(); @@ -2676,9 +2907,10 @@ Word16 wb_vad_ivas_fx( hVAD->nb_active_frames = 0; move16(); - if ( LT_16( hVAD->hangover_cnt, HANGOVER_LONG_FX ) ) /* inside HO period */ + IF( LT_16( hVAD->hangover_cnt, HANGOVER_LONG_FX ) ) /* inside HO period */ { hVAD->hangover_cnt = add( hVAD->hangover_cnt, 1 ); + move16(); } diff --git a/lib_enc/vad_param_updt.c b/lib_enc/vad_param_updt.c index 6f52d2be915d1f1db93619d319d448134d222a3f..9a472c1be15200f9721cb61fccfaf5897a4671cf 100644 --- a/lib_enc/vad_param_updt.c +++ b/lib_enc/vad_param_updt.c @@ -46,7 +46,7 @@ * * Update parameters used by the VAD or DTX *--------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void vad_param_updt( Encoder_State *st, /* i/o: encoder state structure */ const float corr_shift, /* i : correlation shift */ @@ -171,3 +171,4 @@ void vad_param_updt( return; } +#endif diff --git a/lib_enc/vbr_average_rate.c b/lib_enc/vbr_average_rate.c index a3dc254d02be6ece3a4c405043fcae5a85c60bdc..0f758041af4487db951c4ca63d28a4e684a9dbda 100644 --- a/lib_enc/vbr_average_rate.c +++ b/lib_enc/vbr_average_rate.c @@ -52,7 +52,7 @@ * * SC-VBR update average data rate *------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void update_average_rate( SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ const int32_t core_brate /* i : core bitrate */ @@ -197,3 +197,4 @@ void update_average_rate( return; } +#endif diff --git a/lib_enc/vbr_average_rate_fx.c b/lib_enc/vbr_average_rate_fx.c index fe5766eea883fd5a3fd87d8ce8f7265d06b0c09b..931333ebe264c01ecdf50d5a276127413b5ad34f 100644 --- a/lib_enc/vbr_average_rate_fx.c +++ b/lib_enc/vbr_average_rate_fx.c @@ -51,6 +51,7 @@ void update_average_rate_fx( Word32 L_tmp1, L_tmp2; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif Word16 exp, recip, Qrecip; @@ -61,35 +62,41 @@ void update_average_rate_fx( st->global_avr_rate=0.99*st->global_avr_rate+0.01*st->sum_of_rates. This will avoid veriables growing indefinitely while providing a good long term average rate */ - IF( LT_32( hSC_VBR->frame_cnt_ratewin_fx, 1000 ) ) + IF( LT_32( hSC_VBR->global_frame_cnt, 1000 ) ) { - hSC_VBR->frame_cnt_ratewin_fx = add( hSC_VBR->frame_cnt_ratewin_fx, 1 ); + hSC_VBR->global_frame_cnt = add( hSC_VBR->global_frame_cnt, 1 ); + move16(); /*st->global_avr_rate = (st->global_avr_rate * (st->global_frame_cnt-1) + st->sum_of_rates) / st->global_frame_cnt; */ - exp = norm_s( hSC_VBR->frame_cnt_ratewin_fx ); - tmp = shl( hSC_VBR->frame_cnt_ratewin_fx, exp ); + exp = norm_s( hSC_VBR->global_frame_cnt ); + tmp = shl( hSC_VBR->global_frame_cnt, exp ); recip = div_s( 16384, tmp ); - Qrecip = 15 - ( exp - 14 ); + Qrecip = sub( 15, sub( exp, 14 ) ); - IF( GT_32( hSC_VBR->frame_cnt_ratewin_fx, 1 ) ) + IF( GT_32( hSC_VBR->global_frame_cnt, 1 ) ) { - tmp = div_s( sub( hSC_VBR->frame_cnt_ratewin_fx, 1 ), hSC_VBR->frame_cnt_ratewin_fx ); /*Q15*/ - L_tmp1 = Mult_32_16( hSC_VBR->global_avr_rate_fx, tmp ); /* Q13*Q15 = Q13 */ + tmp = div_s( sub( hSC_VBR->global_frame_cnt, 1 ), hSC_VBR->global_frame_cnt ); /*Q15*/ + L_tmp1 = Mult_32_16( hSC_VBR->global_avr_rate_fx, tmp ); /* Q13*Q15 = Q13 */ L_tmp2 = Mult_32_16( hSC_VBR->sum_of_rates_fx, recip ); /*Q13*Qrecip = 13+Qrecip+1-16 = Qrecip-2 */ - hSC_VBR->global_avr_rate_fx = L_add( L_tmp1, L_shl( L_tmp2, 13 - ( Qrecip - 2 ) ) ); /*Q13 */ + hSC_VBR->global_avr_rate_fx = L_add( L_tmp1, L_shl( L_tmp2, sub( 13, ( sub( Qrecip, 2 ) ) ) ) ); /*Q13 */ + move32(); } ELSE { hSC_VBR->global_avr_rate_fx = hSC_VBR->sum_of_rates_fx; /*handle the first frame*/ + move32(); } /* Q13 */ } ELSE { - /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; */ + /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; + 0.01f=328 (Q15) , .99f=32441 (Q15) + */ hSC_VBR->global_avr_rate_fx = L_add( Mult_32_16( hSC_VBR->sum_of_rates_fx, 328 ), Mult_32_16( hSC_VBR->global_avr_rate_fx, 32441 ) ); /*Q13 */ + move32(); } @@ -97,6 +104,7 @@ void update_average_rate_fx( { /* st->sum_of_rates = (float) (RATEWIN * VBR_ADR_MAX_TARGET * 10); */ hSC_VBR->sum_of_rates_fx = L_shl( L_mult0( RATEWIN, VBR_ADR_MAX_TARGET_x10_Q1 ), 12 ); /*Q13 */ + move32(); } /* target = VBR_ADR_MAX_TARGET * 10 * RATEWIN; */ @@ -107,6 +115,7 @@ void update_average_rate_fx( /* Check the vad snr values to table the noisey/not noisey decision */ test(); + /*67=17152 (Q8)*/ IF( LT_16( hSC_VBR->SNR_THLD_fx, 17152 ) ) /*Q8 */ /* Currently in QFF mode. The bumpup thresholds are slightly relaxed for noisy speech. */ { @@ -114,7 +123,9 @@ void update_average_rate_fx( Use 3.5 steps to quickly ramp up the rate control to reduce the settling time */ /* st->SNR_THLD += 3.5f; */ + /*896=3.5 (Q8)*/ hSC_VBR->SNR_THLD_fx = add( hSC_VBR->SNR_THLD_fx, 896 ); /*Q8 */ + move16(); } ELSE IF( hSC_VBR->mode_QQF == 0 && GT_32( hSC_VBR->sum_of_rates_fx, target_fx ) ) /* Now SNR_THLD is in the max allowed. Sill the global average is higher and last RATEWIN frames have a higher agerage than the target rate. Now slightly @@ -135,6 +146,7 @@ void update_average_rate_fx( move16(); /* This will be triggered only if the gloabl average rate is considerablly higher than the target rate. Keep a higher threshold to avoid short term rate increases over the target rate. */ + /* 3440640=420.0f Q(13) */ IF( GT_32( hSC_VBR->global_avr_rate_fx, L_add( target_fx, 3440640 ) ) ) /* Last resort rate control. This is a safer rate control mechanism by increasing NELPS */ { hSC_VBR->Last_Resort = 1; @@ -175,19 +187,20 @@ void update_average_rate_fx( move16(); } ELSE - { + { /*15360=60 (Q8)*/ IF( GE_16( hSC_VBR->SNR_THLD_fx, 15360 ) ) - { + { /*384=1.5 (Q8)*/ hSC_VBR->SNR_THLD_fx = sub( hSC_VBR->SNR_THLD_fx, 384 ); /*Q8 */ + move16(); } ELSE - { + { /*15360=60 (Q8)*/ hSC_VBR->SNR_THLD_fx = 15360; move16(); } } } - + /*983040=120 (Q13)*/ IF( LT_32( hSC_VBR->global_avr_rate_fx, L_sub( target_fx, 983040 ) ) ) /* In QFF mode and global rate is less than target rate-0.2kbps. We can send some Q frames to F frames to improve the quality */ { @@ -208,6 +221,7 @@ void update_average_rate_fx( L_tmp = L_mult0( RATEWIN, VBR_ADR_MAX_TARGET_x10_Q1 ); L_tmp = L_shl( L_tmp, 12 ); L_tmp = L_sub( avratetarg_fx, L_tmp ); + /*27307=(1000/(RATEWIN))Q14 */ tmp = extract_h( L_shl( Mult_32_16( L_tmp, 27307 ), 4 ) ); hSC_VBR->pattern_m = tmp; move16(); @@ -234,13 +248,13 @@ void update_average_rate_fx( } hSC_VBR->sum_of_rates_fx = 0; - move16(); + move32(); hSC_VBR->numactive = 0; move16(); } hSC_VBR->numactive = add( hSC_VBR->numactive, 1 ); - + move16(); /* sum the total number of bits (in kbytes) * 10 here */ /*st->sum_of_rates += (hSC_VBR->core_brate / 1000.0f) * 10; */ L_tmp = L_shl( Mult_32_16( core_brate_fx, 20972 ), 7 ); @@ -249,6 +263,6 @@ void update_average_rate_fx( #else hSC_VBR->sum_of_rates_fx = L_add( hSC_VBR->sum_of_rates_fx, L_tmp ); #endif - + move32(); return; } diff --git a/lib_enc/voiced_enc.c b/lib_enc/voiced_enc.c index 08d1efefbba6698b6f41709f33dc41c5e41946d5..183ec84817e3ec0beedf5087e2417da11ae46f9a 100644 --- a/lib_enc/voiced_enc.c +++ b/lib_enc/voiced_enc.c @@ -1155,10 +1155,17 @@ void sc_vbr_enc_init( hSC_VBR->set_ppp_generic = 0; hSC_VBR->Q_to_F = 0; - hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ +#ifndef IVAS_FLOAT_FIXED hSC_VBR->sum_of_rates = 0.0f; /* sum of the rates of past 600 active frames*/ hSC_VBR->global_avr_rate = 0.0f; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ +#else + hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + move32(); + hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + move32(); +#endif + hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ hSC_VBR->rate_control = 0; hSC_VBR->SNR_THLD = 67.0f; diff --git a/lib_enc/voiced_enc_fx.c b/lib_enc/voiced_enc_fx.c index b9e0b9c425c7dcbf19ffd794b99f6686696ab86d..cf08ebe5af47d25336b81e8abc4dc077fc654f87 100644 --- a/lib_enc/voiced_enc_fx.c +++ b/lib_enc/voiced_enc_fx.c @@ -1688,10 +1688,11 @@ void sc_vbr_enc_init_fx( hSC_VBR->Q_to_F = 0; move16(); - hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ - hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ - hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - hSC_VBR->frame_cnt_ratewin_fx = 0; /* 600 active frame block count. Used to update the global rate*/ + hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ + move16(); hSC_VBR->rate_control = 0; move16(); hSC_VBR->SNR_THLD_fx = SNR_THLD_FX_Q8; diff --git a/lib_rend/ivas_allrad_dec.c b/lib_rend/ivas_allrad_dec.c index 6b780f9bb46d43fc29608b5690e9f5b00ff00f90..09e2a09340100742178ed12ad2a117656e48deb0 100644 --- a/lib_rend/ivas_allrad_dec.c +++ b/lib_rend/ivas_allrad_dec.c @@ -1,3 +1,4 @@ + /****************************************************************************************************** (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, @@ -166,9 +167,9 @@ ivas_error ivas_sba_get_hoa_dec_matrix( #else #define TEMP_VAL 1963413621 // Q37 (1.f / num_td) ivas_error ivas_sba_get_hoa_dec_matrix_fx( - const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ - Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ - const Word16 ambisonics_order /* i : Ambisonics order */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ + Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix, Q29 */ + const Word16 ambisonics_order /* i : Ambisonics order */ ) { Word16 i, j, k; diff --git a/lib_rend/ivas_dirac_ana.c b/lib_rend/ivas_dirac_ana.c index ec9a05dbd79a1c2dcd639cb3f528a5bd82921aa2..2b2f9cc1ce6cda33dddec8b86962ad8d33c95492 100644 --- a/lib_rend/ivas_dirac_ana.c +++ b/lib_rend/ivas_dirac_ana.c @@ -379,10 +379,10 @@ void ivas_dirac_ana_close( #ifdef IVAS_FLOAT_FIXED void ivas_dirac_ana_fx( - DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ - Word32 data_fx[][L_FRAME48k], /* i/o: Input / transport audio signals */ - const Word16 input_frame, /* i : Input frame size */ - const Word16 nchan_transport /* i : Number of transport channels */ + DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ + Word32 data_fx[][L_FRAME48k], /* i/o: Input / transport audio signals, Q7 */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport /* i : Number of transport channels */ ) { Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; @@ -442,12 +442,12 @@ void ivas_dirac_ana( /* Estimate MASA parameters from the SBA signals */ static void ivas_dirac_param_est_ana_fx( DIRAC_ANA_HANDLE hDirAC, - Word32 data_fx[][L_FRAME48k], - Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + Word32 data_fx[][L_FRAME48k], /* Q7 */ + Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q22 */ + Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q22 */ + Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q30 */ + Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Qx */ + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Qx */ const Word16 input_frame ) { Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -475,7 +475,6 @@ static void ivas_dirac_param_est_ana_fx( Word16 q_factor_intensity, q_factor_intensity_old = 0; Word16 q_factor_energy = 0, q_factor_energy_old = 0; Word16 exp = 0, exp_div = 0; - // Word16 exp2; num_freq_bands = hDirAC->nbands; /* l_ts = input_frame / CLDFB_NO_COL_MAX; */ l_ts = shr( input_frame, 4 ); @@ -554,7 +553,7 @@ static void ivas_dirac_param_est_ana_fx( /* Power estimation for diffuseness */ computeReferencePower_ana_fx( hDirAC->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); //( 2 * ( scale_fact - Q1 ) - 31 - 1 ); // computeReferencePower_ana( hDirAC->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, reference_power[ts], num_freq_bands ); - // exp2 = sub( shl( scale_fact, 1 ), 31 ); + /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hDirAC->index_buffer_intensity = add( ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */ move16(); @@ -893,7 +892,7 @@ static void ivas_dirac_param_est_ana( #ifdef IVAS_FLOAT_FIXED /* Compute downmix */ static void ivas_dirac_dmx_fx( - Word32 data_in_fx[][L_FRAME48k], + Word32 data_in_fx[][L_FRAME48k], /* Qx (same as the input Q) */ const Word16 input_frame, const Word16 nchan_transport ) { diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 472e70a26e8f7edfd4361ba6d0d56f22bd1c1734..21c49189e78f281de440d196532e73da5b481157 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -121,7 +121,7 @@ typedef struct parambin_rend_config_data *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_f[], const Word16 nchan_transport, const Word16 subframe ); +static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_f[] /*Q11*/, const Word16 nchan_transport, const Word16 subframe ); #else static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t nchan_transport, const int16_t subframe ); @@ -129,11 +129,11 @@ static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_BIN_HANDLE hDiracDecBin, #endif #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX], Word32 decIm[][CLDFB_NO_CHANNELS_MAX] ); +static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME] /*q_inp*/[CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 decIm[] /*q_inp*/[CLDFB_NO_CHANNELS_MAX] ); #endif #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 Rmat_fx[3][3], const Word16 subframe, const Word16 isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData, Word16 q ); +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q*/, Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q*/, Word32 Rmat_fx[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData, Word16 q ); #else static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData ); @@ -141,13 +141,13 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN #endif #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, Word32 Rmat[3][3], const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData ); +static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, Word32 Rmat[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData ); -static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[], Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat ); +static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat ); -static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] ); +static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ ); -static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] ); +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ ); #endif #ifndef IVAS_FLOAT_FIXED static void ivas_dirac_dec_binaural_process_output( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t processReverb, const int16_t subframe ); @@ -170,7 +170,7 @@ static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word1 static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t useCachedValue ); #endif #ifdef IVAS_FLOAT_FIXED -static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked ); +static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked ); #else static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t isHeadtracked ); @@ -179,16 +179,16 @@ static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Ai static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] ); #endif #ifdef IVAS_FLOAT_FIXED -static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[], const Word16 subframe ); +static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[] /*Q11*/, const Word16 subframe ); #else static void ivas_masa_ext_rend_parambin_internal( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t subframe ); #endif #ifdef IVAS_FLOAT_FIXED -static void formulate2x2MixingMatrix_fx( Word32 Ein1_fx, Word32 Ein2_fx, Word16 q_Ein, Word32 CinRe_fx, Word32 CinIm_fx, Word16 q_Cin, Word32 Eout1_fx, Word32 Eout2_fx, Word16 q_Eout, Word32 CoutRe_fx, Word32 CoutIm_fx, Word16 q_Cout, Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_M, const Word16 regularizationFactor_fx ); +static void formulate2x2MixingMatrix_fx( Word32 Ein1_fx /*q_Ein*/, Word32 Ein2_fx /*q_Ein*/, Word16 q_Ein, Word32 CinRe_fx /*q_Cin*/, Word32 CinIm_fx /*q_Cin*/, Word16 q_Cin, Word32 Eout1_fx /*q_Eout*/, Word32 Eout2_fx /*q_Eout*/, Word16 q_Eout, Word32 CoutRe_fx /*q_Cout*/, Word32 CoutIm_fx /*q_Cout*/, Word16 q_Cout, Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*Q31*/, Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word16 *q_M, const Word16 regularizationFactor_fx /*Q14*/ ); -static void matrixMul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_out ); +static void matrixMul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word16 *q_out ); -static void matrixTransp2Mul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Word16 *q_out ); +static void matrixTransp2Mul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word16 *q_out ); #endif // 1 /*------------------------------------------------------------------------- @@ -460,10 +460,10 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( tmp_e = 0; move16(); } - tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q30*/ - tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); //*binCenterFreq_fx * EVS_PI / 550.0f*/ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); + tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q15-tmp_e*/ + tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); /* Q15 */ //*binCenterFreq_fx * EVS_PI / 550.0f*/ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ /* Q30 */ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */ move32(); move32(); } @@ -562,7 +562,7 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( } } - hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); /* Q14 */ move16(); st_ivas->hDiracDecBin = hDiracDecBin; @@ -689,13 +689,13 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx( { FOR( j = 0; j < HRTF_SH_CHANNELS; j++ ) { - Copy( hrtfShCoeffsRe_fx[i][j], hrtfParambin->hrtfShCoeffsRe_fx[i][j], HRTF_NUM_BINS ); - Copy( hrtfShCoeffsIm_fx[i][j], hrtfParambin->hrtfShCoeffsIm_fx[i][j], HRTF_NUM_BINS ); + Copy( hrtfShCoeffsRe_fx[i][j], hrtfParambin->hrtfShCoeffsRe_fx[i][j], HRTF_NUM_BINS ); /*Q14*/ + Copy( hrtfShCoeffsIm_fx[i][j], hrtfParambin->hrtfShCoeffsIm_fx[i][j], HRTF_NUM_BINS ); /*Q14*/ } } - Copy32( parametricReverberationTimes_fx, hrtfParambin->parametricReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX ); - Copy32( parametricReverberationEneCorrections_fx, hrtfParambin->parametricReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX ); - Copy32( parametricEarlyPartEneCorrection_fx, hrtfParambin->parametricEarlyPartEneCorrection_fx, CLDFB_NO_CHANNELS_MAX ); + Copy32( parametricReverberationTimes_fx, hrtfParambin->parametricReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX ); /*Q31*/ + Copy32( parametricReverberationEneCorrections_fx, hrtfParambin->parametricReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX ); /*Q31*/ + Copy32( parametricEarlyPartEneCorrection_fx, hrtfParambin->parametricEarlyPartEneCorrection_fx, CLDFB_NO_CHANNELS_MAX ); /*Q28*/ *hHrtfParambin = hrtfParambin; } @@ -830,7 +830,7 @@ void ivas_dirac_dec_binaural_render_fx( UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */ UWord16 *nSamplesAvailable, /* o : number of CLDFB slots still to render */ const Word16 nchan_transport, /* i : number of transport channels */ - Word32 *output_f[] /* o : rendered time signal */ + Word32 *output_f[] /* o : rendered time signal, Q11 */ ) { Word16 slots_to_render, first_sf, last_sf, subframe_idx; @@ -908,9 +908,9 @@ void ivas_dirac_dec_binaural_render_fx( *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED void ivas_dirac_dec_binaural_sba_gain_fx( - Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output */ - const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ - const Word16 output_frame /* i : output frame length */ + Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output, inp Qx, out Qx-1 */ + const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ + const Word16 output_frame /* i : output frame length */ ) { Word16 n; @@ -918,18 +918,18 @@ void ivas_dirac_dec_binaural_sba_gain_fx( IF( EQ_16( nchan_remapped, 1 ) ) { - gain = 23681; + gain = 23681; /*Q14*/ move16(); } ELSE { - gain = 22376; + gain = 22376; /*Q14*/ move16(); } FOR( n = 0; n < nchan_remapped; n++ ) { - v_multc_fixed_16( output[n], gain, output[n], output_frame ); + v_multc_fixed_16( output[n], gain, output[n], output_frame ); /* Qx to Qx-1*/ } return; @@ -1214,7 +1214,7 @@ static void ivas_dirac_dec_binaural_internal( static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, - Word32 *output_fx[], + Word32 *output_fx[], /*Q11*/ const Word16 nchan_transport, const Word16 subframe ) { @@ -1275,7 +1275,7 @@ static void ivas_dirac_dec_binaural_internal_fx( move16(); IF( st_ivas->hMasa != NULL ) { - config_data.qualityBasedSmFactor_fx = L_deposit_h( st_ivas->hMasa->data.dir_decode_quality_fx ); + config_data.qualityBasedSmFactor_fx = L_deposit_h( st_ivas->hMasa->data.dir_decode_quality_fx ); // Q31 } ELSE { @@ -1486,12 +1486,12 @@ static void ivas_dirac_dec_binaural_internal_fx( move16(); FOR( Word16 idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { - Scale_sig32( st_ivas->hSpar->hFbMixer->pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[idx], IVAS_MAX_NUM_FB_BANDS, Q31 - Q22 ); + Scale_sig32( st_ivas->hSpar->hFbMixer->pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[idx], IVAS_MAX_NUM_FB_BANDS, Q31 - Q22 ); /*Q31 to Q22*/ } ivas_sba_prototype_renderer_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe ); FOR( Word16 idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { - Scale_sig32( st_ivas->hSpar->hFbMixer->pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[idx], IVAS_MAX_NUM_FB_BANDS, Q22 - Q31 ); + Scale_sig32( st_ivas->hSpar->hFbMixer->pFb->fb_bin_to_band.pp_cldfb_weights_per_spar_band_fx[idx], IVAS_MAX_NUM_FB_BANDS, Q22 - Q31 ); /*Q31 to Q22*/ } } @@ -1501,8 +1501,8 @@ static void ivas_dirac_dec_binaural_internal_fx( { FOR( slot = 0; slot < 4; slot++ ) { - scale_sig32( Cldfb_RealBuffer_in_fx[cha][slot], 60, sub( q_inp, q_cldfb[cha][slot] ) ); - scale_sig32( Cldfb_ImagBuffer_in_fx[cha][slot], 60, sub( q_inp, q_cldfb[cha][slot] ) ); + scale_sig32( Cldfb_RealBuffer_in_fx[cha][slot], 60, sub( q_inp, q_cldfb[cha][slot] ) ); // Q6 + scale_sig32( Cldfb_ImagBuffer_in_fx[cha][slot], 60, sub( q_inp, q_cldfb[cha][slot] ) ); // Q6 } } @@ -1553,8 +1553,8 @@ static void ivas_dirac_dec_binaural_internal_fx( { FOR( Word16 k = 0; k < 60; k++ ) { - Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); - Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); + Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); // q + Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); // q move32(); move32(); } @@ -1621,21 +1621,21 @@ static void ivas_dirac_dec_binaural_internal_fx( { FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) { - Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); - Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); - Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); - Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); - Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); - Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat } FOR( slot = 0; slot < nchanSeparateChannels; slot++ ) { - Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); - Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat } } hDiracDecBin->q_processMtx = q_mat; @@ -1730,11 +1730,11 @@ static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, - Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ Word16 q_inp, - Word32 decRe[][CLDFB_NO_CHANNELS_MAX], - Word32 decIm[][CLDFB_NO_CHANNELS_MAX] ) + Word32 decRe[][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word32 decIm[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/ ) { Word16 offset, ch, bin; Word32 onset_filter_fx[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ @@ -1751,8 +1751,8 @@ static void ivas_dirac_dec_decorrelate_slot_fx( offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); FOR( bin = 0; bin < num_freq_bands; bin++ ) { - protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin]; - protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; + protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin]; // q_protoFrame + protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; // q_protoFrame move32(); move32(); } @@ -1780,8 +1780,8 @@ static void ivas_dirac_dec_decorrelate_slot_fx( offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); FOR( bin = 0; bin < num_freq_bands; bin++ ) { - decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )]; - decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; + decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )]; // q_inp + decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; // q_inp move32(); move32(); } @@ -2264,9 +2264,9 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 Rmat_fx[3][3], + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/ + Word32 Rmat_fx[3][3], /*Q30*/ const Word16 subframe, const Word16 isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData, @@ -2301,9 +2301,9 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric move32(); nchan_transport = hConfig->nchan_transport; move16(); - qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; + qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/ move32(); - qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); + qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/ nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ move16(); @@ -2561,11 +2561,11 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric IF( isIsmDirection ) { /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */ - diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); /*Q30*/ } ELSE { - diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); /*Q30*/ } IF( separateCenterChannelRendering ) @@ -2579,7 +2579,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric azi_scaled = i_mult( aziDeg, 91 ); ele_scaled = i_mult( eleDeg, 91 ); - doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); + doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); /*Q31*/ num = Sqrt32( L_sub( ONE_IN_Q31, Mpy_32_32( doaVectorX_fx, doaVectorX_fx ) ), &e ); den = doaVectorX_fx; move32(); @@ -2686,8 +2686,8 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric /* Weighting factors to determine appropriate target spectrum for spread coherent sound */ IF( LT_16( spreadCoh_fx, 16384 ) ) { - w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); - w2_fx = shl( spreadCoh_fx, 1 ); + w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); /*Q15*/ + w2_fx = shl( spreadCoh_fx, 1 ); /*Q15*/ w3_fx = 0; move16(); } @@ -2695,8 +2695,8 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric { w1_fx = 0; move16(); - w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); - w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); + w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); /*Q15*/ + w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); /*Q15*/ } test(); @@ -2862,7 +2862,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric Word16 num_e, den_e; Word32 num, den; num = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_fx[1][bin], hDiracDecBin->ChEne_e[1][bin], &num_e ); - num = Mpy_32_32( num, IIReneLimiterFactor_fx ); + num = Mpy_32_32( num, IIReneLimiterFactor_fx ); /*Q = (31 - num_e + 26 - 31) = (26 - num_e)*/ den_e = 0; move16(); den = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEnePrev_fx[0][bin], hDiracDecBin->ChEnePrev_e[0][bin], hDiracDecBin->ChEnePrev_fx[1][bin], hDiracDecBin->ChEnePrev_e[1][bin], &den_e ); @@ -2871,12 +2871,12 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric e = add( sub( num_e, den_e ), add( 5, e ) ); IF( L_shr_sat( IIReneLimiter_fx, sub( 31, e ) ) > 0 ) { - IIReneLimiter_fx = ONE_IN_Q31; + IIReneLimiter_fx = ONE_IN_Q31; /*Q31*/ move32(); } ELSE { - IIReneLimiter_fx = L_shl( IIReneLimiter_fx, e ); + IIReneLimiter_fx = L_shl( IIReneLimiter_fx, e ); /*Q31*/ } hDiracDecBin->ChCrossRe_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossRe_fx[bin], qualityBasedSmFactor_fx ); @@ -3184,7 +3184,7 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const Word16 max_band_decorr, - Word32 Rmat[3][3], + Word32 Rmat[3][3], /*Q30*/ const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, @@ -3591,24 +3591,24 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( { FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) { - hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxRe_fx[chA][chB][bin]; + hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxRe_fx[chA][chB][bin]; // q_processMtx_bin move16(); - hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxIm_fx[chA][chB][bin]; + hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxIm_fx[chA][chB][bin]; // q_processMtx_bin move16(); - hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecRe_fx[chA][chB][bin]; + hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecRe_fx[chA][chB][bin]; // q_processMtxDec_bin move16(); - hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecIm_fx[chA][chB][bin]; + hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecIm_fx[chA][chB][bin]; // q_processMtxDec_bin move16(); - hDiracDecBin->processMtxRe_fx[chA][chB][bin] = extract_h( Mre_fx[chA][chB] ); + hDiracDecBin->processMtxRe_fx[chA][chB][bin] = extract_h( Mre_fx[chA][chB] ); // q_M -16 move16(); - hDiracDecBin->processMtxIm_fx[chA][chB][bin] = extract_h( Mim_fx[chA][chB] ); + hDiracDecBin->processMtxIm_fx[chA][chB][bin] = extract_h( Mim_fx[chA][chB] ); // q_M -16 move16(); - hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = extract_h( MdecRe_fx[chA][chB] ); + hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = extract_h( MdecRe_fx[chA][chB] ); // q_Mdec -16 move16(); - hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = extract_h( MdecIm_fx[chA][chB] ); + hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = extract_h( MdecIm_fx[chA][chB] ); // q_Mdec -16 move16(); } } @@ -3736,34 +3736,34 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( { FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) { - hDiracDecBin->processMtxRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); + hDiracDecBin->processMtxRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx move16(); - hDiracDecBin->processMtxIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); + hDiracDecBin->processMtxIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx move16(); - hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); + hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev move16(); - hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); + hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev move16(); - hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRe_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); + hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRe_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec move16(); - hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecIm_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); + hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecIm_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec move16(); - hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); + hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev move16(); - hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); + hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev move16(); } IF( separateCenterChannelRendering ) { FOR( chB = 0; chB < nchanSeparateChannels; chB++ ) { - hDiracDecBin->processMtxRe_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][add( chB, 2 )][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); + hDiracDecBin->processMtxRe_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][add( chB, 2 )][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx move16(); - hDiracDecBin->processMtxIm_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][add( chB, 2 )][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); + hDiracDecBin->processMtxIm_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][add( chB, 2 )][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx move16(); - hDiracDecBin->processMtxRePrev_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][add( chB, 2 )][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); + hDiracDecBin->processMtxRePrev_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][add( chB, 2 )][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev move16(); - hDiracDecBin->processMtxImPrev_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][add( chB, 2 )][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); + hDiracDecBin->processMtxImPrev_fx[chA][add( chB, 2 )][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][add( chB, 2 )][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev move16(); } } @@ -3779,10 +3779,10 @@ static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], - Word32 *output_fx[], + Word32 *output_fx[], /*q_out*/ Word16 *q_out, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/ const Word16 q_input, const Word16 max_band_decorr, const Word16 numInChannels, @@ -3857,13 +3857,13 @@ static void ivas_dirac_dec_binaural_process_output_fx( FOR( Word16 j = 0; j < nSlots; j++ ) { - scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); - scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); + scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ + scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ test(); IF( processReverb && LT_16( i, 2 ) ) { - scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); - scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); + scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ + scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ } } } @@ -3890,11 +3890,11 @@ static void ivas_dirac_dec_binaural_process_output_fx( { IF( NE_16( slot, sub( nSlots, 1 ) ) ) { - interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); + interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); /*Q15*/ } ELSE { - interpVal_fx = 32767; + interpVal_fx = 32767; /*Q15*/ move16(); } test(); @@ -3980,7 +3980,7 @@ static void ivas_dirac_dec_binaural_process_output_fx( IF( LT_16( bin, max_band_decorr ) && LT_16( chB, 2 ) ) { #ifdef IVAS_ENH32_CADENCE_CHANGES - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); // Q11 // interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; outSlotRe_fx[bin] = Madd_32_16( outSlotRe_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result @@ -3988,9 +3988,9 @@ static void ivas_dirac_dec_binaural_process_output_fx( move32(); - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); - outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result - outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); // Q11 + outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result + outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result move32(); move32(); @@ -4166,12 +4166,12 @@ static void ivas_dirac_dec_binaural_process_output( #ifdef IVAS_FLOAT_FIXED static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ Word16 q_inp, const Word16 nBins, const Word16 nSlots, - Word32 Rmat[3][3] ) + Word32 Rmat[3][3] /*Q30*/ ) { Word16 slot, ch, bin, louderCh; Word32 mono_factor_ILD, mono_factor; @@ -4247,7 +4247,7 @@ static void adaptTransportSignalsHeadtracked_fx( move32(); } } - hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); + hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_chEneIIR move32(); temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); IF( LT_16( hHeadTrackData->q_chEneIIR, q_temp ) ) @@ -4296,9 +4296,9 @@ static void adaptTransportSignalsHeadtracked_fx( move16(); /* Determine ILD-based mono factor */ - mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q23 + mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q21 - mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); + mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); // Q21 IF( EQ_32( mono_factor_ILD, ONE_IN_Q21 ) ) { @@ -4330,12 +4330,12 @@ static void adaptTransportSignalsHeadtracked_fx( inIm_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inIm_fx[ch][slot][bin] ) ) ); move32(); move32(); - re = L_shl( inRe_fx[ch][slot][bin], shift ); - img = L_shl( inIm_fx[ch][slot][bin], shift ); + re = L_shl( inRe_fx[ch][slot][bin], shift ); // q_inp +shift + img = L_shl( inIm_fx[ch][slot][bin], shift ); // q_inp +shift band_nrg = L_add( band_nrg, ( L_add( Mpy_32_32( re, re ), Mpy_32_32( img, img ) ) ) ); // 2(q_inp +shift) -31 } } - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_procChEneIIR move32(); temp = Mpy_32_16_1( band_nrg, sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); @@ -4352,7 +4352,7 @@ static void adaptTransportSignalsHeadtracked_fx( ELSE { /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_procChEneIIR move32(); temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); @@ -4544,7 +4544,7 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, - Word32 Rmat_fx[3][3] ) + Word32 Rmat_fx[3][3] /*Q30*/ ) { Word16 slot, bin, ch; Word32 tmpVal; @@ -4893,16 +4893,16 @@ static void eig2x2( } #else static void eig2x2_fx( - const Word32 E1_fx, - const Word32 E2_fx, + const Word32 E1_fx, /*q_E*/ + const Word32 E2_fx, /*q_E*/ Word16 q_E, - const Word32 Cre_fx, - const Word32 Cim_fx, + const Word32 Cre_fx, /*q_C*/ + const Word32 Cim_fx, /*q_C*/ Word16 q_C, - Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/ + Word32 Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/ Word16 *q_U, - Word32 D_fx[BINAURAL_CHANNELS], + Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/ Word16 *q_D ) { Word16 chA, chB, ch; @@ -5130,7 +5130,7 @@ static void eig2x2_fx( tmp2 = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q30, tmp3, &exp ); exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) ); - normVal_fx = Sqrt32( tmp2, &exp ); + normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2 q_tmp2 = sub( 31, exp ); IF( LT_16( q_tmp1, q_c ) ) @@ -5199,7 +5199,7 @@ static void eig2x2_fx( tmp2 = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q30, tmp3, &exp ); exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) ); - normVal_fx = Sqrt32( tmp2, &exp ); + normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2 q_tmp2 = sub( 31, exp ); IF( LT_16( q_tmp1, q_c ) ) @@ -5287,13 +5287,13 @@ static void matrixDiagMul( } #else static void matrixDiagMul_fx( - Word32 reIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 imIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 reIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/ + Word32 imIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/ Word16 q_In, - const Word32 D_fx[BINAURAL_CHANNELS], + const Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/ Word16 q_D, - Word32 reOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 imOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 reOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/ + Word32 imOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/ Word16 *q_Out ) { Word16 chA, chB; @@ -5349,14 +5349,14 @@ static void matrixMul( } #else static void matrixMul_fx( - Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ + Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ Word16 *q_A, - Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ + Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ Word16 *q_B, - Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ + Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ Word16 *q_out ) { Word16 chA, chB; @@ -5533,14 +5533,14 @@ static void matrixTransp1Mul( } #else static void matrixTransp1Mul_fx( - Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ + Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ Word16 q_A, - Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ + Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ Word16 q_B, - Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ + Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ Word16 *q_out ) { Word16 chA, chB; @@ -5658,14 +5658,14 @@ static void matrixTransp2Mul( } #else static void matrixTransp2Mul_fx( - Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ + Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/ Word16 *q_A, - Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ + Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/ Word16 *q_B, - Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ + Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ Word16 *q_out ) { Word16 chA, chB; @@ -5785,14 +5785,14 @@ static void matrixTransp2Mul_fx( #ifdef IVAS_FLOAT_FIXED static void chol2x2_fx( - const Word32 E1, - const Word32 E2, + const Word32 E1, /*q_E*/ + const Word32 E2, /*q_E*/ Word16 q_E, - const Word32 Cre, - const Word32 Cim, + const Word32 Cre, /*q_C*/ + const Word32 Cim, /*q_C*/ Word16 q_C, - Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ + Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/ Word16 *q_out ) { Word16 chA, chB; @@ -5884,13 +5884,13 @@ static void chol2x2_fx( IF( LT_16( q_e, q_tmp ) ) { - sqrtVal_fx = L_sub( e2, L_shr( temp, sub( q_tmp, q_e ) ) ); + sqrtVal_fx = L_sub( e2, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp q_tmp = q_e; move16(); } ELSE { - sqrtVal_fx = L_sub( L_shr( e2, sub( q_e, q_tmp ) ), temp ); + sqrtVal_fx = L_sub( L_shr( e2, sub( q_e, q_tmp ) ), temp ); // q_tmp } exp = sub( 31, q_tmp ); @@ -5969,13 +5969,13 @@ static void chol2x2_fx( IF( LT_16( q_e, q_tmp ) ) { - sqrtVal_fx = L_sub( e1, L_shr( temp, sub( q_tmp, q_e ) ) ); + sqrtVal_fx = L_sub( e1, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp q_tmp = q_e; move16(); } ELSE { - sqrtVal_fx = L_sub( L_shr( e1, sub( q_e, q_tmp ) ), temp ); + sqrtVal_fx = L_sub( L_shr( e1, sub( q_e, q_tmp ) ), temp ); ////q_tmp } exp = sub( 31, q_tmp ); @@ -6168,23 +6168,23 @@ static void formulate2x2MixingMatrix( #else static void formulate2x2MixingMatrix_fx( - Word32 Ein1_fx, - Word32 Ein2_fx, + Word32 Ein1_fx, /*q_Ein*/ + Word32 Ein2_fx, /*q_Ein*/ Word16 q_Ein, - Word32 CinRe_fx, - Word32 CinIm_fx, + Word32 CinRe_fx, /*q_Cin*/ + Word32 CinIm_fx, /*q_Cin*/ Word16 q_Cin, - Word32 Eout1_fx, - Word32 Eout2_fx, + Word32 Eout1_fx, /*q_Eout*/ + Word32 Eout2_fx, /*q_Eout*/ Word16 q_Eout, - Word32 CoutRe_fx, - Word32 CoutIm_fx, + Word32 CoutRe_fx, /*q_Cout*/ + Word32 CoutIm_fx, /*q_Cout*/ Word16 q_Cout, - Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], // Q31 - Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], - Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], // Q31 + Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/ + Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/ Word16 *q_M, - const Word16 regularizationFactor_fx ) + const Word16 regularizationFactor_fx /*Q14*/ ) { /* This function implements a 2x2 solution for an optimized spatial audio rendering algorithm @@ -6257,11 +6257,11 @@ static void formulate2x2MixingMatrix_fx( tmp = L_max( E_out1, E_out2 ); IF( LT_16( q_maxEne, q_eout ) ) { - maxEne_fx = L_max( maxEne_fx, L_shr( tmp, sub( q_eout, q_maxEne ) ) ); + maxEne_fx = L_max( maxEne_fx, L_shr( tmp, sub( q_eout, q_maxEne ) ) ); // q_maxEne } ELSE { - maxEne_fx = L_max( L_shr( maxEne_fx, sub( q_maxEne, q_eout ) ), tmp ); + maxEne_fx = L_max( L_shr( maxEne_fx, sub( q_maxEne, q_eout ) ), tmp ); // q_maxEne q_maxEne = q_eout; move16(); } @@ -6311,9 +6311,9 @@ static void formulate2x2MixingMatrix_fx( Sx_fx[1] = Sqrt32( Sx_fx[1], &exp1 ); move32(); q_Sx = sub( 31, s_max( exp, exp1 ) ); - Sx_fx[0] = L_shr( Sx_fx[0], sub( sub( 31, exp ), q_Sx ) ); + Sx_fx[0] = L_shr( Sx_fx[0], sub( sub( 31, exp ), q_Sx ) ); // q_Sx move32(); - Sx_fx[1] = L_shr( Sx_fx[1], sub( sub( 31, exp1 ), q_Sx ) ); + Sx_fx[1] = L_shr( Sx_fx[1], sub( sub( 31, exp1 ), q_Sx ) ); // q_Sx move32(); matrixDiagMul_fx( Uxre_fx, Uxim_fx, q_Ux, Sx_fx, q_Sx, Kxre_fx, Kxim_fx, &q_Kx ); @@ -6340,11 +6340,11 @@ static void formulate2x2MixingMatrix_fx( temp = BASOP_Util_Divide3232_Scale_cadence( E_out1, temp, &exp ); exp = sub( exp, sub( q_eout, sub( 31, exp_temp ) ) ); } - Ghat_fx[0] = Sqrt32( temp, &exp ); + Ghat_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp move32(); temp = Mpy_32_32( E_in1, 2147484 ); // 2147484 = 0.001f in Q31 - temp = L_max( temp, E_in2 ); + temp = L_max( temp, E_in2 ); // q_ein IF( temp == 0 ) { BASOP_Util_Divide3232_Scale_cadence( E_out2, 4611686, &exp1 ); // 4611686 = Q62 @@ -6357,14 +6357,14 @@ static void formulate2x2MixingMatrix_fx( temp = BASOP_Util_Divide3232_Scale_cadence( E_out2, temp, &exp1 ); exp1 = sub( exp1, sub( q_eout, sub( 31, exp_temp ) ) ); } - Ghat_fx[1] = Sqrt32( temp, &exp1 ); + Ghat_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1 move32(); q_Ghat = sub( 31, s_max( exp, exp1 ) ); - Ghat_fx[0] = L_shr( Ghat_fx[0], sub( sub( 31, exp ), q_Ghat ) ); + Ghat_fx[0] = L_shr( Ghat_fx[0], sub( sub( 31, exp ), q_Ghat ) ); // q_Ghat move32(); - Ghat_fx[1] = L_shr( Ghat_fx[1], sub( sub( 31, exp1 ), q_Ghat ) ); + Ghat_fx[1] = L_shr( Ghat_fx[1], sub( sub( 31, exp1 ), q_Ghat ) ); // q_Ghat move32(); /* Matrix multiplication, tmp = Ky' * G_hat * Q */ @@ -6414,7 +6414,7 @@ static void formulate2x2MixingMatrix_fx( temp = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q30, D_fx[0], &exp ); exp = sub( exp, sub( Q30, q_D ) ); } - div_fx[0] = Sqrt32( temp, &exp ); + div_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp move32(); IF( D_fx[1] == 0 ) @@ -6427,22 +6427,22 @@ static void formulate2x2MixingMatrix_fx( temp = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q30, D_fx[1], &exp1 ); exp1 = sub( exp1, sub( Q30, q_D ) ); } - div_fx[1] = Sqrt32( temp, &exp1 ); + div_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1 move32(); q_div = sub( 31, s_max( exp, exp1 ) ); - div_fx[0] = L_shr( div_fx[0], sub( sub( 31, exp ), q_div ) ); + div_fx[0] = L_shr( div_fx[0], sub( sub( 31, exp ), q_div ) ); // q_div move32(); - div_fx[1] = L_shr( div_fx[1], sub( sub( 31, exp1 ), q_div ) ); + div_fx[1] = L_shr( div_fx[1], sub( sub( 31, exp1 ), q_div ) ); // q_div move32(); // 1310720000 = 10,000.0f in Q17 IF( LT_16( q_div, Q17 ) ) { - div_fx[0] = L_min( L_shr( 1310720000, sub( Q17, q_div ) ), div_fx[0] ); + div_fx[0] = L_min( L_shr( 1310720000, sub( Q17, q_div ) ), div_fx[0] ); // q_div move32(); - div_fx[1] = L_min( L_shr( 1310720000, sub( Q17, q_div ) ), div_fx[1] ); + div_fx[1] = L_min( L_shr( 1310720000, sub( Q17, q_div ) ), div_fx[1] ); // q_div move32(); } ELSE @@ -6558,8 +6558,8 @@ static void formulate2x2MixingMatrix_fx( { FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) { - Pre_fx[chA][chB] = L_shr( Pre_fx[chA][chB], sub( q_Pre[chA][chB], q_P ) ); - Pim_fx[chA][chB] = L_shr( Pim_fx[chA][chB], sub( q_Pim[chA][chB], q_P ) ); + Pre_fx[chA][chB] = L_shr( Pre_fx[chA][chB], sub( q_Pre[chA][chB], q_P ) ); // q_P + Pim_fx[chA][chB] = L_shr( Pim_fx[chA][chB], sub( q_Pim[chA][chB], q_P ) ); // q_P move32(); move32(); } @@ -6584,7 +6584,7 @@ static void getDirectPartGains_fx( Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, - Word32 Rmat[3][3], + Word32 Rmat[3][3], /*Q30*/ PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked ) { @@ -7029,34 +7029,34 @@ Word16 configure_reqularization_factor_fx( ) { Word16 reqularizationFactor; - reqularizationFactor = 16384; /* Default value */ + reqularizationFactor = 16384; /* Default value */ /*Q14*/ move16(); IF( EQ_32( ivas_format, MASA_FORMAT ) ) { IF( GE_32( ivas_total_brate, IVAS_160k ) ) { - reqularizationFactor = 6553; + reqularizationFactor = 6553; /*Q14*/ move16(); } ELSE IF( EQ_32( ivas_total_brate, IVAS_128k ) ) { - reqularizationFactor = 8192; + reqularizationFactor = 8192; /*Q14*/ move16(); } ELSE IF( EQ_32( ivas_total_brate, IVAS_96k ) ) { - reqularizationFactor = 9830; + reqularizationFactor = 9830; /*Q14*/ move16(); } ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) ) { - reqularizationFactor = 13107; + reqularizationFactor = 13107; /*Q14*/ move16(); } ELSE { - reqularizationFactor = 16384; + reqularizationFactor = 16384; /*Q14*/ move16(); } } @@ -7065,27 +7065,27 @@ Word16 configure_reqularization_factor_fx( { IF( GE_32( ivas_total_brate, IVAS_96k ) ) { - reqularizationFactor = 6553; + reqularizationFactor = 6553; /*Q14*/ move16(); } ELSE IF( GE_32( ivas_total_brate, IVAS_80k ) ) { - reqularizationFactor = 8192; + reqularizationFactor = 8192; /*Q14*/ move16(); } ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) ) { - reqularizationFactor = 11468; + reqularizationFactor = 11468; /*Q14*/ move16(); } ELSE IF( GE_32( ivas_total_brate, IVAS_48k ) ) { - reqularizationFactor = 13107; + reqularizationFactor = 13107; /*Q14*/ move16(); } ELSE { - reqularizationFactor = 16384; + reqularizationFactor = 16384; /*Q14*/ move16(); } } @@ -7105,8 +7105,8 @@ Word16 configure_reqularization_factor_fx( void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( Decoder_Struct *st_ivas, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ Word16 *cldfb_buf_q, const Word16 nBins, const Word16 subframe ) @@ -7194,13 +7194,13 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( { FOR( ch = 0; ch < 2; ch++ ) { - Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); + Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 move32(); - Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = -19 + Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 move32(); } - subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); + subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 IF( subframeEne_fx != 0 ) { @@ -7317,13 +7317,13 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( hMasaIsmData->eneMoveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->eneMoveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); move32(); temp = Mpy_32_16_1( subframeEne_fx, eneMove_fx[ch] ); - hMasaIsmData->eneMoveIIR_fx[ch][bin] = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], temp ); // Q = subframeEne_q_fx - 3 + hMasaIsmData->eneMoveIIR_fx[ch][bin] = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22 move32(); hMasaIsmData->enePreserveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->enePreserveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); move32(); temp = Mpy_32_16_1( subframeEne_fx, enePreserve_fx[ch] ); - hMasaIsmData->enePreserveIIR_fx[ch][bin] = L_add( hMasaIsmData->enePreserveIIR_fx[ch][bin], temp ); // Q = subframeEne_q_fx - 3 + hMasaIsmData->enePreserveIIR_fx[ch][bin] = L_add( hMasaIsmData->enePreserveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22 move32(); normVal_fx = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], hMasaIsmData->enePreserveIIR_fx[ch][bin] ); @@ -7380,9 +7380,9 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( { hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] = add( hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin], ismPreprocMtxIncrement_fx[outCh][inCh] ); // Q = 15 move16(); - outSlotRe_fx[outCh] = Mpy_32_16_1( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q = 6; + outSlotRe_fx[outCh] = Mpy_32_16_1( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q; move32(); - outSlotIm_fx[outCh] = Mpy_32_16_1( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q = 6; + outSlotIm_fx[outCh] = Mpy_32_16_1( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q; move32(); } } @@ -7394,14 +7394,14 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( move32(); FOR( ch = 0; ch < 2; ch++ ) { - hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 + hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 move32(); - hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 + hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 move32(); } temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->preprocEneTarget_fx[bin], L_max( EPSILON_FX, hMasaIsmData->preprocEneRealized_fx[bin] ), &eqVal_q_fx ); eqVal_fx = Sqrt16( temp1, &eqVal_q_fx ); - temp1 = 4 << Q12; + temp1 = 4 << Q12; // Q12 move16(); IF( LT_16( eqVal_q_fx, Q12 ) ) { @@ -7417,7 +7417,7 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( { if ( GT_16( shr( eqVal_fx, sub( eqVal_q_fx, Q12 ) ), temp1 ) ) { - eqVal_fx = temp1; + eqVal_fx = temp1; // eqVal_q_fx move16(); } } @@ -7943,8 +7943,8 @@ static void ivas_masa_ext_rend_parambin_internal_fx( { FOR( Word16 k = 0; k < 60; k++ ) { - Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); - Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); + Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); // q + Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); // q move32(); move32(); } @@ -7981,20 +7981,20 @@ static void ivas_masa_ext_rend_parambin_internal_fx( { FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) { - Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); - Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); - Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); - Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); + Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat } } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { FOR( slot = 0; slot < numInChannels; slot++ ) { - Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); - Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); - Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat } } hDiracDecBin->q_processMtx = q_mat; @@ -8018,8 +8018,8 @@ static void ivas_masa_ext_rend_parambin_internal_fx( FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - scale_sig32( output_fx[ch], nBins * hSpatParamRendCom->subframe_nbslots[subframe], sub( Q11, q_out ) ); - scale_sig32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); + scale_sig32( output_fx[ch], nBins * hSpatParamRendCom->subframe_nbslots[subframe], sub( Q11, q_out ) ); // Q11 + scale_sig32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); // Q11 hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11; } diff --git a/lib_rend/ivas_mcmasa_ana.c b/lib_rend/ivas_mcmasa_ana.c index 625fb006f72b16a825a8d1432176c0dbad25f9ac..7928c75d535eb8eb16f0e9e0f680669022e5f40e 100644 --- a/lib_rend/ivas_mcmasa_ana.c +++ b/lib_rend/ivas_mcmasa_ana.c @@ -75,16 +75,16 @@ typedef struct } CovarianceMatrix; #ifdef IVAS_FLOAT_FIXED void ivas_mcmasa_param_est_ana_fx( - MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ - Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ - Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ - Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ - Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ - Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ - Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ + Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation Q22 */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth Q22 */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio Q31 */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence Q31 */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence Q31 */ Word16 q_data, - const Word16 input_frame, /* i : Input frame size */ - const Word16 nchan_inp /* i : Number of input channels */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp /* i : Number of input channels */ ); #else void ivas_mcmasa_param_est_ana( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const int16_t input_frame, const int16_t nchan_inp ); @@ -107,19 +107,20 @@ static void computeVerticalDiffuseness_fx( Word32 **buffer_intensity, /* i : Intensity vectors */ const Word32 *buffer_energy, /* i : Energy */ const Word16 num_freq_bands, /* i : Number of frequency bands */ - Word32 *diffuseness, /* o : Estimated diffuseness */ - Word16 *buffer_intensity_e, - Word16 *buffer_energy_e ); + Word32 *diffuseness, /* o : Estimated diffuseness Q31 */ + Word16 *buffer_intensity_q, + Word16 *buffer_energy_q ); static void compute_cov_mtx_fx( Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */ Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */ const Word16 freq, /* i : Freq to process */ const Word16 N, /* i : Number of channels */ CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ - Word16 shift ); + Word16 inp_exp /* i : Stores exponent for sr and si */ +); static void computeEvenLayout_fx( - const Word32 *ls_azimuth, - Word32 *ls_azimuth_even, + const Word32 *ls_azimuth, /* i: Q22 */ + Word32 *ls_azimuth_even, /* o: Q22 */ const Word16 numChannels ); static void ivas_mcmasa_dmx_fx( @@ -231,7 +232,7 @@ ivas_error ivas_mcmasa_ana_open( /* Determine band grouping */ Copy( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 ); - maxBin = extract_l( W_extract_h( W_add( W_mult_32_32( input_Fs, INV_CLDFB_BANDWIDTH_Q31 ), ONE_IN_Q31 /*0.5f in Q31*/ ) ) ); + maxBin = extract_l( W_extract_h( W_add( W_mult_32_32( input_Fs, INV_CLDFB_BANDWIDTH_Q31 ), ONE_IN_Q31 /*0.5f in Q32*/ ) ) ); // Q0 FOR( i = 1; i < add( hMcMasa->nbands, 1 ); i++ ) { IF( GE_16( hMcMasa->band_grouping[i], maxBin ) ) @@ -323,22 +324,22 @@ ivas_error ivas_mcmasa_ana_open( FOR( i = 0; i < numAnalysisChannels; i++ ) { - hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; + hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; // Q31 move32(); - hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); + hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31 move32(); - hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ), 16 ); + hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ), 16 ); // Q31 move32(); - hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); + hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); // Q31 move32(); - hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; + hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; // Q31 move32(); - hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); + hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31 move32(); - hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; + hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; // Q31 move32(); - hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); + hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); // Q31 move32(); } @@ -346,29 +347,29 @@ ivas_error ivas_mcmasa_ana_open( FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) { - left_min_fx = 360 << 22; + left_min_fx = 360 << 22; // Q22 move32(); - right_min_fx = -( 360 << 22 ); + right_min_fx = -( 360 << 22 ); // Q22 move32(); FOR( j = 0; j < hMcMasa->numHorizontalChannels; j++ ) { - azi_diff_fx = L_sub( ls_azimuth_fx[j], ls_azimuth_fx[i] ); + azi_diff_fx = L_sub( ls_azimuth_fx[j], ls_azimuth_fx[i] ); // Q22 IF( GT_32( azi_diff_fx, ( 180 << 22 ) ) ) { - azi_diff_fx = L_sub( azi_diff_fx, 360 << 22 ); + azi_diff_fx = L_sub( azi_diff_fx, 360 << 22 ); // Q22 } ELSE IF( LT_32( azi_diff_fx, -( 180 << 22 ) ) ) { - azi_diff_fx = L_add( azi_diff_fx, 360 << 22 ); + azi_diff_fx = L_add( azi_diff_fx, 360 << 22 ); // Q22 } test(); IF( LT_32( azi_diff_fx, left_min_fx ) && GT_32( azi_diff_fx, 0 ) ) { hMcMasa->leftNearest[i] = j; move16(); - left_min_fx = azi_diff_fx; + left_min_fx = azi_diff_fx; // Q22 move32(); } test(); @@ -376,7 +377,7 @@ ivas_error ivas_mcmasa_ana_open( { hMcMasa->rightNearest[i] = j; move16(); - right_min_fx = azi_diff_fx; + right_min_fx = azi_diff_fx; // Q22 move32(); } } @@ -398,7 +399,7 @@ ivas_error ivas_mcmasa_ana_open( move16(); FOR( i = 0; i < input_frame; i++ ) { - hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); + hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); // Q15 move16(); } @@ -844,16 +845,16 @@ void ivas_mcmasa_ana( /* Estimate metadata parameters for McMASA */ #ifdef IVAS_FLOAT_FIXED void ivas_mcmasa_param_est_ana_fx( - MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ - Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ - Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ - Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ - Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ - Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ - Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ + Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation Q22 */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth Q22 */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio Q31 */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence Q31 */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence Q31 */ Word16 q_data, - const Word16 input_frame, /* i : Input frame size */ - const Word16 nchan_inp /* i : Number of input channels */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp /* i : Number of input channels */ ) { Word16 cohPanCoh_e; @@ -981,8 +982,8 @@ void ivas_mcmasa_param_est_ana_fx( sf = sub( s_min( cr_q, ci_q ), 4 ); FOR( i = 0; i < numAnalysisChannels; i++ ) { - scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); - scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); + scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf + scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf ); // Q-> inp_q + sf } inp_q = add( inp_q, sf ); c_e = sub( 31, inp_q ); @@ -999,7 +1000,7 @@ void ivas_mcmasa_param_est_ana_fx( { FOR( i = 0; i < numAnalysisChannels; i++ ) { - Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); + Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); // Q-> 2*inp_q - 31, e = 31 - (2*inp_q - 31) = 62 - 2*inp_q = 2*(31 - inp_q) = 2*c_e hMcMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->energy_fx[block_m_idx][band_m_idx], hMcMasa->energy_e[block_m_idx][band_m_idx], temp, shl( c_e, 1 ), &hMcMasa->energy_e[block_m_idx][band_m_idx] ); move32(); } @@ -1021,21 +1022,21 @@ void ivas_mcmasa_param_est_ana_fx( /* Compute standard FOA */ /* W */ - v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); /*q*/ - v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); /*q*/ + v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/ + v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/ FOR( i = 2; i < numAnalysisChannels; i++ ) { - v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*q*/ - v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*q*/ + v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/ + v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/ } /* Y */ - v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*q*/ - v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*q*/ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/ FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*q*/ - v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*q*/ + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/ } /* Z */ IF( hMcMasa->isHorizontalSetup ) @@ -1046,35 +1047,35 @@ void ivas_mcmasa_param_est_ana_fx( } ELSE { - v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*q*/ - v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*q*/ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/ FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*q*/ - v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*q*/ + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins ); /*inp_q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins ); /*inp_q*/ } } /* X */ - v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*q*/ - v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); /*q*/ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/ FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*q*/ - v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*q*/ + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/ } /* Compute even FOA */ /* W */ - Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); - Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); + Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); /*inp_q*/ + Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); /*inp_q*/ /* Y */ - v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*q*/ - v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*q*/ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/ FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*q*/ - v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*q*/ + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins ); /*inp_q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins ); /*inp_q*/ } /* Z (even setups are handled as horizontal) */ @@ -1082,22 +1083,22 @@ void ivas_mcmasa_param_est_ana_fx( set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins ); /* X */ - v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); - v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/ FOR( i = 1; i < numAnalysisChannels; i++ ) { - v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); - v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); /*inp_q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); /*inp_q*/ } /* Direction estimation */ - computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); /*2+q-31*/ + computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); /* Q intensity_real_fx = 2*inp_q-31, e = 31 - 2*inp_q + 31 = 62 - 2*inp_q = 2*(31-inp_q)=2*c_e */ - computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], shl( c_e, 1 ) ); /*Q30*/ + computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], shl( c_e, 1 ) ); /* Q direction_vector_fx = Q30*/ /* Power and intensity estimation for diffuseness */ - computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx ); /*2*(q)-31*/ - computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); /*2*q-30*/ + computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx ); /*2*inp_q-31*/ + computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); /*2*inp_q-30*/ /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hMcMasa->index_buffer_intensity = add( ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */ @@ -1113,19 +1114,19 @@ void ivas_mcmasa_param_est_ana_fx( Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[i_mult( index - 1, num_freq_bands )] ), num_freq_bands ); hMcMasa->buffer_energy_q[index - 1] = sub( shl( inp_q, 1 ), 30 ); move16(); - computeDiffuseness_fixed( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q, out_exp ); + computeDiffuseness_fixed( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q, out_exp ); // out_exp = Q30 /* Compute vertical diffuseness, and tune original diffuseness if needed */ IF( !hMcMasa->isHorizontalSetup ) { Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands ); hMcMasa->buffer_intensity_real_vert_q[index - 1] = sub( shl( inp_q, 1 ), 31 ); move16(); - computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, num_freq_bands, vertical_diffuseness_vector_fx, hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q ); + computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, num_freq_bands, vertical_diffuseness_vector_fx, hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q ); // Q vertical_diffuseness_vector_fx = 31 v_min_fx( diffuseness_vector_fx, out_exp, vertical_diffuseness_vector_fx, q_vdv, diffuseness_vector_fx, out_exp, num_freq_bands ); } FOR( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*2q-30*/ + norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*2*inp_q-30*/ hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] ); hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] ); hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), shl( c_e, 1 ), &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] ); @@ -1255,18 +1256,18 @@ void ivas_mcmasa_param_est_ana_fx( move32(); i1 = 0; move16(); - currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; + currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; /*Q22*/ move32(); FOR( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) { - angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); + angleDist_fx = L_abs( L_sub( currentAzi_fx, hMcMasa->ls_azimuth_fx[i] ) ); /*Q22*/ IF( GT_32( angleDist_fx, 754974720 /*180.0f Q.22*/ ) ) { - angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); + angleDist_fx = L_abs( L_sub( angleDist_fx, 1509949440 ) ); /*Q22*/ } IF( LT_32( angleDist_fx, minAngleDist_fx ) ) { - minAngleDist_fx = angleDist_fx; + minAngleDist_fx = angleDist_fx; /*Q22*/ move32(); i1 = i; move16(); @@ -1296,7 +1297,7 @@ void ivas_mcmasa_param_est_ana_fx( temp2 = L_add( temp2, EPSILON_FX ); lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e ); lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, temp2_e ) ); - lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); + lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31 stereoness_fx = Mult_32_32( stereoCoh_fx, lsEnergyRelation_fx ); stereoness_e = stereoCoh_e; move16(); @@ -1459,13 +1460,13 @@ void ivas_mcmasa_param_est_ana_fx( lsEnergySum_fx = L_add_sat( lsEnergySum_fx, EPSILON_FX ); lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, lsEnergySum_fx, &lsEnergyRelation_e ); lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp1_e, lsEnergySum_e ) ); - lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); - stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); + lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31 + stereoRatio_fx = L_sub( Mult_32_32( L_shl_sat( stereoCoh_fx, stereoCoh_e ), lsEnergyRelation_fx ), surrCoh_fx ); // Q31 lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e ); lsEnergyRelation_e = add( lsEnergyRelation_e, sub( temp2_e, lsEnergySum_e ) ); - lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); - cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); + lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, add( 16, lsEnergyRelation_e ) ); // Q31 + cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); // Q31 IF( GT_32( stereoRatio_fx, cohPanRatio_fx ) ) { @@ -1533,7 +1534,7 @@ void ivas_mcmasa_param_est_ana_fx( diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e ); move32(); diffuseness_m_e = add( diffuseness_m_e, sub( diffuseness_e[band_m_idx], renormalization_factor_diff_e[band_m_idx] ) ); - diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); + diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], add( 16, diffuseness_m_e ) ); // Q31 move32(); } ELSE @@ -2115,7 +2116,7 @@ static void ivas_mcmasa_dmx_fx( FOR( i = 0; i < input_frame; i++ ) { - dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_f_fx[2][i] ) ); + dmx_c_fx = W_extract_h( W_mult_32_32( INV_SQRT2_FX, data_f_fx[2][i] ) ); // data_e move32(); data_f_fx[0][i] = L_add( dmx_c_fx, data_f_fx[0][i] ); move32(); @@ -2148,16 +2149,16 @@ static void ivas_mcmasa_dmx_fx( } } - alpha_fx = 214748364; // Q31 + alpha_fx = 214748364; // 0.1 in Q31 move32(); L_tmp = Mpy_32_32( alpha_fx, multiChEne_fx ); - L_tmp1 = Mpy_32_32( 1932735284, hMcMasa->prevMultiChEne_fx ); + L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevMultiChEne_fx ); hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e ); L_tmp = Mpy_32_32( alpha_fx, downmixEne_fx ); - L_tmp1 = Mpy_32_32( 1932735284, hMcMasa->prevDownmixEne_fx ); + L_tmp1 = Mpy_32_32( 1932735284 /* 1.0 - alpha = 0.9 Q31 */, hMcMasa->prevDownmixEne_fx ); hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp( L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e ); prevEQ_fx = hMcMasa->prevEQ_fx; @@ -2177,16 +2178,16 @@ static void ivas_mcmasa_dmx_fx( FOR( i = 0; i < input_frame; i++ ) { L_tmp = Mpy_32_32( L_deposit_h( hMcMasa->interpolator_fx[i] ), currEQ_fx ); - L_tmp1 = L_sub( 1073741824, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); - L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); + L_tmp1 = L_sub( 1073741824 /* 1.0 in Q30*/, L_lshr( L_deposit_h( hMcMasa->interpolator_fx[i] ), 1 ) ); // Q30 + L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); // e = prevEQ_e + 1 instEQ_fx = BASOP_Util_Add_Mant32Exp( L_tmp, currEQ_e, L_tmp1, add( prevEQ_e, 1 ), &instEQ_e ); FOR( j = 0; j < nchan_transport; j++ ) { - data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); + data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); // e = data_e + instEQ_e move32(); move32(); - data_f_fx[j][i] = L_shl( data_f_fx[j][i], instEQ_e ); + data_f_fx[j][i] = L_shl( data_f_fx[j][i], instEQ_e ); // data_e } } @@ -2203,7 +2204,7 @@ static void compute_cov_mtx_fx( const Word16 freq, /* i : Freq to process */ const Word16 N, /* i : Number of channels */ CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ - Word16 inp_exp /*Stores exponent for temp*/ + Word16 inp_exp /* i : Stores exponent for sr and si */ ) { Word16 i, j; @@ -2225,9 +2226,9 @@ static void compute_cov_mtx_fx( d = si[j][freq]; norm_c = norm_l( c ); norm_d = norm_l( d ); - c = L_shl( c, norm_c ); /*inp_exp-norm_c*/ - d = L_shl( d, norm_d ); /*inp_exp-norm_d*/ - temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), sub( shl( inp_exp, 1 ), add( norm_a, norm_c ) ), Mult_32_32( b, d ), sub( shl( inp_exp, 1 ), add( norm_b, norm_d ) ), &shift ); /*exp=inp_exp-norm_ab+inp_exp-norm_cd*/ + c = L_shl( c, norm_c ); /*inp_exp-norm_c*/ + d = L_shl( d, norm_d ); /*inp_exp-norm_d*/ + temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), sub( shl( inp_exp, 1 ), add( norm_a, norm_c ) ), Mult_32_32( b, d ), sub( shl( inp_exp, 1 ), add( norm_b, norm_d ) ), &shift ); COVls->xr_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xr_fx[i][j], COVls->xr_e[i][j], temp, shift, &COVls->xr_e[i][j] ); move32(); temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( b, c ), sub( shl( inp_exp, 1 ), add( norm_b, norm_c ) ), L_negate( Mult_32_32( a, d ) ), sub( shl( inp_exp, 1 ), add( norm_a, norm_d ) ), &shift ); @@ -2279,7 +2280,7 @@ static void computeVerticalDiffuseness_fx( Word32 **buffer_intensity, /* i : Intensity vectors */ const Word32 *buffer_energy, /* i : Energy */ const Word16 num_freq_bands, /* i : Number of frequency bands */ - Word32 *diffuseness, /* o : Estimated diffuseness */ + Word32 *diffuseness, /* o : Estimated diffuseness Q31 */ Word16 *buffer_intensity_q, Word16 *buffer_energy_q ) { @@ -2304,7 +2305,7 @@ static void computeVerticalDiffuseness_fx( p_tmp_c = buffer_energy + i_mult( i, num_freq_bands ); FOR( k = 0; k < num_freq_bands; k++ ) { - energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], *( p_tmp_c ), sub( 31, buffer_energy_q[i] ), &energy_slow_e[k] ); /*q=min_q*/ + energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k], *( p_tmp_c ), sub( 31, buffer_energy_q[i] ), &energy_slow_e[k] ); move32(); p_tmp_c++; } @@ -2312,7 +2313,7 @@ static void computeVerticalDiffuseness_fx( /* Intensity slow */ FOR( k = 0; k < num_freq_bands; k++ ) { - intensity_slow[k] = BASOP_Util_Add_Mant32Exp( intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k], sub( 31, buffer_intensity_q[i] ), &intensity_slow_e[k] ); /*q=min_q*/ + intensity_slow[k] = BASOP_Util_Add_Mant32Exp( intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k], sub( 31, buffer_intensity_q[i] ), &intensity_slow_e[k] ); move32(); } } @@ -2320,7 +2321,7 @@ static void computeVerticalDiffuseness_fx( /* Compute absolute value */ FOR( k = 0; k < num_freq_bands; k++ ) { - intensity_slow_abs[k] = L_abs( intensity_slow[k] ); /*min_q*/ + intensity_slow_abs[k] = L_abs( intensity_slow[k] ); move32(); } @@ -2340,14 +2341,14 @@ static void computeVerticalDiffuseness_fx( } ELSE IF( GE_32( tmp, L_shl( 1, sub( 15, tmp_e2 ) ) ) ) { - tmp = ONE_IN_Q31; + tmp = ONE_IN_Q31; // Q31 move32(); } ELSE { - tmp = L_shl( tmp, add( 16, tmp_e2 ) ); + tmp = L_shl( tmp, add( 16, tmp_e2 ) ); // Q31 } - diffuseness[i] = tmp; + diffuseness[i] = tmp; // Q31 move32(); } @@ -2411,8 +2412,8 @@ static void computeVerticalDiffuseness( #ifdef IVAS_FLOAT_FIXED static void computeEvenLayout_fx( - const Word32 *ls_azimuth, - Word32 *ls_azimuth_even, + const Word32 *ls_azimuth, /* i: Q22 */ + Word32 *ls_azimuth_even, /* o: Q22 */ const Word16 numChannels ) { Word16 i; @@ -2444,7 +2445,7 @@ static void computeEvenLayout_fx( { IF( LT_32( ls_azimuth_temp[j], smallestAzimuth ) ) { - smallestAzimuth = ls_azimuth_temp[j]; + smallestAzimuth = ls_azimuth_temp[j]; /*Q21*/ move32(); smallestAzimuthIndex = j; move16(); @@ -2452,7 +2453,7 @@ static void computeEvenLayout_fx( } ls_azimuth_order[i] = smallestAzimuthIndex; move32(); - ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); + ls_azimuth_temp[smallestAzimuthIndex] = ( 1000 << 21 ); /*Q21*/ move32(); } @@ -2473,7 +2474,7 @@ static void computeEvenLayout_fx( FOR( i = 0; i < numChannels; i++ ) { - ls_azimuth_even[ls_azimuth_order[i]] = L_shl( L_shr( L_add( ls_azimuth_even_ordered[i], ONE_IN_Q21 ), 22 ), 22 ); /*((a+2^21)/2^22)*2^22*/ + ls_azimuth_even[ls_azimuth_order[i]] = L_shl( L_shr( L_add( ls_azimuth_even_ordered[i], ONE_IN_Q21 /* 0.5 in Q22 */ ), 22 ), 22 ); /*Q22*/ move32(); } @@ -2630,14 +2631,14 @@ void ivas_create_masa_out_meta( } #else void ivas_create_masa_out_meta_fx( - MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */ - SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */ - const Word16 nchan_transport, /* i : Number of transport channels */ - Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation */ - Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth */ - Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */ - Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */ - Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */ + MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */ + SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */ + const Word16 nchan_transport, /* i : Number of transport channels */ + Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation Q22 */ + Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth Q22 */ + Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */ + Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */ + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */ Word16 energyRatio_q, Word16 spreadCoherence_q, Word16 surroundingCoherence_q @@ -2694,7 +2695,7 @@ void ivas_create_masa_out_meta_fx( /* Direct-to-total ratio */ FOR( band = 0; band < numFrequencyBands; band++ ) { - extOutMeta->directToTotalRatio[0][sf][band] = (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ); + extOutMeta->directToTotalRatio[0][sf][band] = (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ); // Q8 move16(); extOutMeta->directToTotalRatio[1][sf][band] = 0; move16(); @@ -2703,7 +2704,7 @@ void ivas_create_masa_out_meta_fx( /* Spread coherence */ FOR( band = 0; band < numFrequencyBands; band++ ) { - extOutMeta->spreadCoherence[0][sf][band] = (UWord8) L_shr( spreadCoherence[sf][band], sub( spreadCoherence_q, 8 ) ); + extOutMeta->spreadCoherence[0][sf][band] = (UWord8) L_shr( spreadCoherence[sf][band], sub( spreadCoherence_q, 8 ) ); // Q8 move16(); extOutMeta->spreadCoherence[1][sf][band] = 0; move16(); @@ -2712,14 +2713,14 @@ void ivas_create_masa_out_meta_fx( /* Diffuse-to-total ratio = 1 - sum(direct-to-total ratios) */ FOR( band = 0; band < numFrequencyBands; band++ ) { - extOutMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( UINT8_MAX, (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ) ); + extOutMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( UINT8_MAX, (UWord8) L_shr( energyRatio[sf][band], sub( energyRatio_q, 8 ) ) ); // Q8 move16(); } /* Surround coherence */ FOR( band = 0; band < numFrequencyBands; band++ ) { - extOutMeta->surroundCoherence[sf][band] = (UWord8) L_shr( surroundingCoherence[sf][band], sub( surroundingCoherence_q, 8 ) ); + extOutMeta->surroundCoherence[sf][band] = (UWord8) L_shr( surroundingCoherence[sf][band], sub( surroundingCoherence_q, 8 ) ); // Q8 move16(); } } diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 1f230806be18e00babea4d972a62ee2d8d20ab87..de706bd47ab815d2fde7b0d91547ec7fde67ab76 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -167,28 +167,28 @@ ivas_error ivas_td_binaural_open_unwrap_fx( SWITCH( transport_config ) { case IVAS_AUDIO_CONFIG_5_1: - ls_azimuth_fx = ls_azimuth_CICP6_fx; - ls_elevation_fx = ls_elevation_CICP6_fx; + ls_azimuth_fx = ls_azimuth_CICP6_fx; // Q22 + ls_elevation_fx = ls_elevation_CICP6_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_7_1: - ls_azimuth_fx = ls_azimuth_CICP12_fx; - ls_elevation_fx = ls_elevation_CICP12_fx; + ls_azimuth_fx = ls_azimuth_CICP12_fx; // Q22 + ls_elevation_fx = ls_elevation_CICP12_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_5_1_2: - ls_azimuth_fx = ls_azimuth_CICP14_fx; - ls_elevation_fx = ls_elevation_CICP14_fx; + ls_azimuth_fx = ls_azimuth_CICP14_fx; // Q22 + ls_elevation_fx = ls_elevation_CICP14_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_5_1_4: - ls_azimuth_fx = ls_azimuth_CICP16_fx; - ls_elevation_fx = ls_elevation_CICP16_fx; + ls_azimuth_fx = ls_azimuth_CICP16_fx; // Q22 + ls_elevation_fx = ls_elevation_CICP16_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_7_1_4: - ls_azimuth_fx = ls_azimuth_CICP19_fx; - ls_elevation_fx = ls_elevation_CICP19_fx; + ls_azimuth_fx = ls_azimuth_CICP19_fx; // Q22 + ls_elevation_fx = ls_elevation_CICP19_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_LS_CUSTOM: - ls_azimuth_fx = hTransSetup.ls_azimuth_fx; - ls_elevation_fx = hTransSetup.ls_elevation_fx; + ls_azimuth_fx = hTransSetup.ls_azimuth_fx; // Q22 + ls_elevation_fx = hTransSetup.ls_elevation_fx; // Q22 BREAK; default: ls_azimuth_fx = NULL; @@ -270,7 +270,7 @@ ivas_error ivas_td_binaural_open_unwrap_fx( test(); IF( NE_16( ivas_format, MASA_ISM_FORMAT ) && NE_16( ivas_format, SBA_ISM_FORMAT ) ) { - *binaural_latency_ns = Mult_32_32( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, 1000000000 ); + *binaural_latency_ns = Mult_32_32( ( *hBinRendererTd )->HrFiltSet_p->latency_s_fx, 1000000000 /* 1000000000.f in Q0 */ ); move32(); } @@ -518,18 +518,18 @@ void ivas_td_binaural_close( #ifdef IVAS_FLOAT_FIXED ivas_error ivas_td_binaural_renderer_unwrap_fx( - const REVERB_HANDLE hReverb, /* i : Reverberator handle */ - const AUDIO_CONFIG transport_config, /* i : Transport configuration */ - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */ - const Word16 num_src, /* i : number of sources to render */ - const Word16 lfe_idx, /* i : LFE channel index */ - const IVAS_FORMAT ivas_format, /* i : IVAS format */ - ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ - COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle */ + const REVERB_HANDLE hReverb, /* i : Reverberator handle */ + const AUDIO_CONFIG transport_config, /* i : Transport configuration */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD binaural object renderer handle */ + const Word16 num_src, /* i : number of sources to render */ + const Word16 lfe_idx, /* i : LFE channel index */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ + ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle */ const Word16 ism_md_subframe_update, /* i : Number of subframes to delay ism metadata to sync with audio */ - Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis */ - const Word16 output_frame, /* i : output frame length */ - const Word16 num_subframes /* i : number of subframes to render */ + Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis Q11 */ + const Word16 output_frame, /* i : output frame length */ + const Word16 num_subframes /* i : number of subframes to render */ ) { Word16 subframe_length; @@ -609,22 +609,22 @@ ivas_error ivas_td_binaural_renderer_unwrap_fx( FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) { - scale_sig32( output_fx[i], L_FRAME48k, -4 ); + scale_sig32( output_fx[i], L_FRAME48k, -4 ); // Q11 - 4 = Q7 } - IF( NE_32( ( error = ivas_reverb_process_fx( hReverb, transport_config, 0, output_fx, p_reverb_signal_fx, subframe_idx ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = ivas_reverb_process_fx( hReverb, transport_config, 0, output_fx, p_reverb_signal_fx, subframe_idx ) ), IVAS_ERR_OK ) ) // Q p_reverb_signal_fx = Q output_fx - 2 = 5 { return error; } FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) { - scale_sig32( output_fx[i], L_FRAME48k, 4 ); + scale_sig32( output_fx[i], L_FRAME48k, 4 ); // Q7 + 4 = Q11 } FOR( i = 0; i < BINAURAL_CHANNELS; ++i ) { - scale_sig32( p_reverb_signal_fx[i] + subframe_idx * hReverb->full_block_size, hReverb->full_block_size, 2 + 4 ); + scale_sig32( p_reverb_signal_fx[i] + subframe_idx * hReverb->full_block_size, hReverb->full_block_size, 2 + 4 ); // Q5 + 6 = Q11 } } @@ -654,8 +654,8 @@ ivas_error ivas_td_binaural_renderer_unwrap_fx( IF( hReverb != NULL ) { - v_add_32( reverb_signal_fx[0], output_fx[0], output_fx[0], output_frame ); - v_add_32( reverb_signal_fx[1], output_fx[1], output_fx[1], output_frame ); + v_add_32( reverb_signal_fx[0], output_fx[0], output_fx[0], output_frame ); // Q11 + v_add_32( reverb_signal_fx[1], output_fx[1], output_fx[1], output_frame ); // Q11 } return IVAS_ERR_OK; @@ -781,10 +781,10 @@ ivas_error ivas_td_binaural_renderer_unwrap( #ifdef IVAS_FLOAT_FIXED ivas_error TDREND_GetMix_fx( - BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 */ - const Word16 subframe_length, /* i/o: subframe length */ - const Word16 subframe_idx, /* i : Subframe index to 5 ms subframe */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 Q11 */ + const Word16 subframe_length, /* i/o: subframe length */ + const Word16 subframe_idx, /* i : Subframe index to 5 ms subframe */ const Word16 ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ ) { @@ -849,8 +849,8 @@ ivas_error TDREND_GetMix_fx( /* Populate output variable */ - Copy32( output_buf[0], output[0] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Left */ - Copy32( output_buf[1], output[1] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Right */ + Copy32( output_buf[0], output[0] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Left same Q as Src_p->InputFrame_p_fx Q11 */ + Copy32( output_buf[1], output[1] + imult1616( subframe_idx, subframe_length ), subframe_length ); /* Right same Q as Src_p->InputFrame_p_fx Q11 */ /* Clear the PoseUpdated and Source position update flags */ TDREND_Clear_Update_flags_fx( hBinRendererTd ); @@ -1219,23 +1219,23 @@ ivas_error TDREND_Update_listener_orientation_fx( move16(); /* Obtain head rotation matrix */ - QuatToRotMat_fx( *headPosition_fx, Rmat_fx ); // Rmat_fx Q: 2*Qx-32 + QuatToRotMat_fx( *headPosition_fx, Rmat_fx ); // Rmat_fx Q: 2*headPosition_q-32 Rmat_q = sub( shl( headPosition_q, 1 ), 32 ); /* Apply rotation matrix to looking vector [1;0;0] */ - FrontVec_fx[0] = Rmat_fx[0][0]; + FrontVec_fx[0] = Rmat_fx[0][0]; // Q Rmat_q move32(); - FrontVec_fx[1] = Rmat_fx[0][1]; + FrontVec_fx[1] = Rmat_fx[0][1]; // Q Rmat_q move32(); - FrontVec_fx[2] = Rmat_fx[0][2]; + FrontVec_fx[2] = Rmat_fx[0][2]; // Q Rmat_q move32(); /* Apply rotation matrix to up vector [0;0;1] */ - UpVec_fx[0] = Rmat_fx[2][0]; + UpVec_fx[0] = Rmat_fx[2][0]; // Q Rmat_q move32(); - UpVec_fx[1] = Rmat_fx[2][1]; + UpVec_fx[1] = Rmat_fx[2][1]; // Q Rmat_q move32(); - UpVec_fx[2] = Rmat_fx[2][2]; + UpVec_fx[2] = Rmat_fx[2][2]; // Q Rmat_q move32(); orient_q = Rmat_q; @@ -1244,9 +1244,9 @@ ivas_error TDREND_Update_listener_orientation_fx( IF( Pos_fx != NULL ) { /* Input position */ - Pos_p_fx[0] = ( *Pos_fx ).x_fx; - Pos_p_fx[1] = ( *Pos_fx ).y_fx; - Pos_p_fx[2] = ( *Pos_fx ).z_fx; + Pos_p_fx[0] = ( *Pos_fx ).x_fx; // Q Pos_fx->q_fact + Pos_p_fx[1] = ( *Pos_fx ).y_fx; // Q Pos_fx->q_fact + Pos_p_fx[2] = ( *Pos_fx ).z_fx; // Q Pos_fx->q_fact } ELSE { @@ -1430,7 +1430,7 @@ ivas_error ivas_td_binaural_renderer_ext_fx( const Word16 ism_md_subframe_update_ext, /* i : Metadata Delay in subframes to sync with audio delay */ const Word32 output_Fs, /* i : output sampling rate */ const Word16 output_frame, /* i : output frame length */ - Word32 output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + Word32 output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis Q11 */ Word16 *exp ) { ISM_METADATA_FRAME hIsmMetaDataFrame; @@ -1659,15 +1659,15 @@ static void angles_to_vec_fx( ) { Word16 elevation_fx, azimuth_fx; - elevation_fx = (Word16) L_shr( Mult_32_16( elevation, 91 ), 7 ); + elevation_fx = (Word16) L_shr( Mult_32_16( elevation, 91 ), 7 ); // Q15 move16(); - azimuth_fx = (Word16) L_shr( Mult_32_16( azimuth, 91 ), 7 ); + azimuth_fx = (Word16) L_shr( Mult_32_16( azimuth, 91 ), 7 ); // Q15 move16(); - vec[0] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getCosWord16R2( azimuth_fx ) ) ); + vec[0] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getCosWord16R2( azimuth_fx ) ) ); // Qx + 16 move32(); - vec[1] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getSineWord16R2( azimuth_fx ) ) ); + vec[1] = L_mult( radius, mult( getCosWord16R2( elevation_fx ), getSineWord16R2( azimuth_fx ) ) ); // Qx + 16 move32(); - vec[2] = L_mult( radius, getSineWord16R2( elevation_fx ) ); + vec[2] = L_mult( radius, getSineWord16R2( elevation_fx ) ); // Qx + 16 move32(); return; } diff --git a/lib_rend/ivas_objectRenderer_hrFilt.c b/lib_rend/ivas_objectRenderer_hrFilt.c index 8568da9eb6b18b2f74b126746df731bbf216d70b..2b0343c80aa469d39415b46cdb8d072998851e11 100644 --- a/lib_rend/ivas_objectRenderer_hrFilt.c +++ b/lib_rend/ivas_objectRenderer_hrFilt.c @@ -93,14 +93,14 @@ ivas_error TDREND_REND_RenderSourceHRFilt( } #else ivas_error TDREND_REND_RenderSourceHRFilt_fx( - TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ - Word32 *hrf_left_delta_fx, /* i/o: Left filter interpolation delta */ - Word16 *hrf_left_delta_e, /* i/o: Left filter interpolation delta exp */ - Word32 *hrf_right_delta_fx, /* i/o: Right filter interpolation delta */ - Word16 *hrf_right_delta_e, /* i/o: Right filter interpolation delta exp */ - const Word16 intp_count, /* i : Interpolation count */ - Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ - const Word16 subframe_length /* i : Subframe length in use */ + TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ + Word32 *hrf_left_delta_fx, /* i/o: Left filter interpolation delta */ + Word16 *hrf_left_delta_e, /* i/o: Left filter interpolation delta exp */ + Word32 *hrf_right_delta_fx, /* i/o: Right filter interpolation delta */ + Word16 *hrf_right_delta_e, /* i/o: Right filter interpolation delta exp */ + const Word16 intp_count, /* i : Interpolation count */ + Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer same Q as Src_p->InputFrame_p_fx Q11 */ + const Word16 subframe_length /* i : Subframe length in use */ ) { Word32 LeftOutputFrame_fx[L_SPATIAL_SUBFR_48k]; // will have same Q as Src_p->InputFrame_p_fx @@ -135,8 +135,8 @@ ivas_error TDREND_REND_RenderSourceHRFilt_fx( move16(); /* Copy to accumulative output frame */ - v_add_32( LeftOutputFrame_fx, output_buf_fx[0], output_buf_fx[0], subframe_length ); // Same Q as Src_p->InputFrame_p_fx - v_add_32( RightOutputFrame_fx, output_buf_fx[1], output_buf_fx[1], subframe_length ); // Same Q as Src_p->InputFrame_p_fx + v_add_32( LeftOutputFrame_fx, output_buf_fx[0], output_buf_fx[0], subframe_length ); // Same Q as Src_p->InputFrame_p_fx Q11 + v_add_32( RightOutputFrame_fx, output_buf_fx[1], output_buf_fx[1], subframe_length ); // Same Q as Src_p->InputFrame_p_fx Q11 return IVAS_ERR_OK; } @@ -190,7 +190,7 @@ void GetFilterFromAngle_fx( Word16 *hrf_left_e, /* o : Left HR filter exponent */ Word32 *hrf_right_fx, /* o : Right HR filter */ Word16 *hrf_right_e, /* o : Right HR filter exponent */ - Word16 *itd /* o : ITD value */ + Word16 *itd /* o : ITD value Q0 */ ) { GenerateFilter_fx( Elev_fx, Azim_fx, &HrFiltSet_p->ModelParams, &HrFiltSet_p->ModelEval ); @@ -206,7 +206,7 @@ void GetFilterFromAngle_fx( IF( HrFiltSet_p->ModelParams.UseItdModel ) { GenerateITD_fx( Elev_fx, Azim_fx, &HrFiltSet_p->ModelParamsITD, &HrFiltSet_p->ModelEval ); - *itd = extract_l( HrFiltSet_p->ModelEval.itdMod_fx ); + *itd = extract_l( HrFiltSet_p->ModelEval.itdMod_fx ); // Q0 move16(); } ELSE @@ -401,13 +401,13 @@ static void GenerateFilter_fx( azim = L_add( azim, model->azimKSeq_fx[p][0] ); WHILE( GT_32( azim, DEG_360_IN_Q22 ) ) { - azim = L_sub( azim, DEG_360_IN_Q22 ); + azim = L_sub( azim, DEG_360_IN_Q22 ); // Q22 } IF( azim < 0 ) { - azim = L_add( azim, DEG_360_IN_Q22 ); + azim = L_add( azim, DEG_360_IN_Q22 ); // Q22 } - azim = L_sub( azim, model->azimKSeq_fx[p][0] ); + azim = L_sub( azim, model->azimKSeq_fx[p][0] ); // Q22 IF( EQ_16( model->azimDim3[EvIdx[p]], 1 ) ) /* Constant basis function */ { @@ -699,13 +699,13 @@ static void GenerateITD_fx( azim_fx = L_add( azim_fx, model->azimKSeq_fx[0] ); WHILE( GT_32( azim_fx, DEG_360_IN_Q22 ) ) { - azim_fx = L_sub( azim_fx, DEG_360_IN_Q22 ); + azim_fx = L_sub( azim_fx, DEG_360_IN_Q22 ); // Q22 } if ( azim_fx < 0 ) { - azim_fx = L_add( azim_fx, DEG_360_IN_Q22 ); + azim_fx = L_add( azim_fx, DEG_360_IN_Q22 ); // Q22 } - azim_fx = L_sub( azim_fx, model->azimKSeq_fx[0] ); + azim_fx = L_sub( azim_fx, model->azimKSeq_fx[0] ); // Q22 IF( NE_32( L_abs( elev_fx ), DEG_90_IN_Q22 ) ) { @@ -717,7 +717,7 @@ static void GenerateITD_fx( if ( GT_32( azim_fx, DEG_180_IN_Q22 ) ) { /* Flip spline functions around 180 deg */ - azim_itd_fx = L_sub( DEG_360_IN_Q22, azim_fx ); + azim_itd_fx = L_sub( DEG_360_IN_Q22, azim_fx ); // Q22 } getStandardBSplineSampVec_fx( modelEval->azimBfVecITD_fx, AzIdx, &num_az_idx, shr( add( model->azimDim3, 1 ), 1 ), azim_itd_fx, model->azimKSeq_fx, model->azimSegSamples, model->azimBsLen, model->azimBsStart, model->azimBsShape_fx ); diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 32af0e0158ae66c938ecc2f1068c33a16ae9b0f1..ca2440753dc1c45ef06d7bbb09de4898c700e0fd 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -267,8 +267,8 @@ void ivas_output_init( case IVAS_AUDIO_CONFIG_STEREO: hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP2_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP2_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP2_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP2_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_FOA: hOutSetup->ambisonics_order = SBA_FOA_ORDER; @@ -289,8 +289,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP6_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP6_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP6_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP6_fx; // Q22 hOutSetup->is_planar_setup = 1; move16(); BREAK; @@ -301,8 +301,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP12_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP12_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP12_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP12_fx; // Q22 hOutSetup->is_planar_setup = 1; move16(); BREAK; @@ -313,8 +313,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP14_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP14_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP14_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP14_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; @@ -325,8 +325,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP16_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP16_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP16_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP16_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; @@ -337,8 +337,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP19_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP19_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP19_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP19_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 3d783bbaa73a8336ba0294a367bab092c34aad02..7e7d93588a9c98e402e994ae03e2217c4e710df2 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -320,16 +320,16 @@ ivas_error ivas_sba_get_hoa_dec_matrix( ); #else ivas_error ivas_sba_get_hoa_dec_matrix_fx( - const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ - Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ + Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix, Q29 */ const Word16 ambisonics_order /* i : Ambisonics order */ ); #endif #ifdef IVAS_FLOAT_FIXED void ivas_dirac_dec_binaural_sba_gain_fx( - Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output */ - const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ - const Word16 output_frame /* i : output frame length */ + Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output, inp Qx, out Qx-1 */ + const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ + const Word16 output_frame /* i : output frame length */ ); #endif void ivas_dirac_dec_binaural_sba_gain( @@ -353,7 +353,7 @@ void ivas_dirac_dec_binaural_render_fx( UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */ UWord16 *nSamplesAvailable, /* o : number of CLDFB slots still to render */ const Word16 nchan_transport, /* i : number of transport channels */ - Word32 *output_f[] /* o : rendered time signal */ + Word32 *output_f[] /* o : rendered time signal, Q11 */ ); #endif #ifndef IVAS_FLOAT_FIXED @@ -1195,7 +1195,7 @@ ivas_error ivas_td_binaural_renderer_unwrap_fx( ISM_METADATA_HANDLE *hIsmMetaData, /* i : ISM metadata handle */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i/o: combined orientaton data handle */ const Word16 ism_md_subframe_update, /* i : Number of subframes to delay ism metadata to sync with audio */ - Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis */ + Word32 *output_fx[], /* i/o: SCE channels / Binaural synthesis Q11 */ const Word16 output_frame, /* i : output frame length */ const Word16 num_subframes /* i : number of subframes to render */ ); @@ -1239,7 +1239,7 @@ ivas_error ivas_td_binaural_renderer_ext_fx( const Word16 ism_md_subframe_update_ext, /* i : Metadata Delay in subframes to sync with audio delay */ const Word32 output_Fs, /* i : output sampling rate */ const Word16 output_frame, /* i : output frame length */ - Word32 output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis */ + Word32 output[][L_FRAME48k], /* i/o: SCE channels / Binaural synthesis Q11 */ Word16 *exp ); @@ -1310,7 +1310,7 @@ ivas_error TDREND_GetMix( ivas_error TDREND_GetMix_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 */ - const Word16 subframe_length, /* i/o: subframe length */ + const Word16 subframe_length, /* i/o: subframe length Q11 */ const Word16 subframe_idx, /* i : Subframe index to 5 ms subframe */ const Word16 ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ ); @@ -1365,7 +1365,7 @@ void GetFilterFromAngle_fx( Word16 *hrf_left_e, /* o : Left HR filter exponent */ Word32 *hrf_right_fx, /* o : Right HR filter */ Word16 *hrf_right_e, /* o : Right HR filter exponent */ - Word16 *itd /* o : ITD value */ + Word16 *itd /* o : ITD value Q0 */ ); #endif @@ -1381,7 +1381,7 @@ ivas_error TDREND_REND_RenderSourceHRFilt_fx( Word32 *hrf_right_delta_fx, /* i/o: Right filter interpolation delta */ Word16 *hrf_right_delta_e, /* i/o: Right filter interpolation delta exp */ const Word16 intp_count, /* i : Interpolation count */ - Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ + Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer same Q as Src_p->InputFrame_p_fx Q11 */ const Word16 subframe_length /* i : Subframe length in use */ ); #else @@ -1792,10 +1792,10 @@ ivas_error ivas_binaural_reverb_open_fastconv( ivas_error ivas_binaural_reverb_open_parambin( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ - const int16_t numBins, /* i : number of CLDFB bins */ - const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + const int16_t numBins, /* i : number of CLDFB bins Q0 */ + const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame Q0 */ IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */ - const int32_t sampling_rate, /* i : sampling rate */ + const int32_t sampling_rate, /* i : sampling rate Q0 */ const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ ); @@ -1858,9 +1858,9 @@ ivas_error ivas_reverb_process_fx( const REVERB_HANDLE hReverb, /* i : Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const Word16 mix_signals, /* i : add reverb to output signal */ - Word32 *pcm_in[], /* i : the PCM audio to apply reverb on */ + Word32 *pcm_in[], /* i (Q11): the PCM audio to apply reverb on */ Word32 *pcm_out[], /* o : the PCM audio with reverb applied */ - const Word16 i_ts /* i : subframe index */ + const Word16 i_ts /* i : (Q0) subframe index */ ); #endif ivas_error ivas_reverb_process( @@ -2785,14 +2785,14 @@ void computeReferencePower_ana( #ifdef IVAS_FLOAT_FIXED void ivas_create_masa_out_meta_fx( - MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */ - SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */ - const Word16 nchan_transport, /* i : Number of transport channels */ - Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation */ - Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth */ - Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */ - Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */ - Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */ + MASA_DECODER_EXT_OUT_META_HANDLE extOutMeta, /* i/o: MASA metadata handle */ + SPHERICAL_GRID_DATA *Sph_Grid16, /* i : Spherical grid */ + const Word16 nchan_transport, /* i : Number of transport channels */ + Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated elevation Q22 */ + Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated azimuth Q22 */ + Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated direct-to-total ratio */ + Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated spread coherence */ + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* i : Estimated surround coherence */ Word16 energyRatio_q, Word16 spreadCoherence_q, Word16 surroundingCoherence_q @@ -2824,8 +2824,8 @@ ivas_error ivas_dirac_ana_open( #ifdef IVAS_FLOAT_FIXED void ivas_dirac_ana_fx( - DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ - Word32 data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ + DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ + Word32 data_in_fx[][L_FRAME48k], /* i/o: Input / transport audio signals, Q7 */ const Word16 input_frame, /* i : Input frame size */ const Word16 nchan_transport /* i : Number of transport channels */ ); diff --git a/lib_rend/ivas_reflections.c b/lib_rend/ivas_reflections.c index 00d4d0ef9509e31a5f4788dafa15e7c3f9556d28..5ea7dad8ec608a2a8e67c93e3dc66608655f4f6c 100644 --- a/lib_rend/ivas_reflections.c +++ b/lib_rend/ivas_reflections.c @@ -244,7 +244,7 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_MONO: reflections->shoebox_data.n_sources = 1; reflections->n_LC_sources = 1; - reflections->LC_mixing = LC_mixing_5_1; + reflections->LC_mixing = LC_mixing_5_1; /*Q0*/ move16(); move16(); move16(); @@ -259,15 +259,15 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_STEREO: reflections->shoebox_data.n_sources = 2; reflections->n_LC_sources = 2; - reflections->LC_mixing = LC_mixing_5_1; + reflections->LC_mixing = LC_mixing_5_1; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP2_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP2_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP2_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP2_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -277,15 +277,15 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_5_1: reflections->shoebox_data.n_sources = 5; reflections->n_LC_sources = 3; - reflections->LC_mixing = LC_mixing_5_1; + reflections->LC_mixing = LC_mixing_5_1; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP6_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP6_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP6_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP6_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -295,14 +295,14 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_7_1: reflections->shoebox_data.n_sources = 7; reflections->n_LC_sources = 5; - reflections->LC_mixing = LC_mixing_7_1; + reflections->LC_mixing = LC_mixing_7_1; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP12_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP12_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP12_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP12_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -312,14 +312,14 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_5_1_2: reflections->shoebox_data.n_sources = 7; reflections->n_LC_sources = 5; - reflections->LC_mixing = LC_mixing_5_1_2; + reflections->LC_mixing = LC_mixing_5_1_2; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP14_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP14_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP14_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP14_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -329,14 +329,14 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_5_1_4: reflections->shoebox_data.n_sources = 9; reflections->n_LC_sources = 5; - reflections->LC_mixing = LC_mixing_5_1_4; + reflections->LC_mixing = LC_mixing_5_1_4; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP16_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP16_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP16_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP16_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -346,14 +346,14 @@ ivas_error ivas_er_set_reflections_mode( case IVAS_AUDIO_CONFIG_7_1_4: reflections->shoebox_data.n_sources = 11; reflections->n_LC_sources = 5; - reflections->LC_mixing = LC_mixing_7_1_4; + reflections->LC_mixing = LC_mixing_7_1_4; /*Q0*/ move16(); move16(); move16(); FOR( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { - reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP19_idx[ch]; - reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP19_idx[ch]; + reflections->source_positions_fx[i_mult( 3, ch )] = ls_azimuth_CICP19_idx[ch]; /*Q0*/ + reflections->source_positions_fx[add( 1, i_mult( 3, ch ) )] = ls_elevation_CICP19_idx[ch]; /*Q0*/ reflections->source_positions_fx[add( 2, i_mult( 3, ch ) )] = ER_RADIUS_FX; move32(); move32(); @@ -597,8 +597,8 @@ ivas_error ivas_er_encoder_init( { /* Compute cartesian points for reflection (from degrees) */ - p_x_fx = reflections->shoebox_data.el_angle.data_fx[i]; - p_y_fx = reflections->shoebox_data.az_angle.data_fx[i]; + p_x_fx = reflections->shoebox_data.el_angle.data_fx[i]; // Q23 + p_y_fx = reflections->shoebox_data.az_angle.data_fx[i]; // Q23 move32(); move32(); @@ -639,9 +639,9 @@ ivas_error ivas_er_encoder_init( p_y_src_fx = Mpy_32_32( src_pos_ptr_fx[2], tmp_data_fx ); // .28 =.29*.30 p_z_src_fx = Mpy_32_32( src_pos_ptr_fx[2], shoebox_sin_cos_tbl_fx[( src_pos_ptr_fx[1] )][0] ); //.29 = .30 * .30 - p_x_src_fx = L_shr( p_x_src_fx, 14 ); - p_y_src_fx = L_shr( p_y_src_fx, 14 ); - p_z_src_fx = L_shr( p_z_src_fx, 15 ); + p_x_src_fx = L_shr( p_x_src_fx, 14 ); // Q.14 + p_y_src_fx = L_shr( p_y_src_fx, 14 ); // Q.14 + p_z_src_fx = L_shr( p_z_src_fx, 15 ); // Q.14 tmp_data = L_sub( p_x_src_fx, p_x_fx ); tmp16 = extract_l( tmp_data ); // Q.14 @@ -755,7 +755,7 @@ ivas_error ivas_er_compute_reflections( { FOR( j = 0; j < reflections->shoebox_data.n_ref; j++ ) { - tmp_fx = reflections->shoebox_data.times.data_fx[add( j, i_mult( i, reflections->shoebox_data.n_ref ) )]; + tmp_fx = reflections->shoebox_data.times.data_fx[add( j, i_mult( i, reflections->shoebox_data.n_ref ) )]; // Q23 tmp_fx_lo = u_extract_l( tmp_fx ); Mpy_32_16_uu( tmp_fx, (UWord16) reflections->output_Fs_fx, &tmp_fx1, &tmp_fx_lo ); tmp_fx1 = (UWord32) L_add( tmp_fx1, 0x20 ); @@ -937,7 +937,7 @@ ivas_error ivas_er_process( er_struct_t *reflections, const Word16 subframe_size, const Word16 subframe_idx, - Word32 **io, + Word32 **io, /*Q11*/ const AUDIO_CONFIG inConfig ) { ivas_error error = IVAS_ERR_OK; @@ -974,12 +974,12 @@ ivas_error ivas_er_process( /* If low complexity ER are requested only compute ER for n_LC_sources */ IF( reflections->lowComplexity ) { - n_ref_sources = reflections->n_LC_sources; + n_ref_sources = reflections->n_LC_sources; // Q0 move16(); } ELSE { - n_ref_sources = reflections->shoebox_data.n_sources; + n_ref_sources = reflections->shoebox_data.n_sources; // Q0 move16(); } @@ -993,7 +993,7 @@ ivas_error ivas_er_process( // buf_ch_idx = ( reflections->lowComplexity == 1 ) ? reflections->LC_mixing[i] : i; IF( EQ_32( reflections->lowComplexity, 1 ) ) { - buf_ch_idx = reflections->LC_mixing[i]; + buf_ch_idx = reflections->LC_mixing[i]; // Q0 move16(); } ELSE diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 73de5a7e627196130cfbaaabecbfd3ccaf8c110e..544f4310c8e6fdbf640eb7a9b90598644b7190e7 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -396,8 +396,8 @@ static void ivas_binaural_reverb_setReverbTimes( static void ivas_binaural_reverb_setReverbTimes_fx( REVERB_STRUCT_HANDLE hReverb, /* i/o: binaural reverb handle */ const Word32 output_Fs, /* i : sampling_rate */ - const Word32 *revTimes_fx, /* i : reverberation times T60 for each CLDFB bin in seconds */ - const Word32 *revEnes_fx /* i : spectrum for reverberated sound at each CLDFB bin */ + const Word32 *revTimes_fx, /*Q31 i : reverberation times T60 for each CLDFB bin in seconds */ + const Word32 *revEnes_fx /*Q31 i : spectrum for reverberated sound at each CLDFB bin */ ) { Word16 bin, ch, tap, sample; @@ -421,7 +421,7 @@ static void ivas_binaural_reverb_setReverbTimes_fx( tmp_exp = BASOP_Util_Add_MantExp( bin, 15, 1, 14, &tmp ); tmp = BASOP_Util_Divide3232_Scale( L_deposit_h( tmp ), L_deposit_h( hReverb->numBins ), &exp ); exp = add( exp, sub( tmp_exp, 15 ) ); - L_tmp = Mpy_32_16_1( output_Fs, tmp ); + L_tmp = Mpy_32_16_1( output_Fs, tmp ); /*- exp */ binCenterFreq_exp = add( 31, exp ); binCenterFreq_fx = L_shr( L_tmp, 1 ); // divide by 2 IF( bin == 0 ) @@ -438,7 +438,7 @@ static void ivas_binaural_reverb_setReverbTimes_fx( tmp = add( mult( EVS_PI_FX, tmp ), EPSILLON_FX ); // to avoid divide by 0 issue tmp_exp = sub( add( binCenterFreq_exp, 2 ), norm ); - sine_inp = wrap_rad_fixed( L_shl( tmp, sub( tmp_exp, 2 ) ) ); + sine_inp = wrap_rad_fixed( L_shl( tmp, sub( tmp_exp, 2 ) ) ); // Q13 sine = getSinWord16( sine_inp ); // Q15 div1 = BASOP_Util_Divide1616_Scale( sine, tmp, &scale ); @@ -510,8 +510,8 @@ static void ivas_binaural_reverb_setReverbTimes_fx( Word32 tmp_mul; scale = norm_l( hReverb->loopBufLength[bin] ); tmp_mul = L_shl( hReverb->loopBufLength[bin], scale ); - L_tmp = BASOP_Util_Log2( attenuationFactorPerSample_fx ); - L_tmp = L_add( L_tmp, L_shl( (Word32) attenuationFactorPerSample_exp, 25 ) ); + L_tmp = BASOP_Util_Log2( attenuationFactorPerSample_fx ); // Q25 + L_tmp = L_add( L_tmp, L_shl( (Word32) attenuationFactorPerSample_exp, 25 ) ); // Q25 L_tmp = Mpy_32_32( L_tmp, tmp_mul ); L_tmp = BASOP_util_Pow2( L_tmp, sub( 6 + 31, scale ), &exp ); hReverb->loopAttenuationFactor_fx[bin] = L_shl( L_tmp, exp ); // making as Q31 @@ -538,7 +538,7 @@ static void ivas_binaural_reverb_setReverbTimes_fx( move32(); energyBuildup_exp = 0; move16(); - currentEnergy_fx = 1073741824; + currentEnergy_fx = ONE_IN_Q30; move32(); currentEnergy_exp = 1; move16(); @@ -625,13 +625,13 @@ static void ivas_binaural_reverb_setReverbTimes_fx( *-----------------------------------------------------------------------------------------*/ static ivas_error compute_feedback_matrix_fx( - Word32 *pFeedbackMatrix, + Word32 *pFeedbackMatrix, // Q31 const Word16 n ) { Word32 u; Word16 i, j, x; - u = MATRIX_CONSTANT; + u = MATRIX_CONSTANT; // Q31 move32(); pFeedbackMatrix[0] = u; @@ -814,15 +814,15 @@ static ivas_error set_base_config_fx( /* set loop delays to default */ IF( EQ_32( output_Fs, 48000 ) ) { - selected_loop_delay = default_loop_delay_48k; + selected_loop_delay = default_loop_delay_48k; // Q0 } ELSE IF( EQ_32( output_Fs, 32000 ) ) { - selected_loop_delay = default_loop_delay_32k; + selected_loop_delay = default_loop_delay_32k; // Q0 } ELSE IF( EQ_32( output_Fs, 16000 ) ) { - selected_loop_delay = default_loop_delay_16k; + selected_loop_delay = default_loop_delay_16k; // Q0 } FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) @@ -931,7 +931,7 @@ static ivas_error set_base_config( *-----------------------------------------------------------------------------------------*/ static Word32 calc_dmx_gain_fx( void ) { - const Word32 gain = DMX_GAIN; + const Word32 gain = DMX_GAIN; // Q25 move32(); return gain; } @@ -974,11 +974,11 @@ static void calc_predelay_fx( if ( LT_16( output_frame, predelay ) ) { - predelay = output_frame; + predelay = output_frame; // Q0 move16(); } - pParams->pre_delay = predelay; + pParams->pre_delay = predelay; // Q0 move16(); move16(); move16(); @@ -1021,7 +1021,7 @@ static void calc_predelay( #ifdef IVAS_FLOAT_FIXED static ivas_error compute_t60_coeffs_fx( ivas_reverb_params_t *pParams, - const Word16 nr_fc_fft_filter, + const Word16 nr_fc_fft_filter, /*Q0*/ const Word32 output_Fs ) { Word16 bin_idx, loop_idx, tf_T60_len, len; @@ -1073,15 +1073,15 @@ static ivas_error compute_t60_coeffs_fx( tmp = BASOP_Util_Cmp_Mant32Exp( L_deposit_h( target_gains_db_fx[bin_idx] ), target_gains_db_exp[bin_idx], -2013265920, 7 ); IF( tmp < 0 ) { - target_gains_db_fx[bin_idx] = -30720; + target_gains_db_fx[bin_idx] = -30720; // -60 in Q9 -> -30720 move16(); target_gains_db_exp[bin_idx] = 7; move16(); } } - pCoeffs_a_fx = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( len, loop_idx ), 1 ), len )]; - pCoeffs_b_fx = &pParams->pT60_filter_coeff_fx[shl( i_mult( len, loop_idx ), 1 )]; + pCoeffs_a_fx = &pParams->pT60_filter_coeff_fx[add( shl( i_mult( len, loop_idx ), 1 ), len )]; // Q14 + pCoeffs_b_fx = &pParams->pT60_filter_coeff_fx[shl( i_mult( len, loop_idx ), 1 )]; // Q14 Word16 val = target_gains_db_exp[0]; move16(); @@ -1103,10 +1103,10 @@ static ivas_error compute_t60_coeffs_fx( } } - len = shr( ( add( pParams->t60_filter_order, 1 ) ), 1 ); /* == floor( (order+1) / 2) */ + len = shr( ( add( pParams->t60_filter_order, 1 ) ), 1 ); // Q0// /* == floor( (order+1) / 2) */ FOR( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) { - pParams->pLoop_delays[loop_idx] = sub( pParams->pLoop_delays[loop_idx], len ); + pParams->pLoop_delays[loop_idx] = sub( pParams->pLoop_delays[loop_idx], len ); // Q0 move16(); } return error; @@ -1328,13 +1328,13 @@ static void calc_low_shelf_first_order_filter_fx( move16(); norm_den1 = add( exp, sub( norm_den1, norm_den0 ) ); - pNum[0] = shr( pNum[0], sub( 1, norm_num0 ) ); + pNum[0] = shr( pNum[0], sub( 1, norm_num0 ) ); // Q14 move16(); - pNum[1] = shr( pNum[1], sub( 1, norm_num1 ) ); + pNum[1] = shr( pNum[1], sub( 1, norm_num1 ) ); // Q14 move16(); - pDen[1] = shr( pDen[1], sub( 1, norm_den1 ) ); + pDen[1] = shr( pDen[1], sub( 1, norm_den1 ) ); // Q14 move16(); - pDen[0] = shl( 1, 14 ); + pDen[0] = shl( 1, 14 ); // Q14 move16(); return; } @@ -1434,9 +1434,9 @@ static ivas_error calc_jot_t60_coeffs_fx( Word16 ref_hf_max_norm_fx = BASOP_Util_Divide1616_Scale( REF_HF_MAX_FX, fNyquist_fx, &scale4 ); ref_lf_min_norm_fx = shl( ref_lf_min_norm_fx, sub( scale1, 1 ) ); // Q14 - ref_lf_max_norm_fx = shl( ref_lf_max_norm_fx, sub( scale2, 1 ) ); - ref_hf_min_norm_fx = shl( ref_hf_min_norm_fx, sub( scale3, 1 ) ); - ref_hf_max_norm_fx = shl( ref_hf_max_norm_fx, sub( scale4, 1 ) ); + ref_lf_max_norm_fx = shl( ref_lf_max_norm_fx, sub( scale2, 1 ) ); // Q14 + ref_hf_min_norm_fx = shl( ref_hf_min_norm_fx, sub( scale3, 1 ) ); // Q14 + ref_hf_max_norm_fx = shl( ref_hf_max_norm_fx, sub( scale4, 1 ) ); // Q14 Word32 L_tmp; Word16 f0_fx, tmp_fx, lf_target_gain_dB_fx, hf_target_gain_dB_fx, mid_crossing_gain_dB_fx; @@ -1632,8 +1632,8 @@ static ivas_error set_t60_filter( REVERB_HANDLE hReverb, const UWord16 branch, const UWord16 nr_taps, - const Word16 coefA[], - const Word16 coefB[] ) + const Word16 coefA[], /*Q14*/ + const Word16 coefB[] /*Q14*/ ) { IF( GE_32( branch, hReverb->nr_of_branches ) ) { @@ -1683,7 +1683,7 @@ static ivas_error set_t60_filter( static ivas_error set_feedback_delay_fx( REVERB_HANDLE hReverb, const UWord16 branch, - const Word16 fb_delay ) + const Word16 fb_delay /*Q0*/ ) { IF( GE_32( branch, hReverb->nr_of_branches ) ) { @@ -1727,7 +1727,7 @@ static ivas_error set_feedback_delay( static ivas_error set_feedback_gain_fx( REVERB_HANDLE hReverb, const UWord16 branch, - const Word32 *pGain ) + const Word32 *pGain /*Q31*/ ) { UWord16 gain_idx; IF( GE_32( branch, hReverb->nr_of_branches ) ) @@ -1737,7 +1737,7 @@ static ivas_error set_feedback_gain_fx( FOR( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ ) { - hReverb->gain_matrix_fx[branch][gain_idx] = pGain[gain_idx]; + hReverb->gain_matrix_fx[branch][gain_idx] = pGain[gain_idx]; // Q31 move32(); } @@ -1894,7 +1894,7 @@ static ivas_error set_color_fft_filter( static ivas_error set_mixer_level_fx( REVERB_HANDLE hReverb, const UWord16 channel, - const Word16 level[] ) + const Word16 level[] /*Q0*/ ) { UWord16 branch_idx; IF( GE_32( channel, BINAURAL_CHANNELS ) ) @@ -1904,7 +1904,7 @@ static ivas_error set_mixer_level_fx( FOR( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ ) { - hReverb->mixer_fx[channel][branch_idx] = level[branch_idx]; + hReverb->mixer_fx[channel][branch_idx] = level[branch_idx]; /*Q0*/ move16(); } @@ -3038,7 +3038,7 @@ static void post_fft_filter( static void reverb_block_fx( REVERB_HANDLE hReverb, - Word32 *pInput_fx, + Word32 *pInput_fx, /*Q11*/ Word32 *pOut0_fx, Word32 *pOut1_fx ) @@ -3089,9 +3089,9 @@ static void reverb_block_fx( ivas_reverb_iir_filt_2taps_feed_blk_fx( &( hReverb->t60[i] ), inner_bsize, pTemp_fx, ppOutput_fx[i] ); FOR( ns = 0; ns < inner_bsize; ns++ ) { - pO0[ns] = L_add( imult3216( pOutput_i_fx[ns], mixer_0_i ), pO0[ns] ); /* mixer ch 0 */ + pO0[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_0_i ), pO0[ns] ); /* mixer ch 0 */ move32(); - pO1[ns] = L_add( imult3216( pOutput_i_fx[ns], mixer_1_i ), pO1[ns] ); /* mixer ch 1 */ + pO1[ns] = L_add_sat( imult3216( pOutput_i_fx[ns], mixer_1_i ), pO1[ns] ); /* mixer ch 1 */ move32(); } } @@ -3108,7 +3108,7 @@ static void reverb_block_fx( FOR( j = 0; j < nr_branches; j++ ) { - Word32 gain_matrix_j_i = hReverb->gain_matrix_fx[j][i]; + Word32 gain_matrix_j_i = hReverb->gain_matrix_fx[j][i]; // Q31 move32(); Word32 *pOutput = &ppOutput_fx[j][0]; FOR( ns = 0; ns < inner_bsize; ns++ ) @@ -3123,7 +3123,7 @@ static void reverb_block_fx( } Word16 r_shift; - r_shift = find_guarded_bits_fx( hReverb->fft_filter_ols.fft_size ); + r_shift = add( find_guarded_bits_fx( hReverb->fft_filter_ols.fft_size ), 1 ); // Applying guard bits for the DoRTFT inside the post_fft_filter function FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ ) { @@ -3139,6 +3139,14 @@ static void reverb_block_fx( post_fft_filter_fx( hReverb, pOut0_fx + start_sample_idx, pOut1_fx + start_sample_idx, pFFT_buf[0], pFFT_buf[1] ); } + FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ ) + { + pOut0_fx[k] = (Word32) L_shl( pOut0_fx[k], 1 ); + move32(); + pOut1_fx[k] = (Word32) L_shl( pOut1_fx[k], 1 ); + move32(); + } + return; } #else @@ -3243,9 +3251,9 @@ static void reverb_block( static ivas_error downmix_input_block_fx( const REVERB_HANDLE hReverb, - Word32 *pcm_in[], + Word32 *pcm_in[], /* i Q11 : the input PCM audio */ const AUDIO_CONFIG input_audio_config, - Word32 *pPcm_out, + Word32 *pPcm_out, /* o Q11 : the output PCM audio */ const Word16 input_offset ) { Word16 i, s, nchan_transport; @@ -3285,7 +3293,7 @@ static ivas_error downmix_input_block_fx( { FOR( s = 0; s < hReverb->full_block_size; s++ ) { - pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( pcm_in[0][input_offset + s], 8 ) ); + pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( pcm_in[0][input_offset + s], 8 ) ); //(Q23 + Q11 + Q8) - 31 = Q11 move32(); } BREAK; @@ -3366,8 +3374,8 @@ static ivas_error downmix_input_block( static void predelay_block_fx( const REVERB_HANDLE hReverb, - Word32 *pInput, - Word32 *pOutput ) + Word32 *pInput, /*Q11*/ + Word32 *pOutput /*Q11*/ ) { UWord16 i, idx, n_samples, blk_size; UWord16 max_blk_size = (UWord16) hReverb->predelay_line.Delay; @@ -3377,7 +3385,7 @@ static void predelay_block_fx( { FOR( i = 0; i < hReverb->full_block_size; i++ ) { - pOutput[i] = pInput[i]; + pOutput[i] = pInput[i]; // Q11 move32(); } } @@ -3385,7 +3393,7 @@ static void predelay_block_fx( { FOR( i = 0; i < hReverb->full_block_size; i++ ) { - pOutput[i] = ivas_rev_delay_line_get_sample_fx( &( hReverb->predelay_line ) ); + pOutput[i] = ivas_rev_delay_line_get_sample_fx( &( hReverb->predelay_line ) ); // Q11 move32(); ivas_rev_delay_line_feed_sample_fx( &( hReverb->predelay_line ), pInput[i] ); } @@ -3532,8 +3540,8 @@ ivas_error ivas_reverb_process_fx( const REVERB_HANDLE hReverb, /* i : Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const Word16 mix_signals, /* i : add reverb to output signal */ - Word32 *pcm_in_fx[], /* i : the PCM audio to apply reverb on */ - Word32 *pcm_out_fx[], /* o : the PCM audio with reverb applied */ + Word32 *pcm_in_fx[], /* i Q11 : the PCM audio to apply reverb on */ + Word32 *pcm_out_fx[], /* o Q11 : the PCM audio with reverb applied */ const Word16 i_ts /* i : subframe index */ ) { @@ -3783,13 +3791,12 @@ void ivas_binaural_reverb_processSubframe_fx( const Word16 numSlots, /* i : number of slots to be processed */ Word32 inReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i (Q_in) : input CLDFB data real, Comment: This change swaps two first dimensions as first dimension is not constant. */ Word32 inImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* i (Q_in) : input CLDFB data imag */ - Word32 outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : output CLDFB data real */ - Word32 outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* o : output CLDFB data imag */ + Word32 outReal[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o (Q_in) : output CLDFB data real */ + Word32 outImag[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /* o (Q_in) : output CLDFB data imag */ ) { /* Declare the required variables */ Word16 idx, bin, ch, sample, invertSampleIndex, tapIdx, *phaseShiftTypePr; - // float **tapRealPr, **tapImagPr; Word32 **tapRealPr_fx, **tapImagPr_fx; push_wmops( "binaural_reverb" ); @@ -3819,11 +3826,11 @@ void ivas_binaural_reverb_processSubframe_fx( { /* Add from pre-delay buffer a sample to the loop buffer, in a time-inverted order. * Also apply the spectral gains determined for the reverberation */ - Word32 temp_1 = Mpy_32_32( hReverb->preDelayBufferReal_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); - Word32 temp_2 = Mpy_32_32( hReverb->preDelayBufferImag_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); - hReverb->loopBufReal_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufReal_fx[bin][invertSampleIndex], temp_1 ); + Word32 temp_1 = Mpy_32_32( hReverb->preDelayBufferReal_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); /*Q_in*/ + Word32 temp_2 = Mpy_32_32( hReverb->preDelayBufferImag_fx[idx][bin], hReverb->reverbEqGains_fx[bin] ); /*Q_in*/ + hReverb->loopBufReal_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufReal_fx[bin][invertSampleIndex], temp_1 ); /*Q_in*/ move32(); - hReverb->loopBufImag_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufImag_fx[bin][invertSampleIndex], temp_2 ); + hReverb->loopBufImag_fx[bin][invertSampleIndex] = L_add( hReverb->loopBufImag_fx[bin][invertSampleIndex], temp_2 ); /*Q_in*/ move32(); hReverb->preDelayBufferReal_fx[idx][bin] = 0; move32(); @@ -3899,17 +3906,16 @@ void ivas_binaural_reverb_processSubframe_fx( { FOR( sample = 0; sample < numSlots; sample++ ) { - // float leftRe, rightRe, leftIm, rightIm; Word32 leftRe_fx, rightRe_fx, leftIm_fx, rightIm_fx; leftRe_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ), - Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ) ); + Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ) ); // Q_in rightRe_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferReal_fx[bin][1][sample] ), - Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ) ); + Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferReal_fx[bin][0][sample] ) ); // Q_in leftIm_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ), - Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ) ); + Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ) ); // Q_in rightIm_fx = L_add( Mpy_32_32( hReverb->binauralCoherenceDirectGains_fx[bin], hReverb->outputBufferImag_fx[bin][1][sample] ), - Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ) ); + Mpy_32_32( hReverb->binauralCoherenceCrossmixGains_fx[bin], hReverb->outputBufferImag_fx[bin][0][sample] ) ); // Q_in hReverb->outputBufferReal_fx[bin][0][sample] = leftRe_fx; // Q_in move32(); @@ -3934,9 +3940,9 @@ void ivas_binaural_reverb_processSubframe_fx( FOR( bin = 0; bin < hReverb->numBins; bin++ ) { - outReal[ch][sample][bin] = hReverb->outputBufferReal_fx[bin][ch][invertSampleIndex]; // Q_in + Q30 + outReal[ch][sample][bin] = hReverb->outputBufferReal_fx[bin][ch][invertSampleIndex]; // Q_in move32(); - outImag[ch][sample][bin] = hReverb->outputBufferImag_fx[bin][ch][invertSampleIndex]; // Q_in + Q30 + outImag[ch][sample][bin] = hReverb->outputBufferImag_fx[bin][ch][invertSampleIndex]; // Q_in move32(); } FOR( ; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) @@ -3962,12 +3968,12 @@ void ivas_binaural_reverb_processSubframe_fx( #ifdef IVAS_FLOAT_FIXED static ivas_error ivas_binaural_reverb_open_fx( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ - const Word16 numBins, /* i : number of CLDFB bins */ - const Word16 numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ - const Word32 sampling_rate, /* i : sampling rate */ - const Word32 *revTimes_fx, /* i : reverberation times T60 for each CLDFB bin in seconds */ - const Word32 *revEnes_fx, /* i : spectrum for reverberated sound at each CLDFB bin */ - const Word16 preDelay /* i : reverb pre-delay in CLDFB slots */ + const Word16 numBins, /* i : Q0 number of CLDFB bins */ + const Word16 numCldfbSlotsPerFrame, /* i : Q0 number of CLDFB slots per frame */ + const Word32 sampling_rate, /* i : Q0 sampling rate */ + const Word32 *revTimes_fx, /* i : Q31 reverberation times T60 for each CLDFB bin in seconds */ + const Word32 *revEnes_fx, /* i : Q31 spectrum for reverberated sound at each CLDFB bin */ + const Word16 preDelay /* i : Q0 reverb pre-delay in CLDFB slots */ ) { Word16 bin, chIdx, k, len, scale, tmp; @@ -4027,7 +4033,7 @@ static ivas_error ivas_binaural_reverb_open_fx( // hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 ); Word32 L_tmp_BufLength = L_shl( L_shr( Mpy_32_32( revTimes_fx[bin], 1258291200 /*150.0 in Q23*/ ), 23 ), 23 ); L_tmp_BufLength = L_add( Mpy_32_32( 1556925645 /*1.45 in Q30*/, L_tmp_BufLength ), ONE_IN_Q22 ); - hReverb->loopBufLength[bin] = (Word16) L_shr( L_tmp_BufLength, 22 ); + hReverb->loopBufLength[bin] = (Word16) L_shr( L_tmp_BufLength, 22 ); /*Q0*/ move16(); hReverb->loopBufLength[bin] = s_min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] ); @@ -4292,8 +4298,8 @@ ivas_error ivas_binaural_reverb_open_fastconv_fx( } ELSE { - revTimes = hHrtfFastConv->fastconvReverberationTimes_fx; - revEne = hHrtfFastConv->fastconvReverberationEneCorrections_fx; + revTimes = hHrtfFastConv->fastconvReverberationTimes_fx; /*Q31*/ + revEne = hHrtfFastConv->fastconvReverberationEneCorrections_fx; /*Q31*/ preDelay = 10; move16(); } @@ -4353,10 +4359,10 @@ ivas_error ivas_binaural_reverb_open_fastconv( #ifdef IVAS_FLOAT_FIXED ivas_error ivas_binaural_reverb_open_parambin( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ - const Word16 numBins, /* i : number of CLDFB bins */ - const Word16 numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + const Word16 numBins, /* i : number of CLDFB bins Q0 */ + const Word16 numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame Q0 */ IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */ - const int32_t sampling_rate, /* i : sampling rate */ + const int32_t sampling_rate, /* i : sampling rate Q0 */ const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ ) { @@ -4373,19 +4379,13 @@ ivas_error ivas_binaural_reverb_open_parambin( { revTimes = t60; revEne = ene; - /* Todo Philips: This needs a suitable function for ParamBin here. */ - // if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, internal_config, false, sampling_rate, t60, ene ) ) != IVAS_ERR_OK ) - // { - // return error; - // } - // preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); - preDelay = (Word16) L_shr_r( Mpy_32_32( 1677721600 /*800 in Q21*/, roomAcoustics->acousticPreDelay_fx /*Q27*/ ), Q17 ); + preDelay = (Word16) L_shr_r( Mpy_32_32( 1677721600 /*800 in Q21*/, roomAcoustics->acousticPreDelay_fx /*Q27*/ ), Q17 ); /*Q0*/ move16(); } ELSE { - revTimes = hHrtfParambin->parametricReverberationTimes_fx; - revEne = hHrtfParambin->parametricReverberationEneCorrections_fx; + revTimes = hHrtfParambin->parametricReverberationTimes_fx; /*Q31*/ + revEne = hHrtfParambin->parametricReverberationEneCorrections_fx; /*Q31*/ preDelay = 10; move16(); } diff --git a/lib_rend/ivas_reverb_iir_filter.c b/lib_rend/ivas_reverb_iir_filter.c index 454e2930a3c6619a0bafee20bebd95aab1f850f7..85245aadcccfb44dc15fde8aa3d2d928662de202 100644 --- a/lib_rend/ivas_reverb_iir_filter.c +++ b/lib_rend/ivas_reverb_iir_filter.c @@ -221,8 +221,8 @@ void ivas_reverb_iir_filt_2taps_feed_blk_fx( move32(); FOR( i = 0; i < blk_size; i++ ) { - flt_output_fx = L_add( Mpy_32_32( L_shl( input[i], 1 ), flt_CoefB_0_fx ), flt_pBuffer_0_fx ); - flt_pBuffer_0_fx = L_sub( L_add( flt_pBuffer_1_fx, Mpy_32_32( L_shl( input[i], 1 ), flt_CoefB_1_fx ) ), Mpy_32_32( L_shl( flt_output_fx, 1 ), flt_CoefA_1_fx ) ); + flt_output_fx = L_add( L_shl( Mpy_32_32( input[i], flt_CoefB_0_fx ), 1 ), flt_pBuffer_0_fx ); + flt_pBuffer_0_fx = L_sub( L_add( flt_pBuffer_1_fx, L_shl( Mpy_32_32( input[i], flt_CoefB_1_fx ), 1 ) ), L_shl( Mpy_32_32( flt_output_fx, flt_CoefA_1_fx ), 1 ) ); output[i] = flt_output_fx; move32(); } diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index d5d23e49c19a93e00a16a96ae7f6f431d7b9cd2b..b6f6274cf413f44126604b86b023552c28268d15 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -58,8 +58,8 @@ typedef struct ivas_output_setup_structure Word16 num_lfe; Word16 index_lfe[1]; - const Word32 *ls_azimuth_fx; - const Word32 *ls_elevation_fx; + const Word32 *ls_azimuth_fx; // Q22 + const Word32 *ls_elevation_fx; // Q22 UWord8 separateChannelEnabled; Word16 separateChannelIndex; @@ -941,7 +941,7 @@ typedef struct ivas_dirac_dec_binaural_data_structure Word32 ChCrossImOut_fx[CLDFB_NO_CHANNELS_MAX]; Word32 ChEneOut_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; Word32 ChEneOutPrev_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - Word32 frameMeanDiffuseness_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 frameMeanDiffuseness_fx[CLDFB_NO_CHANNELS_MAX]; /*Q29*/ Word32 ChCrossReOutPrev_fx[CLDFB_NO_CHANNELS_MAX]; Word32 ChCrossImOutPrev_fx[CLDFB_NO_CHANNELS_MAX]; @@ -2220,7 +2220,7 @@ typedef struct ivas_hrtfs_parambin_struct float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; #else - Word16 hrtfShCoeffsRe_fx[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; /* Q15 */ + Word16 hrtfShCoeffsRe_fx[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; /* Q14 */ Word16 hrtfShCoeffsIm_fx[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; /* Q14 */ #endif @@ -2437,13 +2437,13 @@ typedef struct ivas_mcmasa_ana_data_structure Word16 buffer_intensity_real_vert_q[DIRAC_NO_COL_AVG_DIFF]; Word32 buffer_energy_fx[DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS]; Word16 buffer_energy_q[DIRAC_NO_COL_AVG_DIFF]; - Word32 chnlToFoaMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; - Word32 chnlToFoaEvenMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; + Word32 chnlToFoaMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; // Q31 + Word32 chnlToFoaEvenMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; // Q31 Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS]; Word32 prevMultiChEne_fx; Word32 prevDownmixEne_fx; Word32 prevEQ_fx; - Word16 interpolator_fx[L_FRAME48k]; + Word16 interpolator_fx[L_FRAME48k]; // Q15 Word16 chnlToFoaMtx_e; Word16 prevMultiChEne_e; Word16 prevDownmixEne_e;