diff --git a/lib_com/cnst.h b/lib_com/cnst.h index f5cdaea66e3adf76b1a085da91235a9fd44d5ee2..3543fe64d0f5e83d36c6a362449433c8001f6687 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 */ @@ -737,6 +746,7 @@ enum #define PIT_L_INTERPOL6_2 17 #define PIT_FIR_SIZE6_2 ( PIT_UP_SAMP6 * PIT_L_INTERPOL6_2 + 1 ) #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 */ @@ -2752,6 +2762,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 */ diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index c76143a5e4fdc46182c083be8c8dfe97936e2191..d746b0ec199393cf5ca3f1529b02f12b4d3a8e17 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -703,6 +703,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 */ @@ -715,7 +716,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 */ @@ -3102,7 +3102,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 */ @@ -3681,7 +3691,26 @@ 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: front-VAD handles */ + const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t input_frame, /* i : frame length */ + int16_t vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ + float fr_bands[][2 * NB_BANDS], /* i : energy in frequency bands */ + float Etot_LR[], /* o : total energy Left & Right channel */ + float lf_E[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels */ + int16_t localVAD_HE_SAD[], /* o : HE-SAD flag without hangover, LR channels */ + int16_t vad_hover_flag[], /* o : VAD hangover flag */ + float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN */ + float *PS_out, /* o : energy spectrum */ + float *Bin_E_out, /* o : log-energy spectrum of the current frame*/ + Word16 Qinp +); +#endif ivas_error front_vad_spar( SPAR_ENC_HANDLE hSpar, /* i/o: SPAR encoder structure */ const float *omni_in, /* i : omnidirectional input signal */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 59dc816a1f79dc167cd9a0accf34f749c7ecc119..285c69eaaa5e36f21ba3c2d69aa34e39fc4bcf68 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( @@ -1402,10 +1402,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 */ ); @@ -2700,7 +2708,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 */ @@ -2708,6 +2715,32 @@ 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 spectral_balancer_fx16( Word16 *signal, /* i/o : signal Qx */ Word16 *mem, /* i/o : mem Qx */ @@ -2763,8 +2796,6 @@ void acelp_fast_fx( const Word16 L_subfr /* i : subframe length */ ); -#endif - void ivas_mdct_quant_coder_fx( CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ @@ -2819,4 +2850,17 @@ void InternalTCXDecoder_fx( 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 */ +); + #endif 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/parameter_bitmaping.c b/lib_com/parameter_bitmaping.c index 4c8d6d9993763eabe312a33229f06fe6ee9dab54..495890355d695b3ef9d889936e57645451b42894 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( 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 7a0bbfbc9642fdf48bf636247ac73de4911c9d13..1383ec487af78079e3f23b78ab17d2d265fc3a91 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 */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index f9b45da970a07f61f5cd8d069afc55278ee24d99..58f0ea49a81f297e04a327d916f974b86e774c3a 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -8730,6 +8730,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, diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index 8a73dc6bf7d75e75af492789fb601910be5e4c77..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, @@ -40860,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 1f8155cbc85dfec0f08b9acb68f61a1a9b15d90e..3c298732249f2c8f9ff5cb570be6b63a711f3d3a 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -207,6 +207,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 */ @@ -2150,9 +2151,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_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 463fa1fc5fa14180233bb3eacfac717446859085..742be031bcb8254f48983b8ee8eebe8b1dd2a39b 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -62,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 */ @@ -142,6 +142,7 @@ ivas_error acelp_core_enc( 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; @@ -170,11 +171,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 att_fx; Word16 lsp_new_fx[M]; /* i : LSPs at the end of the frame */ @@ -183,6 +186,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++ ) @@ -488,7 +493,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++ ) { @@ -499,17 +504,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 { @@ -521,7 +615,32 @@ ivas_error acelp_core_enc( 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 ); +#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 + mvr2r( exc2, exc3, st->L_frame ); if ( st->core_brate == SID_2k40 ) @@ -574,7 +693,10 @@ ivas_error acelp_core_enc( #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 ); @@ -588,7 +710,28 @@ 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 } /*Update MODE2 core switching memory*/ @@ -655,8 +798,8 @@ ivas_error acelp_core_enc( 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]; + // 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 ); @@ -933,11 +1076,40 @@ 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 */ { @@ -979,7 +1151,28 @@ 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*/ @@ -1102,7 +1295,7 @@ ivas_error acelp_core_enc( #ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 voice_factors_fx[NB_SUBFR16k]; + // Word16 voice_factors_fx[NB_SUBFR16k]; floatToFixed_arr16( voice_factors, voice_factors_fx, Q15, 5 ); st->hBWE_TD->bwe_non_lin_prev_scale_fx = floatToFixed( st->hBWE_TD->bwe_non_lin_prev_scale, Q30 ); @@ -1144,7 +1337,7 @@ ivas_error acelp_core_enc( #ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 pitch_buf_fx[NB_SUBFR16k]; + // Word16 pitch_buf_fx[NB_SUBFR16k]; floatToFixed_arr16( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); floatToFixed_arr16( st->old_pitch_buf, st->old_pitch_buf_fx, Q6, 2 * NB_SUBFR16k ); diff --git a/lib_enc/analy_sp_fx.c b/lib_enc/analy_sp_fx.c index e23c9b9a5eb4701391cfe37e7c43a7149f6ca0b5..49affa6e6b07024793c970f418a785eb3cf360c3 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 ( 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, ( 2 * Q_inp_dmx - 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/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/cod_tcx.c b/lib_enc/cod_tcx.c index edffd41358c27812810e82788e935a62e50f4ecc..b438baa3cfd5f3b665e55358423fddc65b7df866 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 = shr( add( pFilter[0]->predictionGain, pFilter[1]->predictionGain ), 1 ); // 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() * @@ -1560,7 +2206,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 ); diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index 0157c69714bb40fa365878893294baded3254f5c..e449b2420f5dbaef56632161f91ecc9af430191e 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -1152,17 +1152,31 @@ void ShapeSpectrum_ivas_fx( 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, NULL ); - FOR( i = L_frame; i < L_spec - L_frame; i++ ) + 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, q_spectrum ); + *spectrum_e = sub( 31 - 1, q_spectrum ); // As the output spectrum from sns_shape_spectrum_fx has Q = q_spectrum + 1 move16(); } ELSE @@ -1304,7 +1318,7 @@ void ShapeSpectrum_ivas_fx( test(); test(); test(); - IF( st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns ) + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) && st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns ) { PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e ); } diff --git a/lib_enc/evs_enc.c b/lib_enc/evs_enc.c index 487f00555850df61d1238ba43ccc4b90668c3b70..a80c21c3a436a6503f3ddcf168ec148e817c005d 100644 --- a/lib_enc/evs_enc.c +++ b/lib_enc/evs_enc.c @@ -238,7 +238,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; } diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c index 47dadb33d00528d4aa08e40e48c40cc6e8eb007c..2c4374e4074b206ee8e49e2756e2ef275a5e9374 100644 --- a/lib_enc/ext_sig_ana.c +++ b/lib_enc/ext_sig_ana.c @@ -427,13 +427,6 @@ void core_signal_analysis_high_bitrate( if ( st->hTcxCfg->fIsTNSAllowed ) { // conv params to float // avgSqrCoef_flt = float(avgSqrCoef, Q 15) - hTcxEnc->tnsData[frameno].filter[0].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[0].avgSqrCoef, 15 ); - hTcxEnc->tnsData[frameno].filter[1].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[1].avgSqrCoef, 15 ); - - // avgSqrCoef_flt = float(avgSqrCoef, Q 15) - hTcxEnc->tnsData[frameno].filter[0].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[0].predictionGain, 7 ); - hTcxEnc->tnsData[frameno].filter[1].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[frameno].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 ); @@ -478,7 +471,45 @@ void core_signal_analysis_high_bitrate( 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 ); + } +#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 ); + } +#endif +#else ProcessIGF( st, hTcxEnc->spectrum[frameno], hTcxEnc->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); +#endif } } } diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index bfe9875936fe7441aa0cc04bc7e851acee6f603c..a9883f9278e18d746d388cb31235e47b9cbfb86f 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -1164,6 +1164,317 @@ 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++ ) + { + t1 = BASOP_Util_Log2( lr_in_ptr_fx[ch][p] ); // 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], 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 */ ) @@ -1372,7 +1683,6 @@ void FdCngEncodeMDCTStereoSID( { #ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 ms_ptr_e; Word16 weights_fx[24]; invTrfMatrix_fx = (Word32 *) tmpRAM_fx; @@ -1383,13 +1693,17 @@ void FdCngEncodeMDCTStereoSID( #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] ); -#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix, ms_ptr[ch], NULL ); +#endif } } @@ -1522,7 +1836,7 @@ void FdCngEncodeMDCTStereoSID( return; } - +#endif /*-------------------------------------------------------------------* * FdCngEncodeDiracMDCTStereoSID() @@ -1531,6 +1845,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 */ ) @@ -1555,6 +2113,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++ ) @@ -1611,40 +2170,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 - Word32 ms_ptr_t_fx[24]; - Word16 ms_ptr_t_e; - Word32 *invTrfMatrix_fx; - Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; Word16 weights_fx[24]; - invTrfMatrix_fx = (Word32 *) tmpRAM_fx; - f2me_buf( ms_ptr[0], ms_ptr_t_fx, &ms_ptr_t_e, N[0] ); - floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); floatToFixed_arr( weights, weights_fx, Q8, 24 ); #endif - msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_t_fx, ms_ptr_t_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights_fx, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[0] ); + 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] ); -#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix, ms_ptr[0], NULL ); +#endif /* set S to zero */ @@ -1653,7 +2245,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 ); @@ -1737,3 +2339,4 @@ void FdCngEncodeDiracMDCTStereoSID( return; } +#endif 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/igf_enc.c b/lib_enc/igf_enc.c index 7fa5ed9f0ef5920d63325eafa41637cc80ac2b7f..93e1c658a0675ab138734ad3ac09a4fed0dd34bc 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -3582,7 +3582,7 @@ void IGFEncApplyMono( #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 ); diff --git a/lib_enc/igf_enc_fx.c b/lib_enc/igf_enc_fx.c index 8be8d54e2af56560ba82c900cea8bab6c85ab900..6d60e02c08cc54b965dba305d9e5176b00505ae6 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_fx.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 ); - *pFrame_size += nb_bits_written; + /* delete the indice */ + ind_list[i].nb_bits = -1; + move16(); +} +} - /* update list of indices */ - hBstr->nb_ind_tot -= bsBits; - hBstr->nb_bits_tot -= nb_bits_written; +*pFrame_size = add( *pFrame_size, nb_bits_written ); +move16(); - return; +/* 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; } -#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 **************************************************************************/ diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 97a04df0dc67ffe79178f81c253a685060effeda..93d90dbcd78d5bac6b0e7c294fe0f09d0a890799 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -317,7 +317,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; } @@ -325,8 +325,117 @@ 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 ) @@ -563,11 +672,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 } } } diff --git a/lib_enc/ivas_core_pre_proc.c b/lib_enc/ivas_core_pre_proc.c index 8a10571be7297e9a03a0d985d24c7167cd6db013..b306b032e1f646a1ee14ada627f4d25d1f7a7068 100644 --- a/lib_enc/ivas_core_pre_proc.c +++ b/lib_enc/ivas_core_pre_proc.c @@ -657,14 +657,52 @@ ivas_error ivas_compute_core_buffers( { float *inp_16k, *new_inp_16k; float tmp, mem_decim16k_dummy[2 * L_FILT_MAX]; - const float *signal_in; + /*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 + signal_in_32fx = st->input32_fx; + signal_in_fx = st->input_fx; + Word16 Q_sig = -1; + move16(); + floatToFixed_arr( signal_in, signal_in_fx, Q_sig, 960 ); + floatToFixed_arrL( signal_in, signal_in_32fx, Q11, 960 ); + + Word16 mem_decim16k_fx[2 * L_FILT_MAX], exp_mem_decim16k = 0, Q_mem_decim16k = 0; + move16(); + move16(); + f2me_buf_16( st->mem_decim16k, mem_decim16k_fx, &exp_mem_decim16k, 2 * L_FILT_MAX ); + Q_mem_decim16k = sub( 15, exp_mem_decim16k ); + Word16 flag = 0; + FOR( Word16 i = 0; i < L_INP; i++ ) + { + IF( mem_decim16k_fx[i] != 0 ) + { + flag = 1; + move16(); + break; + } + } + if ( flag == 0 ) + { + exp_mem_decim16k = 15; + Q_mem_decim16k = 0; + move16(); + move16(); + } +#endif input_Fs = st->input_Fs; element_mode = st->element_mode; @@ -685,6 +723,31 @@ ivas_error ivas_compute_core_buffers( L_look = NS2SA( sr_core, ACELP_LOOK_NS ); /* lookahead at other sampling rate (16kHz, 25.6kHz, 32kHz) */ +#ifdef IVAS_FLOAT_FIXED + Word16 old_inp_16k_fx[L_INP], exp_old_inp_16k = 0, Q_old_inp_16k = 0; + move16(); + move16(); + Word16 *new_inp_16k_fx; + + f2me_buf_16( old_inp_16k, old_inp_16k_fx, &exp_old_inp_16k, L_INP ); + Word16 flag1 = 0; + move16(); + FOR( Word16 i = 0; i < L_INP; i++ ) + { + IF( old_inp_16k_fx[i] != 0 ) + { + flag1 = 1; + break; + } + } + if ( flag1 == 0 ) + { + exp_old_inp_16k = 15; + move16(); + } + + new_inp_16k_fx = old_inp_16k_fx + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ +#endif 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 */ @@ -692,6 +755,9 @@ ivas_error ivas_compute_core_buffers( if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_SCE ) { new_inp_16k -= NS2SA( sr_core, DELAY_FIR_RESAMPL_NS ); +#ifdef IVAS_FLOAT_FIXED + new_inp_16k_fx -= NS2SA( sr_core, DELAY_FIR_RESAMPL_NS ); +#endif } if ( element_mode == IVAS_CPE_DFT ) @@ -710,7 +776,271 @@ ivas_error ivas_compute_core_buffers( /*---------------------------------------------------------------* * Change the sampling frequency to 16/25.6/32 kHz *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + Word16 Q_new_inp_16k = 0, prev_Q_mem_decim16k = 0, Q_mem_decim16k_dummy = 0; + move16(); + move16(); + move16(); + Word16 size_mem_decim16k_dummy = 0, length_new_inp_16k = 0, mem_decim16k_size = 0; + move16(); + move16(); + move16(); + /*handle multiple modify_Fs calls updating differnt portions of new_inp_16k_fx*/ + Word16 len_1 = 0, len_2 = 0, len_3 = 0, len_4 = 0; + move16(); + move16(); + move16(); + move16(); + Word16 Q_len_1 = 0, Q_len_2 = 0, Q_len_3 = 0, Q_len_4 = 0; + move16(); + move16(); + move16(); + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + floatToFixed_arr32( signal_in, signal_in_32fx, Q11, 960 ); + floatToFixed_arr( signal_in, signal_in_fx, -1, 960 ); + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) + { + IF( EQ_32( input_Fs, sr_core ) ) + { + floatToFixed_arr32( signal_in - lMemRecalc, signal_in_32fx - lMemRecalc, Q11, lMemRecalc + 960 ); + floatToFixed_arr( signal_in - lMemRecalc, signal_in_fx - lMemRecalc, -1, lMemRecalc + 960 ); + } + ELSE IF( EQ_32( input_Fs, 32000 ) || EQ_32( input_Fs, 48000 ) ) + { + Word16 length_inp_tmp = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); + floatToFixed_arr32( signal_in - lMemRecalc - length_inp_tmp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), signal_in_32fx - lMemRecalc - length_inp_tmp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), Q11, lMemRecalc + length_inp_tmp + 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) + 960 ); + floatToFixed_arr( signal_in - lMemRecalc - length_inp_tmp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), signal_in_fx - lMemRecalc - length_inp_tmp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), -1, lMemRecalc + length_inp_tmp + 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) + 960 ); + + floatToFixed_arr32( signal_in - lMemRecalc + input_frame, signal_in_32fx - lMemRecalc + input_frame, Q11, lMemRecalc ); + floatToFixed_arr( signal_in - lMemRecalc + input_frame, signal_in_fx - lMemRecalc + input_frame, -1, lMemRecalc ); + } + } + ELSE IF( st->idchan == 0 ) + { + floatToFixed_arr( signal_in + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), signal_in_fx + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), -1, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + } +#endif + + 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 ); + move16(); + prev_Q_mem_decim16k = Q_mem_decim16k; + move16(); + Copy( 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 ), mem_decim16k_fx, shl( delay, 1 ) ); + Q_mem_decim16k = Q_sig; + move16(); + } + ELSE IF( EQ_32( input_Fs, 32000 ) || EQ_32( input_Fs, 48000 ) ) + { + Word16 scale_factor = sub( getScaleFactor16( signal_in_fx, 960 ), 1 ); + Copy_Scale_sig32_16( signal_in_32fx, signal_in_fx, 960, 16 - Q11 - 1 + scale_factor ); /*-1+scale_factor*/ + Q_sig = sub( scale_factor, 1 ); + + Scale_sig( mem_decim16k_fx, 2 * L_FILT_MAX, sub( sub( scale_factor, 1 ), sub( 15, exp_mem_decim16k ) ) ); + exp_mem_decim16k = sub( 15, add( sub( Q_sig, 1 ), scale_factor ) ); + + mem_decim16k_size = 2 * L_FILT_MAX; + Word16 Q_tmp = 0; + move16(); + Word16 size_new_inp_16k_fx = modify_Fs_fx( signal_in_fx, input_frame, input_Fs, new_inp_16k_fx, sr_core, mem_decim16k_fx, 0, &Q_tmp, &mem_decim16k_size ); + Q_old_inp_16k = add( sub( Q_tmp, 1 ), scale_factor ); + + Copy( mem_decim16k_fx, mem_decim16k_dummy_fx, 2 * L_FILT_MAX ); + set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); + Word16 Q_tmp1 = 0; + move16(); + size_mem_decim16k_dummy = 2 * L_FILT_MAX; + move16(); + Word16 size_temp1F_icatdmResampBuf = modify_Fs_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_tmp1, &size_mem_decim16k_dummy ); + + length_new_inp_16k = s_max( size_new_inp_16k_fx, size_temp1F_icatdmResampBuf ); + Q_old_inp_16k = add( sub( Q_tmp1, 1 ), scale_factor ); + Q_mem_decim16k = sub( scale_factor, 1 ); + } + } + 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 ); + prev_Q_mem_decim16k = Q_mem_decim16k; + move16(); + Copy( 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 ) ), mem_decim16k_fx, shl( delay, 1 ) ); + Q_mem_decim16k = Q_sig; + move16(); + } + 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 ); + + Word16 scale_factor = getScaleFactor16( signal_in_fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), lMemRecalc + length_inp + 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) + 960 ) - 1; + Copy_Scale_sig32_16( signal_in_32fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), signal_in_fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), lMemRecalc + length_inp + 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) + 960, 16 - Q11 - 1 + scale_factor ); /*-1+scale_factor*/ + Q_sig = sub( scale_factor, 1 ); + + Copy( signal_in_fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), mem_decim16k_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + mem_decim16k_size = 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); + Word16 Q_tmp = 0; + + length_new_inp_16k = modify_Fs_fx( signal_in_fx - lMemRecalc - length_inp - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), length_inp, input_Fs, new_inp_16k_fx - lMemRecalc_16k - length_16k, sr_core, mem_decim16k_fx, 0, &Q_tmp, &mem_decim16k_size ); + len_1 = length_new_inp_16k; + Q_new_inp_16k = add( sub( Q_tmp, 1 ), scale_factor ); + Q_len_1 = Q_new_inp_16k; + Q_mem_decim16k = sub( scale_factor, 1 ); + } + + Word16 scale_factor = getScaleFactor16( signal_in_fx - lMemRecalc, lMemRecalc + 960 ) - 1; + Copy_Scale_sig32_16( signal_in_32fx - lMemRecalc, signal_in_fx - lMemRecalc, lMemRecalc + 960, 16 - Q11 - 1 + scale_factor ); /*-1+scale_factor*/ + Q_sig = sub( scale_factor, 1 ); + + Scale_sig( mem_decim16k_fx, 2 * L_FILT_MAX, sub( sub( scale_factor, 1 ), sub( 15, exp_mem_decim16k ) ) ); + exp_mem_decim16k = sub( 15, ( add( sub( Q_sig, 1 ), scale_factor ) ) ); + Q_mem_decim16k = sub( scale_factor, 1 ); + mem_decim16k_size = 2 * L_FILT_MAX; + Word16 Q_tmp_1 = 0; + move16(); + move16(); + length_new_inp_16k = modify_Fs_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_16k_fx - ( lMemRecalc * sr_core ) / st->input_Fs, sr_core, mem_decim16k_fx, 0, &Q_tmp_1, &mem_decim16k_size ); + len_2 = length_new_inp_16k; + Copy( mem_decim16k_fx, mem_decim16k_dummy_fx, 2 * L_FILT_MAX ); + size_mem_decim16k_dummy = 2 * L_FILT_MAX; + move16(); + + Q_new_inp_16k = add( sub( Q_tmp_1, 1 ), scale_factor ); + Q_len_2 = Q_new_inp_16k; + move16(); + + Q_mem_decim16k = sub( scale_factor, 1 ); + Q_mem_decim16k_dummy = Q_mem_decim16k; + move16(); + + IF( lMemRecalc > 0 ) + { + Word16 scale_factor_1 = getScaleFactor16( signal_in_fx - lMemRecalc + input_frame, lMemRecalc ) - 1; + Copy_Scale_sig32_16( signal_in_32fx - lMemRecalc + input_frame, signal_in_fx - lMemRecalc + input_frame, lMemRecalc, 16 - Q11 - 1 + scale_factor_1 ); /*-1+scale_factor*/ + Q_sig = sub( scale_factor_1, 1 ); + Scale_sig( mem_decim16k_dummy_fx, 2 * L_FILT_MAX, ( -1 + scale_factor_1 ) - Q_mem_decim16k ); + exp_mem_decim16k = sub( 15, ( add( sub( Q_sig, 1 ), scale_factor_1 ) ) ); + mem_decim16k_size = 2 * L_FILT_MAX; + move16(); + Q_tmp_1 = 0; + move16(); + length_new_inp_16k = modify_Fs_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_1, &size_mem_decim16k_dummy ); + len_3 = length_new_inp_16k; + move16(); + Q_new_inp_16k = add( sub( Q_tmp_1, 1 ), scale_factor_1 ); + Q_len_3 = Q_new_inp_16k; + move16(); + Q_mem_decim16k_dummy = sub( scale_factor_1, 1 ); + size_mem_decim16k_dummy = mem_decim16k_size; + move16(); + } + + set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); + Word16 Q_tmp_2 = 0; + move16(); + length_new_inp_16k = modify_Fs_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_2, &mem_decim16k_size ); + len_4 = length_new_inp_16k; + Q_new_inp_16k = Q_tmp_2; + Q_len_4 = Q_new_inp_16k; + size_mem_decim16k_dummy = mem_decim16k_size; + move16(); + move16(); + move16(); + move16(); + } + } + 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 ), mem_decim16k_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + Q_mem_decim16k = -1; + move16(); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( element_mode == IVAS_SCE ) + { + if ( input_Fs == sr_core ) + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); + // prev_Q_mem_decim16k = Q_mem_decim16k; + Q_mem_decim16k = Q_sig; + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, Q_mem_decim16k, 2 * delay ); + fixedToFloat_arr( new_inp_16k_fx, new_inp_16k, prev_Q_mem_decim16k, delay ); + for ( int i = delay; i < input_frame; i++ ) + { + new_inp_16k[i] = fixedToFloat( new_inp_16k_fx[i], Q_sig ); + } + } + else if ( input_Fs == 32000 || input_Fs == 48000 ) + { + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, Q_mem_decim16k, mem_decim16k_size ); // can be removed + fixedToFloat_arr( new_inp_16k_fx, new_inp_16k, Q_old_inp_16k, length_new_inp_16k ); // can be removed + fixedToFloat_arr( mem_decim16k_dummy_fx, mem_decim16k_dummy, Q_mem_decim16k_dummy, size_mem_decim16k_dummy ); + } + } + else if ( element_mode == IVAS_CPE_TD ) + { + if ( input_Fs == sr_core ) + { + /* no resampling needed, only delay adjustment to account for the FIR resampling delay */ + delay = NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc - delay + L_FILT16k, new_inp_16k - lMemRecalc - delay + L_FILT16k, prev_Q_mem_decim16k, delay ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc + L_FILT16k, new_inp_16k - lMemRecalc + L_FILT16k, Q_sig, input_frame + lMemRecalc ); + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, -1, 2 * delay ); + } + else if ( input_Fs == 32000 || input_Fs == 48000 ) + { + /* reconstruct past segment of input signal when switching from MDCT stereo */ + if ( last_element_mode == IVAS_CPE_MDCT /*|| st->idchan == 1*/ ) + { + Word16 length_16k = NS2SA( INT_FS_16k, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, Q_mem_decim16k, mem_decim16k_size ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k - length_16k, new_inp_16k - lMemRecalc_16k - length_16k, Q_len_1, len_1 ); + } + + + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, Q_mem_decim16k, mem_decim16k_size ); + fixedToFloat_arr( new_inp_16k_fx - ( lMemRecalc * sr_core ) / st->input_Fs, new_inp_16k - ( lMemRecalc * sr_core ) / st->input_Fs, Q_len_2, len_2 ); + + if ( lMemRecalc > 0 ) + { + fixedToFloat_arr( new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ) - ( lMemRecalc * sr_core ) / st->input_Fs, new_inp_16k + NS2SA( sr_core, FRAME_SIZE_NS ) - ( lMemRecalc * sr_core ) / st->input_Fs, Q_len_3, len_3 ); + } + + fixedToFloat_arr( mem_decim16k_dummy_fx, mem_decim16k_dummy, Q_mem_decim16k_dummy, size_mem_decim16k_dummy ); + fixedToFloat_arr( new_inp_16k_fx + NS2SA( sr_core, FRAME_SIZE_NS ), new_inp_16k + NS2SA( sr_core, FRAME_SIZE_NS ), Q_len_4, len_4 ); + } + } + else if ( st->idchan == 0 ) + { + /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ + fixedToFloat_arr( mem_decim16k_fx, st->mem_decim16k, Q_mem_decim16k, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); + } +#endif + +#else if ( element_mode == IVAS_SCE ) { if ( input_Fs == sr_core ) @@ -769,6 +1099,8 @@ ivas_error ivas_compute_core_buffers( /* 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_decim16k, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); } +#endif + /*------------------------------------------------* * Update BWE memories * @@ -822,9 +1154,7 @@ 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]; } diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 8fca12d6cad5bfeec45eb7a202eb86865e0628bf..1f26d7586743bb83157aabc29bf699373c0fc0ca 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -196,12 +196,35 @@ ivas_error ivas_cpe_enc( } stereo_mode_combined_format_enc( st_ivas, hCPE ); +#ifdef IVAS_FLOAT_FIXED + Word16 Q_inp = Q15; + if ( hCPE->hFrontVad[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) + { - 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++ ) + { + + Q_inp = min( Q_inp, Q_factor_arr( sts[n]->input, L_FRAME48k ) ); + // floatToFixed_arr( sts[n]->input, st->input_fx, Q_inp, L_FRAME48k ); + } + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + + // Q_inp = L_min( Q_inp, Q_factor_arr( sts[n]->input, L_FRAME48k ) ); + floatToFixed_arr( sts[n]->input, sts[n]->input_fx, Q_inp, L_FRAME48k ); + } + } + if ( ( error = front_vad_fx( 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, Q_inp ) ) != IVAS_ERR_OK ) { return error; } +#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; @@ -893,11 +916,11 @@ 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 { - 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 ); } } diff --git a/lib_enc/ivas_front_vad.c b/lib_enc/ivas_front_vad.c index 95ead975af07e91064352e1c0d4a7753be3dc983..7c4c8379f7b1f9ca56b06a4b6c2f56b9f52508fe 100644 --- a/lib_enc/ivas_front_vad.c +++ b/lib_enc/ivas_front_vad.c @@ -242,7 +242,470 @@ ivas_error front_vad( pop_wmops(); return error; } +#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 int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const int16_t input_frame, /* i : frame length */ + int16_t vad_flag_dtx[], /* o : HE-SAD flag with additional DTX HO */ + float fr_bands[][2 * NB_BANDS], /* i : energy in frequency bands */ + float Etot_LR[], /* o : total energy Left & Right channel */ + float lf_E[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels */ + int16_t localVAD_HE_SAD[], /* o : HE-SAD flag without hangover, LR channels */ + int16_t vad_hover_flag[], /* o : VAD hangover flag */ + float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN*/ + float *PS_out, /* o : energy spectrum */ + float *Bin_E_out, /* o : log-energy spectrum of the current frame */ + Word16 Q_inp ) +{ + ENC_CORE_HANDLE *sts; + float band_energies[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 band_energies_fx[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 PS_fx[128]; + // Word32 *PS_out_fx; + // Word32 PS_out_buff_fx[128]; + Word16 *lgBin_E_fx; + float PS[L_FRAME / 2]; /* speech/music clasif. parameters */ + // float snr_sum_he; /* HE SAD parameters */ + Word16 snr_sum_he_fx; + float Bin_E[L_FFT]; /* per bin log energy spectrum for mid-frame */ + Word32 fr_bands_fx[2][2 * NB_BANDS] = { { 0 } }; + 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 */ + Word32 lf_E_fx[2][2 * VOIC_BINS]; + Word16 Etot_LR_fx[2]; + Word32 band_energies_LR_fx[2 * NB_BANDS]; + int16_t n, n_chan, dummy; + Word8 dummy_short; + int16_t element_mode, last_element_mode; + ivas_error error; + Word16 Q_buffer[2]; + + Word16 Q_new = 0, band_ener_guardbits = 0; + Word16 Qband, mem_decim_size, Q_band[2]; + error = IVAS_ERR_OK; + push_wmops( "front_vad" ); + + lgBin_E_fx = NULL; + if ( st != NULL ) + { + lgBin_E_fx = &st->lgBin_E_fx[0]; + } + if ( hCPE != NULL ) + { + n_chan = CPE_CHANNELS; + sts = &hCPE->hCoreCoder[0]; + element_mode = hCPE->element_mode; + last_element_mode = hCPE->last_element_mode; + } + else if ( st != NULL ) + { + n_chan = 1; + sts = &st; + element_mode = IVAS_SCE; + last_element_mode = IVAS_SCE; + } + else + { + assert( 0 && "Either CPE or SCE must be given!" ); + return IVAS_ERR_INTERNAL_FATAL; + } + + // snr_sum_he = 0; + for ( n = 0; n < n_chan; n++ ) + { + localVAD_HE_SAD[n] = 0; + vad_hover_flag[n] = 0; + vad_flag_dtx[n] = 1; + } + /*------------------------------------------------------------------* + * Allocate/deallocate hFrontVad handles in case of element_mode change + *-----------------------------------------------------------------*/ + + if ( sts[0]->ini_frame > 0 && MCT_flag == 0 && last_element_mode != element_mode ) + { + if ( element_mode == IVAS_CPE_MDCT ) + { + if ( hFrontVads[0] != NULL ) + { + for ( n = 0; n < n_chan; n++ ) + { + front_vad_destroy( &hFrontVads[n] ); + hFrontVads[n] = NULL; + } + } + } + else + { + if ( sts[0]->Opt_DTX_ON && hFrontVads[0] == NULL ) + { + for ( n = 0; n < n_chan; n++ ) + { + if ( ( error = front_vad_create( &hFrontVads[n], hEncoderConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + /* if ( ( error = front_vad_create_fx( &hFrontVads[n], hEncoderConfig ) ) != IVAS_ERR_OK ) + { + return error; + }*/ + } + } + } + } + + /* Only run VAD if DTX is on and TD stereo or unified stereo is selected */ + if ( hFrontVads[0] != NULL && element_mode != IVAS_CPE_MDCT ) + { + + /*------------------------------------------------------------------* + * VAD + *-----------------------------------------------------------------*/ + + set_zero( band_energies_LR, 2 * NB_BANDS ); + /* Q_new = Q15; + for ( n = 0; n < n_chan; n++ ) + { + Q_new =min(Q_new, Q_factor_arr( hFrontVads[n]->buffer_12k8, 384 )); + } + for ( n = 0; n < n_chan; n++ ) + { + floatToFixed_arr( hFrontVads[n]->mem_decim, hFrontVads[n]->mem_decim_fx, Q_inp, 90 ); + hFrontVads[n]->mem_preemph_fx = (Word16) floatToFixed( hFrontVads[n]->mem_preemph, Q_inp ); + }*/ + Qband = -1; + Word16 Q_new_old = ( Q_inp + Qband ) + 3; + for ( n = 0; n < n_chan; n++ ) + { + floatToFixed_arr( hFrontVads[n]->mem_decim, hFrontVads[n]->mem_decim_fx, Q_inp, 90 ); + hFrontVads[n]->mem_preemph_fx = (Word16) floatToFixed( hFrontVads[n]->mem_preemph, Q_inp - 1 ); + Q_buffer[n] = Q_factor_arr( hFrontVads[n]->buffer_12k8 + L_FFT, L_FFT / 2 ); + floatToFixed_arr( hFrontVads[n]->buffer_12k8, hFrontVads[n]->buffer_12k8_fx, Q_buffer[n], 384 ); + hFrontVads[n]->hNoiseEst->Etot_h_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_h * 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_l_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_l * 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_l_lp_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_l_lp * 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_last_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_last * 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_v_h2_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_v_h2 * 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_lp_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->Etot_lp * 16777216.0 ); + hFrontVads[n]->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( hFrontVads[n]->hNoiseEst->sign_dyn_lp * 16777216.0 ); + + hFrontVads[n]->lp_noise_fx = (Word16) floatToFixed( hFrontVads[n]->lp_noise, Q8 ); + hFrontVads[n]->lp_speech_fx = (Word16) floatToFixed( hFrontVads[n]->lp_speech, Q8 ); + sts[n]->lp_speech_fx = (Word16) floatToFixed( sts[n]->lp_speech, Q8 ); + sts[n]->lp_noise_fx = (Word16) floatToFixed( sts[n]->lp_noise, Q8 ); + floatToFixed_arrL( hFrontVads[n]->hNoiseEst->bckr, hFrontVads[n]->hNoiseEst->bckr_fx, Q_new_old + QSCALE, 20 ); + floatToFixed_arrL( hFrontVads[n]->hNoiseEst->enrO, hFrontVads[n]->hNoiseEst->enrO_fx, Q_new_old + QSCALE, 20 ); + sts[n]->flag_noisy_speech_snr_fx = (Word8) sts[n]->flag_noisy_speech_snr; + hFrontVads[n]->hVAD->bcg_flux_fx = (Word16) hFrontVads[n]->hVAD->bcg_flux * ( 1 << 4 ); + + + hFrontVads[n]->hVAD->snr_sum_vad_fx = (Word16) ( hFrontVads[n]->hVAD->snr_sum_vad * 32767 ); + hFrontVads[n]->hVAD->prim_act_quick_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act_quick * 32767 ); + hFrontVads[n]->hVAD->prim_act_slow_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act_slow * 32767 ); + hFrontVads[n]->hVAD->prim_act_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act * 32767 ); + hFrontVads[n]->hVAD->prim_act_quick_he_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act_quick_he * 32767 ); + hFrontVads[n]->hVAD->prim_act_slow_he_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act_slow_he * 32767 ); + hFrontVads[n]->hVAD->prim_act_he_fx = (Word16) ( hFrontVads[n]->hVAD->prim_act_he * 32767 ); + } + floatToFixed_arrL( &band_energies_LR[0], &band_energies_LR_fx[0], Q_new_old + QSCALE + 2, 40 ); + 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]; + // hFrontVad->mem_preemph_fx = (Word16) floatToFixed( hFrontVad->mem_preemph, Q_inp ); + /* Move previous frame 12k8 signal */ + + MVR2R_WORD16( hFrontVad->buffer_12k8_fx + L_FFT, hFrontVad->buffer_12k8_fx, L_FFT / 2 ); + // mvr2r_Word16( hFrontVad->buffer_12k8_fx + L_FFT, hFrontVad->buffer_12k8_fx, L_FFT / 2 ); +#if 1 + // floatToFixed_arr( hFrontVad->mem_decim, hFrontVad->mem_decim_fx, Q_inp, 90 ); + // modify_Fs( sts[n]->input, input_frame, sts[0]->input_Fs, hFrontVad->buffer_12k8 + L_FFT / 2, INT_FS_12k8, hFrontVad->mem_decim, ( sts[0]->max_bwidth == NB ) ); + + /* 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 ); + // fixedToFloat_arr( hFrontVad->buffer_12k8_fx + L_FFT / 2, hFrontVad->buffer_12k8 + L_FFT / 2, Q_inp + Qband, 384 - L_FFT / 2 ); + // fixedToFloat_arr( hFrontVad->mem_decim_fx, hFrontVad->mem_decim, Q_inp, 90 ); + // Scale_sig( hFrontVad->buffer_12k8_fx + L_FFT / 2, 384 - L_FFT / 2, Q9 - (Q_inp + Qband )); + Q_band[n] = Qband; +#else + modify_Fs( sts[n]->input, input_frame, sts[0]->input_Fs, hFrontVad->buffer_12k8 + L_FFT / 2, INT_FS_12k8, hFrontVad->mem_decim, ( sts[0]->max_bwidth == NB ) ); + +#endif +#if 0 + /* Preemphasis */ + preemph( hFrontVad->buffer_12k8 + L_FFT / 2, PREEMPH_FAC_FLT, L_FRAME, &hFrontVad->mem_preemph ); +#else + /* Preemphasis */ + // hFrontVad->mem_preemph_fx = (Word16) floatToFixed( hFrontVad->mem_preemph, Q_inp + Qband ); + hFrontVad->mem_preemph_fx = shl( hFrontVad->mem_preemph_fx, -1 - Qband ); + /*Word16 temp = (Word16) floatToFixed( hFrontVad->mem_preemph, Q_inp + Qband ); + if ( abs(temp - hFrontVad->mem_preemph_fx) > 2 ) + { + printf( "%d\n", temp ); + + }*/ + // preemph( hFrontVad->buffer_12k8 + L_FFT / 2, PREEMPH_FAC_FLT, L_FRAME, &hFrontVad->mem_preemph ); + PREEMPH_FX( hFrontVad->buffer_12k8_fx + L_FFT / 2, PREEMPH_FAC, L_FRAME, &hFrontVad->mem_preemph_fx ); + // hFrontVad->mem_preemph = fixedToFloat( hFrontVad->mem_preemph_fx, Q_inp + Qband ); + // fixedToFloat_arr( hFrontVad->buffer_12k8_fx + L_FFT / 2, hFrontVad->buffer_12k8 + L_FFT / 2, Q_inp + Qband, 384 - L_FFT / 2 ); + +#endif +#if 0 + analy_sp( IVAS_CPE_TD, hCPE, sts[0]->input_Fs, hFrontVad->buffer_12k8 + L_FFT / 2 - 3 * ( L_SUBFR / 2 ), Bin_E, Bin_E_old, fr_bands[n], lf_E[n], &Etot_LR[n], sts[0]->min_band, sts[0]->max_band, band_energies, PS, fft_buffLR ); +#else + Word16 Scale_fac[2]; + Q_new = ( Q_inp + Qband ) + 3; + // if ( Q_buffer[n] < Q_inp + Qband ) + //{ + // Scale_sig( hFrontVad->buffer_12k8_fx, L_FFT / 2, Q_buffer[n] - Q_new ); + // //Scale_sig( hFrontVad->buffer_12k8_fx + L_FFT / 2, 384 - L_FFT / 2, Q_buffer[n] -( Q_inp + Qband) ); + // Q_new = Q_buffer[n]; + // // Scale_sig( hFrontVad->buffer_12k8_fx, L_FFT / 2, Q_inp + Qband - Q_buffer[n] ); + // } + // else + //{ + // Scale_sig( hFrontVad->buffer_12k8_fx + L_FFT / 2, 384 - L_FFT / 2, ( Q_inp + Qband ) - Q_buffer[n] ); + // Q_new = ( Q_inp + Qband ); + // } + + // Q_new = Q_factor_arr( hFrontVad->buffer_12k8, 384 ); + 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 - ( Q_inp + Qband ) ); + + Q_buffer[n] = Q_new; + // floatToFixed_arr( hFrontVad->buffer_12k8, hFrontVad->buffer_12k8_fx, Q_new, 384 ); + 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 ); + // fixedToFloat_arrL( fr_bands_fx[n], fr_bands[n], Q_new + QSCALE + 2, 40 ); + // fixedToFloat_arrL( band_energies_fx, band_energies, Q_new + QSCALE + 2, 40 ); + /* fixedToFloat_arrL( lf_E_fx[n], lf_E[n], Q_new + QSCALE - 2, 148 ); + if ( lgBin_E_fx != NULL ) + { + fixedToFloat_arr( lgBin_E_fx, Bin_E, Q7, 128 ); + } + fixedToFloat_arrL( PS_fx, PS, Q_new + QSCALE, 128 ); + Etot_LR[n] = fixedToFloat( Etot_LR_fx[n], Q8 );*/ + +#endif + + /* add up energies for later calculating average of channel energies */ + // v_add( &band_energies[0], &band_energies_LR[0], &band_energies_LR[0], 2 * NB_BANDS ); + // floatToFixed_arrL( &band_energies_LR[0], &band_energies_LR_fx[0], Q_new + QSCALE + 2, 40 ); + Scale_sig32( &band_energies_LR_fx[0], ( Q_new + QSCALE + 2 ) - ( Q_new_old + QSCALE + 2 - band_ener_guardbits ), 40 ); + // Scale_sig32( band_energies_fx,( Q_new + QSCALE + 2)-( Q_new_old + QSCALE + 2 ), 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 ); + // fixedToFloat_arrL( &band_energies_LR_fx[0], &band_energies_LR[0], Q_new + QSCALE - band_ener_guardbits, 40 ); +#if 0 + noise_est_pre( Etot_LR[n], hFrontVads[0]->ini_frame, hFrontVad->hNoiseEst, 0, 0, 0 ); +#else + // Word32 Etot_fx = (Word32) ( Etot_LR[n] * ( 1 << 24 ) ); + Word32 Etot_fx = L_deposit_h( Etot_LR_fx[n] ); + /* hFrontVad->hNoiseEst->Etot_h_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_h * 16777216.0 ); + hFrontVad->hNoiseEst->Etot_l_32fx = (Word32) ( hFrontVad->hNoiseEst->Etot_l * 16777216.0 ); + 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 );*/ + + noise_est_pre_32fx( Etot_fx, hFrontVads[0]->ini_frame, hFrontVad->hNoiseEst, 0, 0, 0 ); + + /* hFrontVad->hNoiseEst->Etot_h = (float) ( hFrontVad->hNoiseEst->Etot_h_32fx / 16777216.0 ); + hFrontVad->hNoiseEst->Etot_l = (float) ( hFrontVad->hNoiseEst->Etot_l_32fx / 16777216.0 ); + 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_32fx / 16777216.0 ); + // hFrontVad->hNoiseEst->sign_dyn_lp = (float) ( hFrontVad->hNoiseEst->sign_dyn_lp_32fx / 16777216.0 ); +#endif + /* wb_vad */ +#if 0 + hFrontVad->hVAD->vad_flag = wb_vad( sts[n], fr_bands[n], &dummy, &dummy, &dummy, &snr_sum_he, &localVAD_HE_SAD[n], &dummy, hFrontVad->hVAD, hFrontVad->hNoiseEst, hFrontVad->lp_speech, hFrontVad->lp_noise ); +#else + // floatToFixed_arrL( fr_bands[n], fr_bands_fx[n], Q_new + QSCALE, 40 ); + for ( int i = 0; i < 40; i++ ) + { + fr_bands_cp_fx[i] = L_shr_sat( fr_bands_fx[n][i], 2 ); + } + // Scale_sig32( fr_bands_fx[n], -2, 40 ); + Scale_sig32( hFrontVads[n]->hNoiseEst->bckr_fx, Q_new + QSCALE - ( ( Q_inp - 1 ) + 3 + QSCALE ), 20 ); + Scale_sig32( hFrontVads[n]->hNoiseEst->enrO_fx, Q_new + QSCALE - ( ( Q_inp - 1 ) + 3 + QSCALE ), 20 ); + /* hFrontVad->lp_noise_fx = (Word16) floatToFixed( hFrontVad->lp_noise, Q8 ); + hFrontVad->lp_speech_fx = (Word16) floatToFixed( hFrontVad->lp_speech, Q8 ); + sts[n]->lp_speech_fx = (Word16) floatToFixed( sts[n]->lp_speech, Q8 ); + sts[n]->lp_noise_fx = (Word16) floatToFixed( sts[n]->lp_noise, Q8 ); + floatToFixed_arrL( hFrontVad->hNoiseEst->bckr, hFrontVad->hNoiseEst->bckr_fx, Q_new + QSCALE, 20 ); + floatToFixed_arrL( hFrontVad->hNoiseEst->enrO, hFrontVad->hNoiseEst->enrO_fx, Q_new + QSCALE, 20 ); + sts[n]->flag_noisy_speech_snr_fx = (Word8) sts[n]->flag_noisy_speech_snr; + hFrontVad->hVAD->bcg_flux_fx = (Word16) hFrontVad->hVAD->bcg_flux * ( 1 << 4 ); + hFrontVad->hNoiseEst->Etot_v_h2_fx = (Word16) ( hFrontVad->hNoiseEst->Etot_v_h2 * ( 1 << 8 ) ); + hFrontVad->hNoiseEst->sign_dyn_lp_fx = (Word16) ( hFrontVad->hNoiseEst->sign_dyn_lp * ( 1 << 8 ) ); + hFrontVad->hVAD->snr_sum_vad_fx = (Word16) ( hFrontVad->hVAD->snr_sum_vad * 32767 ); + hFrontVad->hVAD->prim_act_quick_fx = (Word16) ( hFrontVad->hVAD->prim_act_quick * 32767 ); + hFrontVad->hVAD->prim_act_slow_fx = (Word16) ( hFrontVad->hVAD->prim_act_slow * 32767 ); + hFrontVad->hVAD->prim_act_fx = (Word16) ( hFrontVad->hVAD->prim_act * 32767 ); + hFrontVad->hVAD->prim_act_quick_he_fx = (Word16) ( hFrontVad->hVAD->prim_act_quick_he * 32767 ); + hFrontVad->hVAD->prim_act_slow_he_fx = (Word16) ( hFrontVad->hVAD->prim_act_slow_he * 32767 ); + hFrontVad->hVAD->prim_act_he_fx = (Word16) ( hFrontVad->hVAD->prim_act_he * 32767 );*/ + 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_cp_fx, &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 ); + // snr_sum_he = (float)(snr_sum_he_fx / ONE_IN_Q8 ); + /* 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 ) ); + hFrontVad->hVAD->bcg_flux = (float) ( hFrontVad->hVAD->bcg_flux_fx / ( 16.0 ) ); + hFrontVad->hVAD->snr_sum_vad = (float) ( hFrontVad->hVAD->snr_sum_vad_fx / 32767.0 ); + hFrontVad->hVAD->prim_act_quick = (float) ( hFrontVad->hVAD->prim_act_quick_fx / 32767.0 ); + hFrontVad->hVAD->prim_act_slow = (float) ( hFrontVad->hVAD->prim_act_slow_fx / 32767.0 ); + hFrontVad->hVAD->prim_act = (float) ( hFrontVad->hVAD->prim_act_fx / 32767.0 ); + hFrontVad->hVAD->prim_act_quick_he = (float) ( hFrontVad->hVAD->prim_act_quick_he_fx / 32767.0 ); + hFrontVad->hVAD->prim_act_slow_he = (float) ( hFrontVad->hVAD->prim_act_slow_he_fx / 32767.0 ); + hFrontVad->hVAD->prim_act_he = (float) ( hFrontVad->hVAD->prim_act_he_fx / 32767.0 );*/ +#endif + if ( n == 0 && n_chan > 1 && last_element_mode == IVAS_CPE_DFT ) + { + sts[1]->last_coder_type = sts[0]->last_coder_type; + } +#if 0 + /* DTX hangover addition */ + vad_flag_dtx[n] = dtx_hangover_addition( sts[n], hFrontVad->hVAD->vad_flag, hFrontVad->lp_speech - hFrontVad->lp_noise, 0 /* <- no cldfb addition */, &vad_hover_flag[n], hFrontVad->hVAD, hFrontVad->hNoiseEst, &hFrontVads[n]->rem_dtx_ho ); +#else + 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 ); + +#endif + if ( n_chan == 1 ) + { + sts[n]->vad_flag = hFrontVad->hVAD->vad_flag; + } + } + for ( n = 0; n < n_chan; n++ ) + { + fixedToFloat_arr( hFrontVads[n]->mem_decim_fx, hFrontVads[n]->mem_decim, Q_inp, 90 ); + hFrontVads[n]->mem_preemph = fixedToFloat( hFrontVads[n]->mem_preemph_fx, Q_inp + Q_band[n] ); + fixedToFloat_arr( hFrontVads[n]->buffer_12k8_fx, hFrontVads[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 - 2, 148 ); + if ( lgBin_E_fx != NULL ) + { + fixedToFloat_arr( lgBin_E_fx, Bin_E, Q7, 128 ); + } + fixedToFloat_arrL( PS_fx, PS, Q_new + QSCALE, 128 ); + Etot_LR[n] = fixedToFloat( Etot_LR_fx[n], Q8 ); + + hFrontVads[n]->hNoiseEst->Etot_h = (float) ( hFrontVads[n]->hNoiseEst->Etot_h_32fx / 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_l = (float) ( hFrontVads[n]->hNoiseEst->Etot_l_32fx / 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_l_lp = (float) ( hFrontVads[n]->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_last = (float) ( hFrontVads[n]->hNoiseEst->Etot_last_32fx / 16777216.0 ); + // hFrontVads[n]->hNoiseEst->Etot_v_h2 = (float) ( hFrontVads[n]->hNoiseEst->Etot_v_h2_32fx / 16777216.0 ); + hFrontVads[n]->hNoiseEst->Etot_lp = (float) ( hFrontVads[n]->hNoiseEst->Etot_lp_32fx / 16777216.0 ); + // hFrontVads[n]->hNoiseEst->sign_dyn_lp = (float) ( hFrontVads[n]->hNoiseEst->sign_dyn_lp_32fx / 16777216.0 ); + + hFrontVads[n]->hNoiseEst->Etot_v_h2 = (float) ( hFrontVads[n]->hNoiseEst->Etot_v_h2_fx / ( 256.0 ) ); + hFrontVads[n]->hNoiseEst->sign_dyn_lp = (float) ( hFrontVads[n]->hNoiseEst->sign_dyn_lp_fx / ( 256.0 ) ); + hFrontVads[n]->hVAD->bcg_flux = (float) ( hFrontVads[n]->hVAD->bcg_flux_fx / ( 16.0 ) ); + hFrontVads[n]->hVAD->snr_sum_vad = (float) ( hFrontVads[n]->hVAD->snr_sum_vad_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act_quick = (float) ( hFrontVads[n]->hVAD->prim_act_quick_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act_slow = (float) ( hFrontVads[n]->hVAD->prim_act_slow_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act = (float) ( hFrontVads[n]->hVAD->prim_act_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act_quick_he = (float) ( hFrontVads[n]->hVAD->prim_act_quick_he_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act_slow_he = (float) ( hFrontVads[n]->hVAD->prim_act_slow_he_fx / 32767.0 ); + hFrontVads[n]->hVAD->prim_act_he = (float) ( hFrontVads[n]->hVAD->prim_act_he_fx / 32767.0 ); + // floatToFixed_arr( hFrontVads[n]->mem_decim, hFrontVads[n]->mem_decim_fx, Q_inp, 90 ); + // hFrontVads[n]->mem_preemph_fx = (Word16) floatToFixed( hFrontVads[n]->mem_preemph, Q_inp ); + } + fixedToFloat_arrL( band_energies_fx, band_energies, Q_new + QSCALE + 2, 40 ); + // fixedToFloat_arrL( &band_energies_LR_fx[0], &band_energies_LR[0], Q_new + QSCALE + 2 - band_ener_guardbits, 40 ); + if ( n_chan == CPE_CHANNELS ) + { + /* get average channel energies, adding up was already done, so only need to scale by number of channels */ +#if 0 + v_multc( &band_energies_LR[0], 0.5f, &band_energies_LR[0], 2 * NB_BANDS ); +#else + + v_multc_fixed( &band_energies_LR_fx[0], ONE_IN_Q30, &band_energies_LR_fx[0], 2 * NB_BANDS ); + +#endif + /* Logical OR between L and R decisions */ + vad_flag_dtx[0] = vad_flag_dtx[0] || vad_flag_dtx[1]; + } + fixedToFloat_arrL( &band_energies_LR_fx[0], &band_energies_LR[0], Q_new + QSCALE + 2 - band_ener_guardbits, 40 ); + if ( sts[0]->hFdCngEnc != NULL ) + { +#if 0 + resetFdCngEnc( sts[0] ); +#else + sts[0]->last_totalNoise_fx = (Word16) float_to_fix16( sts[0]->last_totalNoise, Q8 ); + sts[0]->hNoiseEst->totalNoise_fx = (Word16) float_to_fix16( sts[0]->hNoiseEst->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 ); + } + resetFdCngEnc_fx( sts[0] ); + sts[0]->last_totalNoise = fix16_to_float( sts[0]->last_totalNoise_fx, Q8 ); + sts[0]->hNoiseEst->totalNoise = fix16_to_float( sts[0]->hNoiseEst->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; + +#endif + } + + /* Part of DTX to decide if SID/NO_DATA */ + if ( vad_flag_dtx[0] == 0 && 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; + sts[1]->active_cnt = 0; + } + } + else + { + vad_flag_dtx[0] = 1; + } + } + else + { + vad_flag_dtx[0] = 1; + } + } + + if ( PS_out != NULL ) + { +#if 1 + mvr2r( PS, PS_out, L_FRAME / 2 ); +#else + mvr2r_Word32( PS_fx, PS_out_fx, L_FRAME / 2 ); + fixedToFloat_arrL( PS_out_fx, PS_out, Q_new + QSCALE, 128 ); +#endif + } + + if ( Bin_E_out != NULL ) + { + + mvr2r( Bin_E, Bin_E_out, L_FRAME ); + } + + pop_wmops(); + return error; +} + +#endif /*-----------------------------------------------------------------------------------------* * Function front_vad_create() @@ -270,6 +733,7 @@ ivas_error front_vad_create( 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 ); @@ -278,6 +742,14 @@ ivas_error front_vad_create( 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 = 23040; /* 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; +#endif hFrontVad->mem_preemph = 0; hFrontVad->ini_frame = 0; hFrontVad->hVAD->vad_flag = 1; @@ -395,7 +867,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 } }; @@ -412,19 +885,18 @@ ivas_error front_vad_spar( Word32 tmpN_fx[NB_BANDS] = { 0 }; Word32 tmpE_fx[NB_BANDS] = { 0 }; float corr_shift; - float dummy, res_energy; + // float res_energy; 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 +905,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 @@ -501,16 +971,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 +993,32 @@ 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 ); + floatToFixed_arr( st->input, st->input_fx, Q_inp, L_FRAME48k ); /*------------------------------------------------------------------* * 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 + if ( ( error = front_vad_fx( 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], Q_inp ) ) != IVAS_ERR_OK ) + { + return error; + } +#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 ); @@ -549,7 +1030,7 @@ ivas_error front_vad_spar( 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++ ) @@ -597,7 +1078,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 +1086,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 +1125,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 +1133,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, Q9, 368 ); + floatToFixed_arr( st->old_wsp2, st->old_wsp2_fx, Q9, 115 ); + floatToFixed_arr( st->mem_decim2, st->mem_decim2_fx, Q9, 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, Q9, 115 ); + fixedToFloat_arr( st->mem_decim2_fx, st->mem_decim2, Q9, 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 @@ -728,16 +1208,17 @@ ivas_error front_vad_spar( #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 ); @@ -749,19 +1230,44 @@ ivas_error front_vad_spar( 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->lt_tn_dist_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_tn_dist, Q8 ); + hFrontVad->hNoiseEst->lt_Ellp_dist_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->lt_Ellp_dist, Q8 ); + hFrontVad->hNoiseEst->sign_dyn_lp_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->sign_dyn_lp, Q8 ); 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->totalNoise_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->totalNoise, 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->hNoiseEst->Etot_st_est_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->Etot_st_est, Q8 ); + hFrontVad->hNoiseEst->Etot_sq_st_est_fx = (Word16) floatToFixed( hFrontVad->hNoiseEst->Etot_sq_st_est, Q2 ); 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, &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 ); + hFrontVad->hNoiseEst->noise_char = (float) fixedToFloat( hFrontVad->hNoiseEst->noise_char_fx, Q11 ); + 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 ); + hFrontVad->hNoiseEst->Etot_st_est = fixedToFloat( hFrontVad->hNoiseEst->Etot_st_est_fx, Q8 ); + hFrontVad->hNoiseEst->Etot_sq_st_est = fixedToFloat( hFrontVad->hNoiseEst->Etot_sq_st_est_fx, Q2 ); + hFrontVad->hNoiseEst->epsP_2_16_lp2 = fixedToFloat( hFrontVad->hNoiseEst->epsP_2_16_lp2_fx, Q12 ); + hFrontVad->hNoiseEst->epsP_2_16_lp = fixedToFloat( hFrontVad->hNoiseEst->epsP_2_16_lp_fx, Q12 ); + hFrontVad->hNoiseEst->epsP_2_16_dlp_lp2 = fixedToFloat( hFrontVad->hNoiseEst->epsP_2_16_dlp_lp2_fx, Q12 ); + hFrontVad->hNoiseEst->lt_tn_track = fixedToFloat( hFrontVad->hNoiseEst->lt_tn_track_fx, Q15 ); + hFrontVad->hNoiseEst->lt_tn_dist = fixedToFloat( hFrontVad->hNoiseEst->lt_tn_dist_fx, Q8 ); + hFrontVad->hNoiseEst->lt_Ellp_dist = fixedToFloat( hFrontVad->hNoiseEst->lt_Ellp_dist_fx, Q8 ); + hFrontVad->hNoiseEst->lt_haco_ev = fixedToFloat( hFrontVad->hNoiseEst->lt_haco_ev_fx, Q15 ); + hFrontVad->hNoiseEst->lt_aEn_zero = fixedToFloat( hFrontVad->hNoiseEst->lt_aEn_zero_fx, Q15 ); + + hFrontVad->hNoiseEst->act_pred = fixedToFloat( hFrontVad->hNoiseEst->act_pred_fx, Q15 ); + 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 ); @@ -791,10 +1297,10 @@ ivas_error front_vad_spar( #else SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; #if 1 - Word16 relE_fx; - Word16 lsp_new_fx[M]; + // Word16 relE_fx; + // Word16 lsp_new_fx[M]; Word32 PS_fx[128]; - Word32 epsP_fx[M + 1]; + // Word32 epsP_fx[M + 1]; cor_map_sum_fx = (Word16) floatToFixed( cor_map_sum, Q8 ); Word16 non_sta_fx = (Word16) floatToFixed( non_staX, Q8 ); // Word32 epsP_fx[M + 1]; @@ -808,7 +1314,7 @@ ivas_error front_vad_spar( hSpMusClas->relE_attack_sum_fx = (Word16) ( hSpMusClas->relE_attack_sum * ONE_IN_Q9 ); 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 ); diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index 992b49ac57fed8eb5f4b858300f1f36d78b352b3..eca4da63991dc193817b21f9ae89abf23ac75b78 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -496,7 +496,7 @@ ivas_error ivas_mct_enc( st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); if ( st->hTdCngEnc != NULL ) { - st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + 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 ); diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index 815db85b4b13e11f0923e000f2b63b66b4334be5..afba3cc1a18411c0dc5fa7707781d5e4e27096dc 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -876,7 +876,188 @@ static void kernel_switch_update_transforms( } #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, @@ -949,14 +1130,301 @@ 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( + 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) */ +) +{ + 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( LT_16( nSamplesMax, 512 ) ) + { + IF( LT_16( nSamplesMax, 256 ) ) + { + fadeInLen = 10; + } + ELSE + { + fadeInLen = 20; + } + } + ELSE + { + fadeInLen = 40; + } + + 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 */ @@ -1060,7 +1528,7 @@ static uint16_t enc_ste_pre_mdct( return ( corr > 0.75f ? 1 : 0 ); } - +#endif /*--------------------------------------------------------------* * enc_prm_igf_mdct() @@ -1157,6 +1625,9 @@ 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; @@ -1174,7 +1645,8 @@ 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 @@ -1216,6 +1688,13 @@ 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 */ @@ -1493,7 +1972,54 @@ void ivas_mdct_core_whitening_enc( 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 ) ); @@ -1501,12 +2027,38 @@ void ivas_mdct_core_whitening_enc( 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 @@ -1595,9 +2147,52 @@ void ivas_mdct_core_whitening_enc( } } } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + int k; - TNSAnalysisStereo( sts, mdst_spectrum, 0, tnsSize, tnsBits, param_core, mct_on ); + Word16 q_temp[2][2]; + TCX_ENC_HANDLE hTcxEnc = NULL; + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + q_com = L_get_q_buf1( st->hTcxEnc->spectrum[0], N_MAX ); + st->hTcxEnc->spectrum_e[0] = Q31 - ( q_com - 4 ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], ( Q31 - st->hTcxEnc->spectrum_e[0] ), N_MAX ); + + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + q_temp[ch][k] = L_get_q_buf1( mdst_spectrum[ch][k], 2 * st->hTcxCfg->tcx5SizeFB ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_temp[ch][k], 2 * st->hTcxCfg->tcx5SizeFB ); + } + + 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; + fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[0], st->hTcxEnc->spectrum[0], ( Q31 - st->hTcxEnc->spectrum_e[0] ), N_MAX ); + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( k = 0; k < nSubframes; k++ ) + { + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_temp[ch][k], 2 * st->hTcxCfg->tcx5SizeFB ); + } + 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 *---------------------------------------------------------------*/ @@ -1648,8 +2243,18 @@ void ivas_mdct_core_whitening_enc( { 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 */ @@ -1681,7 +2286,33 @@ void ivas_mdct_core_whitening_enc( 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 { @@ -1773,8 +2404,30 @@ void ivas_mdct_core_whitening_enc( { 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 } } @@ -1816,8 +2469,48 @@ void ivas_mdct_core_whitening_enc( } } } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + hTcxEnc = st->hTcxEnc; + q_com = L_get_q_buf1( st->hTcxEnc->spectrum[0], N_MAX ); + + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + st->hTcxEnc->spectrum_e[0] = Q31 - ( q_com - 4 ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], ( Q31 - st->hTcxEnc->spectrum_e[0] ), N_MAX ); + + for ( k = 0; k < nSubframes; k++ ) + { + q_temp[ch][k] = L_get_q_buf1( mdst_spectrum[ch][k], st->hTcxCfg->tcx5SizeFB ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_temp[ch][k], 2 * st->hTcxCfg->tcx5SizeFB ); + } + 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; + fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[0], st->hTcxEnc->spectrum[0], ( Q31 - st->hTcxEnc->spectrum_e[0] ), N_MAX ); + + nSubframes = ( hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( k = 0; k < nSubframes; k++ ) + { + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_temp[ch][k], 2 * st->hTcxCfg->tcx5SizeFB ); + } + 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++ ) { @@ -1843,7 +2536,31 @@ void ivas_mdct_core_whitening_enc( { 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 } } } @@ -2322,6 +3039,12 @@ void ivas_mdct_quant_coder_fx( nSubframes = NB_DIV; } move16(); + + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } + FOR( n = 0; n < nSubframes; n++ ) { temp_scale = getScaleFactor32( quantized_spectrum_fx[ch][n], L_spec[ch][n] ); @@ -2347,6 +3070,12 @@ void ivas_mdct_quant_coder_fx( nSubframes = NB_DIV; } move16(); + + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + continue; + } + 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 ) ); diff --git a/lib_enc/ivas_sns_enc.c b/lib_enc/ivas_sns_enc.c index e8113d90f3eb08dfb425dbcda194d11fdaf1d629..5419544c20573f898df401f6091a84890110fce8 100644 --- a/lib_enc/ivas_sns_enc.c +++ b/lib_enc/ivas_sns_enc.c @@ -806,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], @@ -913,8 +1160,8 @@ int16_t quantize_sns( Word16 weights_fx[24]; f2me_buf( snsQ, snsQ_fx, &sns_e, M ); - Scale_sig32( snsQ_fx, M, sns_e - s_max( 0, sns_e ) ); - sns_e = s_max( sns_e, 0 ); + 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] ); @@ -964,3 +1211,4 @@ int16_t quantize_sns( return nbits; } +#endif diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 01585ded06a168522115e27e450ac8a82cf4dec3..6ac31ad8cac58f5ea988982c158f31bc99f01fc4 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -1222,19 +1222,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; diff --git a/lib_enc/ivas_stereo_cng_enc.c b/lib_enc/ivas_stereo_cng_enc.c index 55247933e347cf31aa3362ec7eb1c0744d7868e6..84bbc55c223891668a93f6ae929dbd0243cda731 100644 --- a/lib_enc/ivas_stereo_cng_enc.c +++ b/lib_enc/ivas_stereo_cng_enc.c @@ -340,6 +340,173 @@ 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 ); +#ifndef IVAS_FLOAT_FIXED + hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->hConfig->band_res, min( STEREO_DFT_N_32k_ENC, NFFT_inner ), ENC ); +#else + 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(); +#endif + 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( 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 +622,7 @@ void stereo_dft_cng_side_gain( return; } - +#endif /*--------------------------------------------------------------- * stereo_enc_cng_init() @@ -473,8 +640,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 +666,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_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 643dfca8c591650dd3f5c25b5a519c1ff90014c1..2eccc298d90db1a17d6325fdda289dce83130a0c 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -1433,7 +1433,7 @@ void stereo_mdct_core_enc( st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); if ( st->hTdCngEnc != NULL ) { - st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + 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 ); diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 68f49408a3ab119929d3cea9add2f9e67441cb4a..721241fc36fe508fca69f87fa83df769c90fa03d 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -225,35 +225,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 */ - Word16 lsp_new_fx[M], lsp_mid_fx[M]; - // 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,8 +262,7 @@ void stereo_tcx_core_enc( Word16 bits_param_lpc[10], no_param_lpc; /*LPC*/ - float lsf[M]; - float lsf_tcx_q[M]; + Word16 lsp_fx[M]; Word16 lsp_q_fx[M], lsf_q_fx[M], lsf_fx[M]; Word16 lspmid_q_fx[M]; Word16 A_q_fx[M + 1]; @@ -296,6 +279,8 @@ void stereo_tcx_core_enc( /*HM*/ Word16 indexBuffer[2 * ( ( N_MAX / 2 ) + 1 )]; + Word16 s; + CONTEXT_HM_CONFIG hm_cfg[2]; /* bitstream */ @@ -320,31 +305,9 @@ void stereo_tcx_core_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word16 Q_new, Q_exc, q_comm_Bin; - Word16 lsp_fx[M]; - Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )]; - float Aw_flt[NB_SUBFR16k * ( M + 1 )] /*, max = 0*/; - - st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); - mvr2r( Aw, Aw_flt, st->nb_subfr * ( M + 1 ) ); - floatToFixed_arr( Aw_flt, Aw_fx, Q12, st->nb_subfr * ( M + 1 ) ); - st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); - - for ( int j = 0; j < 6; j++ ) - { - st->clip_var_fx[j] = (Word16) ( st->clip_var[j] * 2.56f ); - } - hTcxEnc->tcx_target_bits_fac = float_to_fix16( hTcxEnc->tcx_target_bits_fac_flt, Q14 ); - st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); - 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, Q12 ); - } - floatToFixed_arr( hTcxEnc->Txnq_flt, hTcxEnc->Txnq, -1, L_FRAME32k / 2 + 64 ); + Word16 lsp_new_fx[M], lsp_mid_fx[M]; #endif - /*--------------------------------------------------------------* * Configuration of TCX *---------------------------------------------------------------*/ @@ -404,14 +367,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); } } @@ -519,7 +481,6 @@ void stereo_tcx_core_enc( st->gamma = float_to_fix16( st->gamma_flt, Q15 ); floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); - floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); @@ -552,31 +513,25 @@ void stereo_tcx_core_enc( } Q_new = 0; - Q_exc = Q_new + ( Q_new - 1 ) + 1; st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); floatToFixed_arr( st->lsp_old16k, st->lsp_old16k_fx, Q15, M ); - IF( st->hTdCngEnc != NULL ) + 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 ) { - 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 ); } - IF( st->hDtxEnc != NULL ) + if ( st->hDtxEnc != NULL ) { floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); } floatToFixed_arr( st->synth_flt, st->synth, Q_new, st->L_frame ); floatToFixed_arr( st->hLPDmem->syn_flt, st->hLPDmem->syn, Q_new, M + 1 ); - // floatToFixed_arr( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, Q_new, L_EXC_MEM ); st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); - 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; #endif // IVAS_FLOAT_FIXED_CONVERSIONS IF( !st->enableTcxLpc ) @@ -602,21 +557,6 @@ void stereo_tcx_core_enc( Copy( lsf_q_fx, st->lsf_old_fx, M ); } } -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->streaklimit = fix16_to_float( st->streaklimit_fx, Q15 ); - fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); - fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); - fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); - for ( int j = 0; j < M; j++ ) - { - st->lsf_old[j] = (float) st->lsf_old_fx[j] / 2.56f; - st->lsf_adaptive_mean[j] = (float) st->lsf_adaptive_mean_fx[j] / 2.56f; - st->mem_MA[j] = (float) st->mem_MA_fx[j] / 2.56f; - st->mem_AR[j] = (float) st->mem_AR_fx[j] / 2.56f; - } - fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, q_comm_Bin, 128 ); - fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, q_comm_Bin, 256 ); -#endif last_core_orig = st->last_core; move16(); @@ -628,7 +568,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 ); @@ -640,23 +579,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; @@ -667,7 +591,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 ); @@ -741,77 +664,39 @@ void stereo_tcx_core_enc( } tmp2 = imult1616( n, NPRM_DIV ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - hTcxEnc->Q_old_out = Q_factor_arr( hTcxEnc->old_out, L_frame ) - 1; - floatToFixed_arr( hTcxEnc->old_out, hTcxEnc->old_out_fx, hTcxEnc->Q_old_out, L_frame ); -#endif - 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 ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( hTcxEnc->old_out_fx, hTcxEnc->old_out, hTcxEnc->Q_old_out, L_frame ); -#endif } /* Update tcx overlap mode */ st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; move16(); -#if 0 - Word16 s = sub( getScaleFactor16( st->synth, st->L_frame ), 2 ); + s = sub( getScaleFactor16( st->synth, st->L_frame ), 2 ); + s = s_min( s, getScaleFactor16( st->hLPDmem->syn, M ) ); + s = s_min( s, norm_s( st->wspeech_enc[st->L_frame - 1] ) ); Scale_sig( st->synth, st->L_frame, s ); - Q_exc = sub( 15, st->hLPDmem->e_old_exc ); - Scale_sig( st->hLPDmem->old_exc, L_EXC_MEM, sub( s, Q_exc ) ); Scale_sig( st->hLPDmem->syn, M + 1, s ); st->wspeech_enc[st->L_frame - 1] = shl( st->wspeech_enc[st->L_frame - 1], s ); Q_new = add( Q_new, s ); move16(); move16(); -#else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - float max = 0.0f; - fixedToFloat_arr( st->synth + tmp1, st->synth_flt + tmp1, 0, L_frame ); - for ( int k = 0; k < st->L_frame; k++ ) - { - if ( max < (float) fabs( st->synth_flt[k] ) ) - { - max = (float) fabs( st->synth_flt[k] ); - } - } - if ( max >= 32768.f ) - { - Q_new = -1; - } - else + + /* Scaling old_exc buffer to Q_new */ + IF( NE_16( Q_new, Q_exc ) ) { - Q_new = norm_s( (Word16) max ) - 2; + Scale_sig( st->hLPDmem->old_exc, L_EXC_MEM, sub( Q_new, Q_exc ) ); } - floatToFixed_arr( st->synth_flt, st->synth, Q_new, st->L_frame ); - floatToFixed_arr( st->hLPDmem->syn_flt, st->hLPDmem->syn, Q_new, M + 1 ); - floatToFixed_arr( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, Q_new, L_EXC_MEM ); - st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); -#endif -#endif coder_tcx_post_ivas_fx( st, st->hLPDmem, st->hTcxCfg, st->synth, A_q_fx, Aw_fx, st->wspeech_enc, Q_new ); -#if 0 - Q_exc = shl( Q_new, 1 ); // Q_new + ( Q_new - 1 ) + 1; - move16(); -#else - fixedToFloat_arr( st->hLPDmem->old_exc, st->hLPDmem->old_exc_flt, Q_new + ( Q_new - 1 ) + 1, L_EXC_MEM ); - f2me_buf_16( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, &exp_exc, L_EXC_MEM ); - Q_exc = 15 - exp_exc; + /* 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 ) { - 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 ); + 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 IF( st->enableTcxLpc ) { @@ -922,13 +807,52 @@ 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 ); + set16_fx( pitch_buf_fx, L_SUBFR * ONE_IN_Q6, NB_SUBFR16k ); } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Fixed to float + IF( st->hTdCngEnc != NULL ) + { + fixedToFloat_arr( st->hTdCngEnc->cng_exc2_buf, st->hTdCngEnc->cng_exc2_buf_flt, Q_exc, HO_HIST_SIZE * L_FFT ); + } + + 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; @@ -1300,60 +1224,11 @@ void stereo_tcx_core_enc( { set_f( pitch_buf, L_SUBFR, 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 ); - } - - hTcxEnc->measuredBwRatio_flt = fix16_to_float( hTcxEnc->measuredBwRatio, Q14 ); - - fixedToFloat_arr( st->synth, st->synth_flt, Q_new, st->L_frame ); - fixedToFloat_arr( st->hLPDmem->mem_syn_r, st->hLPDmem->mem_syn_r_flt, Q_new + ( Q_new - 1 ), L_SYN_MEM ); - fixedToFloat_arr( st->hLPDmem->mem_syn, st->hLPDmem->mem_syn_flt, Q_new + ( Q_new - 1 ), M ); - fixedToFloat_arr( st->hLPDmem->mem_syn2, st->hLPDmem->mem_syn2_flt, Q_new + ( Q_new - 1 ), M ); - fixedToFloat_arr( st->hLPDmem->syn, st->hLPDmem->syn_flt, Q_new, M + 1 ); - fixedToFloat_arr( st->hLPDmem->old_exc, st->hLPDmem->old_exc_flt, Q_exc, L_EXC_MEM ); - st->hLPDmem->mem_w0_flt = fixedToFloat_16( st->hLPDmem->mem_w0, Q_new ); - - st->streaklimit = fix16_to_float( st->streaklimit_fx, Q15 ); - fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); - for ( int j = 0; j < 6; j++ ) - { - st->clip_var[j] = (float) st->clip_var_fx[j] / 2.56f; - } - for ( int j = 0; j < M; j++ ) - { - st->lsf_old[j] = (float) st->lsf_old_fx[j] / 2.56f; - st->mem_MA[j] = (float) st->mem_MA_fx[j] / 2.56f; - } - if ( st->enablePlcWaveadjust ) - { - st->hTcxCfg->SFM2_flt = fix_to_float( st->hTcxCfg->SFM2, Q31 ); - } - for ( n = 0; n < n_subframes; n++ ) - { - fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], 31 - st->hTcxEnc->spectrum_e[n], s_max( L_frame, L_spec ) ); - } - fixedToFloat_arr( hTcxEnc->Txnq, hTcxEnc->Txnq_flt, -1, L_FRAME32k / 2 + 64 ); - st->hTcxEnc->noiseTiltFactor_flt = fix16_to_float( st->hTcxEnc->noiseTiltFactor, Q15 ); - hTcxEnc->tcx_target_bits_fac_flt = me2f_16( hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); -#endif pop_wmops(); return; } +#endif /*-------------------------------------------------------------------* diff --git a/lib_enc/lsf_enc_fx.c b/lib_enc/lsf_enc_fx.c index 03579f6a8bb239e6bb9d073f2f7b6f582bc90958..c2635ec428e89b5cecd510057b7cd33333a5b901 100644 --- a/lib_enc/lsf_enc_fx.c +++ b/lib_enc/lsf_enc_fx.c @@ -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 ) ) { @@ -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(); } } @@ -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 2b57ba975b9e8709d412c20d4bfd41ce87d8ea4c..9c277ca20b362398615028aa55196f992e204a35 100644 --- a/lib_enc/lsf_msvq_ma_enc.c +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -1028,7 +1028,7 @@ void msvq_enc_ivas_fx( /* Set up inital error (residual) vectors */ pTmp = resid_fx[1]; /*move16();*/ - resid_e = add( u_e, 1 ); + resid_e = u_e; move16(); IF( applyDCT_flag != 0 ) { @@ -1042,10 +1042,6 @@ void msvq_enc_ivas_fx( { scale_sig32( pTmp + c * N, N, sub( u_e, resid_e ) ); } - ELSE - { - scale_sig32( pTmp + c * N, N, -1 ); - } dist_fx[1][c] = ss2; move32(); dist_e[1][c] = tmp_e; @@ -1295,7 +1291,7 @@ excludes the waveform contributions at pos 21,22,23 to the MSE, important to kee test(); IF( s == 0 && applyDCT_flag != 0 && n == FDCNG_VQ_MAX_LEN_WB ) { - p_max = msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( st1_syn_vec_ptr_fx, 11, u_fx, u_e, maxC, dist_fx[1], &dist_e[1][0] ); + p_max = msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( st1_syn_vec_ptr_fx, resid_e, u_fx, u_e, maxC, dist_fx[1], &dist_e[1][0] ); set16_fx( dist_e[1], dist_e[1][0], maxC ); } m = maxC; diff --git a/lib_enc/nois_est_fx.c b/lib_enc/nois_est_fx.c index dbb29cc6c27df3c6cee8a3a85e790040fc03315d..8b4c2b99af7f16154b4dc92b8cdb2b33aae990a3 100644 --- a/lib_enc/nois_est_fx.c +++ b/lib_enc/nois_est_fx.c @@ -2096,6 +2096,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 +2221,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(); } } /*-----------------------------------------------------------------* @@ -2423,8 +2425,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 +2560,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 +2570,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 +2895,7 @@ void noise_est_ivas_fx( /*-----------------------------------------------------------------* * Stereo classifier - save raw aEn *-----------------------------------------------------------------*/ - - if ( hStereoClassif != NULL ) + IF( hStereoClassif != NULL ) { /* if ( ( non_sta > th_sta ) || @@ -2903,21 +2903,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 +2930,7 @@ void noise_est_ivas_fx( { hStereoClassif->aEn_raw[st_fx->idchan] = 0; } + move16(); } @@ -3358,16 +3364,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/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index cf502f30795b0270b4f60768cf7f820ca5b2b0eb..2f889cf0c3147de800a7d0e842843b8004353736 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -166,7 +166,17 @@ 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 */ @@ -1083,6 +1093,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 */ @@ -1406,6 +1432,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. @@ -1566,6 +1599,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, @@ -1852,7 +1900,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[], @@ -2571,6 +2640,13 @@ 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 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 */ @@ -4064,4 +4140,5 @@ Word16 cng_energy_ivas_fx( const Word16 len, /* i : vector length */ const Word16 Q_new /* i : Input scaling */ ); + #endif diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 21abcc4d1713907a1abcde8f8667e9c577fbc8af..483c73e384111c50a426d6d89423837441a7814d 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 */ @@ -418,18 +417,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; @@ -493,7 +492,7 @@ typedef struct td_cng_enc_structure int16_t shb_cng_ini_cnt; int16_t last_SID_bwidth; int16_t shb_NO_DATA_cnt; - Word16 CNG_att_fx; + Word16 CNG_att_fx; /* Q7 */ } TD_CNG_ENC_DATA, *TD_CNG_ENC_HANDLE; @@ -1100,7 +1099,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 */ @@ -1896,7 +1894,6 @@ 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; diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index 45ef64e1e344a815df2b0a6fb399c199f5fbf14b..7a6cb1ad9ebf415f65f11c06c28f729169619700 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1625,6 +1625,116 @@ void ProcessIGF_ivas_fx( #endif } #endif + + +#ifdef IVAS_FLOAT_FIXED +/*---------------------------------------------------------------------* + * ProcessIGF_ivas_fx() + * + * + *---------------------------------------------------------------------*/ +void ProcessIGF_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + Word32 *pMDCTSpectrum, /* i : MDCT spectrum (*q_spectrum) */ + const Word32 *pITFMDCTSpectrum, /* i : MDCT spectrum fir ITF (*q_spectrum) */ + 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, 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( st->last_core == ACELP_CORE && isTCX20 ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + 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 ) ) + { + isIndepFlag = 0; + move16(); + } + } + + IGFSaveSpectrumForITF_ivas_fx( hIGFEnc, igfGridIdx, pITFMDCTSpectrum ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + float pMDCTSpectrum_flt[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + float pPowerSpectrum_flt[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + fixedToFloat_arrL32( pMDCTSpectrum, pMDCTSpectrum_flt, *q_spectrum, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( pPowerSpectrum, pPowerSpectrum_flt, *q_powerSpec, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); +#endif + IGFEncApplyMono( st, igfGridIdx, pMDCTSpectrum_flt, pPowerSpectrum_flt, isTCX20, st->hTcxEnc->fUseTns[frameno], sp_aud_decision0, vad_hover_flag ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arrL32( pMDCTSpectrum_flt, pMDCTSpectrum, *q_spectrum, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( pPowerSpectrum_flt, pPowerSpectrum, *q_powerSpec, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); +#endif + + curr_order = 0; + move16(); + predictionGain = 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 */ ) ) + { + hIGFEnc->flatteningTrigger = 1; + move16(); + } + ELSE + { + hIGFEnc->flatteningTrigger = 0; + move16(); + } + + hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + + IF( isTCX20 ) + { + IGFEncWriteBitstream_ivas_fx( hIGFEnc, NULL, &hIGFEnc->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + } + ELSE + { + pBsStart = hBstr->nb_ind_tot; + move16(); + + IGFEncWriteBitstream_ivas_fx( hIGFEnc, hBstr, &hIGFEnc->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + + bsBits = sub( hBstr->nb_ind_tot, pBsStart ); + IGFEncConcatenateBitstream_ivas_fx( hIGFEnc, bsBits, hBstr ); + } + + return; +} +#endif + + void ProcessIGF( Encoder_State *st, /* i : Encoder state */ float *pMDCTSpectrum, /* i : MDCT spectrum */ 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/vad_fx.c b/lib_enc/vad_fx.c index d0356f518e67567e254099f52c41e7fad7ee3de4..46cf0e1aa94fff32979613068def04b6531d5725 100644 --- a/lib_enc/vad_fx.c +++ b/lib_enc/vad_fx.c @@ -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() *