From 0c287810b746e3656af22df2ec81ca12467be2b1 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Thu, 12 Sep 2024 18:46:07 +0530 Subject: [PATCH] Core coder and stereo DFT functions conversion/integration [x] Use EVS version of GetTCXAvgTemporalFlatnessMeasure function with SUBBLOCK_NRG_CHANGE_E as exponent [x] hq_hr_enc() conversion - some sub functions converted [x] TNSAnalysis_ivas_fx function added [x] stereo_tcx_core_enc: Lsf and Lsp related functions integrated [x] stereo dft enc functions conversion --- lib_com/cnst.h | 3 + lib_com/hq_bit_allocation_fx.c | 1 - lib_com/interleave_spectrum.c | 85 ++ lib_com/ivas_prot.h | 8 + lib_com/ivas_prot_fx.h | 9 + lib_com/logqnorm_fx.c | 124 ++- lib_com/prot.h | 5 +- lib_com/prot_fx.h | 50 +- lib_com/rom_com.c | 69 +- lib_com/rom_com.h | 3 + lib_com/stat_com.h | 1 + lib_com/tcx_utils_fx.c | 17 + lib_com/tns_base.c | 136 ++++ lib_com/tools.c | 19 + lib_enc/acelp_core_enc.c | 2 +- lib_enc/cng_enc_fx.c | 1 - lib_enc/cod_tcx_fx.c | 86 +++ lib_enc/ext_sig_ana.c | 45 +- lib_enc/hq_classifier_enc.c | 23 +- lib_enc/hq_classifier_enc_fx.c | 785 ++++++++++++++++++- lib_enc/hq_core_enc.c | 4 + lib_enc/hq_env_enc_fx.c | 3 +- lib_enc/hq_hr_enc.c | 118 ++- lib_enc/ivas_cpe_enc.c | 181 +++-- lib_enc/ivas_mdct_core_enc.c | 3 +- lib_enc/ivas_rom_enc.c | 21 + lib_enc/ivas_rom_enc.h | 6 + lib_enc/ivas_stat_enc.h | 49 +- lib_enc/ivas_stereo_classifier.c | 179 ++++- lib_enc/ivas_stereo_dft_enc.c | 1203 ++++++++++++++++++++++------- lib_enc/ivas_stereo_dft_enc_itd.c | 2 +- lib_enc/ivas_tcx_core_enc.c | 224 +++--- lib_enc/prot_fx_enc.h | 87 ++- lib_enc/stat_enc.h | 16 +- lib_enc/tns_base_enc_fx.c | 288 +++++++ lib_enc/transient_detection_fx.c | 136 ++-- 36 files changed, 3349 insertions(+), 643 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index e7c27f942..bbedf69d6 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -2251,8 +2251,11 @@ typedef enum _DCTTYPE #define HVQ_NSUB_24k 7 /* HVQ Classifier number of subbands */ #define HQ_CREST_THRESHOLD 7.0f /* HQ harmonic high band classifier, crest threshold */ +#define HQ_CREST_THRESHOLD_FX 1879048192 //7.0f in Q28 /* HQ harmonic high band classifier, crest threshold */ #define HQ_CREST_MOD_THRESHOLD 2.128f /* HQ harmonic high band classifier, modified crest threshold */ +#define HQ_CREST_MOD_THRESHOLD_FX 1142461301 //2.128f in Q29 /* HQ harmonic high band classifier, modified crest threshold */ #define HQ_CREST_FAC_SM 0.97f /* HQ harmonic high band classifier, smoothing factor */ +#define HQ_CREST_FAC_SM_FX 2083059139 //0.97f in Q31 /* HQ harmonic high band classifier, smoothing factor */ #define HVQ_BWE_NOISE_BANDS 2 /* Number of BWE noise bands */ #define HVQ_BWE_WEIGHT1 0.95f diff --git a/lib_com/hq_bit_allocation_fx.c b/lib_com/hq_bit_allocation_fx.c index b78d2b374..e03fec40b 100644 --- a/lib_com/hq_bit_allocation_fx.c +++ b/lib_com/hq_bit_allocation_fx.c @@ -227,7 +227,6 @@ move16(); return; } - void hq_bit_allocation_fx( const Word32 core_brate, /* i : Core bit-rate Q0 */ const Word16 length, /* i : Frame length Q0 */ diff --git a/lib_com/interleave_spectrum.c b/lib_com/interleave_spectrum.c index 5ae7c421a..65b42e575 100644 --- a/lib_com/interleave_spectrum.c +++ b/lib_com/interleave_spectrum.c @@ -212,6 +212,91 @@ void interleave_spectrum_fx( return; } + +void interleave_spectrum_ivas_fx( + Word32 *coefs, /* i/o: input and output coefficients Q12 */ + const Word16 length /* i : length of spectrum Q0 */ +) +{ + Word16 i, j, k; + Word32 *p1, *p2, *p3, *p4; + Word32 *p_out; + Word32 coefs_out[L_FRAME48k]; + Word16 sublen[3] = { 240, 160, 80 }; + move16(); + move16(); + move16(); + Word16 grps; + const Word16 *bw; + const Word16 *cnt; + + /* Common inits */ + p1 = coefs; + p_out = coefs_out; + + IF( EQ_16( length, L_SPEC48k ) ) + { + bw = intl_bw_48; + cnt = intl_cnt_48; + grps = N_INTL_GRP_48; + move16(); + p2 = p1 + sublen[0]; + p3 = p2 + sublen[0]; + p4 = p3 + sublen[0]; + } + ELSE IF( EQ_16( length, L_SPEC32k ) ) + { + bw = intl_bw_32; + cnt = intl_cnt_32; + grps = N_INTL_GRP_32; + move16(); + p2 = p1 + sublen[1]; + p3 = p2 + sublen[1]; + p4 = p3 + sublen[1]; + } + ELSE /* length == L_SPEC16k */ + { + bw = intl_bw_16; + cnt = intl_cnt_16; + grps = N_INTL_GRP_16; + move16(); + p2 = p1 + sublen[2]; + p3 = p2 + sublen[2]; + p4 = p3 + sublen[2]; + } + + FOR( i = 0; i < grps; i++ ) + { + FOR( j = 0; j < cnt[i]; j++ ) + { + FOR( k = 0; k < bw[i]; k++ ) + { + *p_out++ = *p1++; + move32(); + } + FOR( k = 0; k < bw[i]; k++ ) + { + *p_out++ = *p2++; + move32(); + } + FOR( k = 0; k < bw[i]; k++ ) + { + *p_out++ = *p3++; + move32(); + } + FOR( k = 0; k < bw[i]; k++ ) + { + *p_out++ = *p4++; + move32(); + } + } + } + + /* For FB the interleaved spectrum is 800 samples */ + Copy32( coefs_out, coefs, (Word16) ( p_out - coefs_out ) ); + + return; +} #endif /*--------------------------------------------------------------------------* diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index da6477a3d..90b569501 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -1760,12 +1760,14 @@ float stereo_dft_enc_synthesize( const int16_t L_frame /* i : frame length at internal Fs */ ); +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_process( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ const int16_t vad_hover_flag[], /* i : VAD hangover flags */ const int16_t input_frame /* i : input frame length */ ); +#endif void stereo_dft_enc_res( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ @@ -2640,9 +2642,15 @@ void stereo_classifier_features( const int16_t clas /* i : signal class */ ); +#ifdef IVAS_FLOAT_FIXED +void unclr_classifier_dft_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +); +#else void unclr_classifier_dft( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ); +#endif void unclr_classifier_td( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 850985440..68175df02 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -2692,3 +2692,12 @@ void rc_uni_enc_encode_bits( const UWord16 value, /* i : Value to encode */ 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 */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : input frame length */ +); +#endif diff --git a/lib_com/logqnorm_fx.c b/lib_com/logqnorm_fx.c index 8d542b6be..d47feb209 100644 --- a/lib_com/logqnorm_fx.c +++ b/lib_com/logqnorm_fx.c @@ -35,7 +35,7 @@ #include "prot_fx.h" /* Function prototypes */ #include "rom_com.h" /* Static table prototypes */ #include "cnst.h" /* Common constants */ - +#include /*--------------------------------------------------------------------------* * Local constants *--------------------------------------------------------------------------*/ @@ -47,7 +47,92 @@ * * Log quantization for norms of sub-vectors *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void logqnorm_ivas_fx( + const Word32 *x_fx, /* i : coefficient vector */ + const Word16 q, /* i : q of coefficient vector */ + Word16 *k_fx, /* o : index (Q0)*/ + const Word16 L, /* i : codebook length */ + const Word16 N, /* i : sub-vector size */ + const Word32 *thre_fxn /* i : quantization thresholds */ +) +{ + Word16 i, j, j1, j2; + Word64 temp_fx; + Word32 temp32_fx; + Word32 power_fx; + Word64 thren0_sqr, threnL2_sqr; + Word32 thren0_sqr32, threnL2_sqr32; + Word16 thren0_sqr32_e, threnL2_sqr32_e; + temp_fx = 0; + move64(); + Word32 result1, result2; + Word16 result1_e, result2_e; + Word16 gd_bits = find_guarded_bits_fx( N ); + FOR( i = 0; i < N; i++ ) + { + temp_fx = W_add( W_shr( W_mult0_32_32( x_fx[i], x_fx[i] ), gd_bits ), temp_fx ); // 2*qin-gd_bits + } + Word16 l_shift = W_norm( temp_fx ); + temp32_fx = W_extract_h( W_shl( temp_fx, l_shift ) ); // 2*qin-gd_bits + l_shift -32 + Word16 temp_e = sub( 31, ( sub( add( sub( shl( q, 1 ), gd_bits ), l_shift ), 32 ) ) ); + /* sqrt will be done later */ + // temp *= inv_tbl[N]; + temp32_fx = Mpy_32_16_1( temp32_fx, inv_tbl_fx[N] ); // temp_e + thren0_sqr = W_mult0_32_32( thre_fxn[0], thre_fxn[0] ); // Q28 + threnL2_sqr = W_mult0_32_32( thre_fxn[L - 2], thre_fxn[L - 2] ); // Q28 + l_shift = W_norm( thren0_sqr ); + thren0_sqr32 = W_extract_h( W_shl( thren0_sqr, l_shift ) ); + thren0_sqr32_e = sub( 31, sub( add( Q28, l_shift ), 32 ) ); + l_shift = W_norm( threnL2_sqr ); + threnL2_sqr32 = W_extract_h( W_shl( threnL2_sqr, l_shift ) ); + threnL2_sqr32_e = sub( 31, sub( add( Q28, l_shift ), 32 ) ); + result1 = BASOP_Util_Add_Mant32Exp( thren0_sqr32, thren0_sqr32_e, L_negate( temp32_fx ), temp_e, &result1_e ); + result2 = BASOP_Util_Add_Mant32Exp( threnL2_sqr32, threnL2_sqr32_e, L_negate( temp32_fx ), temp_e, &result2_e ); + IF( result1 <= 0 ) + { + *k_fx = 0; + move16(); + } + ELSE IF( result2 > 0 ) + { + *k_fx = L - 1; + move16(); + } + ELSE + { + Word16 e = 0; + move16(); + power_fx = Sqrt32( ONE_IN_Q31, &e ); + power_fx = Sqrt32( temp32_fx, &temp_e ); + // power_fx = L_shr( power_fx , Q14-(31-temp_e)); + j1 = 0; + move16(); + j2 = L - 1; + move16(); + WHILE( GT_16( sub( j2, j1 ), 1 ) ) + { + j = shr( add( j1, j2 ), 1 ); + Word16 flag = BASOP_Util_Cmp_Mant32Exp( power_fx, temp_e, thre_fxn[j], Q31 - Q14 ); + IF( flag >= 0 ) + { + j2 = j; + move16(); + } + ELSE + { + j1 = j; + move16(); + } + } + + *k_fx = j2; + move16(); + } + return; +} +#endif void logqnorm_fx( const Word32 *L_x, /* i : coefficient vector Qx */ const Word16 qx, /* i : Q value of input */ @@ -193,7 +278,44 @@ void logqnorm_2_fx( * * Calculate the norms for the spectral envelope *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void calc_norm_ivas_fx( + const Word32 *x_fx, /* i : Input vector.(Qin) */ + Word16 *norm, /* o : Quantization indices for norms Q0 */ + Word16 *normlg, /* o : Quantized norms in log2 Q0 */ + const Word16 start_band, /* i : Indice of band to start coding */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_len, /* i : Length of bands */ + const Word16 *band_start /* i : Start of bands */ +) +{ + Word16 nrm; + Word16 band; + Word16 tmp; + + set16_fx( norm, 0, start_band ); + + // logqnorm_ivas_fx( &x_fx[band_start[start_band]], 12, &x[band_start[start_band]], &nrm, 32, band_len[start_band], thren_HQ ); + logqnorm_ivas_fx( &x_fx[band_start[start_band]], 12, &nrm, 32, band_len[start_band], thren_HQ_fx ); + norm[start_band] = nrm; + move16(); + normlg[start_band] = dicnlg2[nrm]; + move16(); + + tmp = add( start_band, num_bands ); + FOR( band = add( start_band, 1 ); band < tmp; band++ ) + { + logqnorm_ivas_fx( &x_fx[band_start[band]], 12, &nrm, 40, band_len[band], thren_HQ_fx ); + norm[band] = nrm; + move16(); + normlg[band] = dicnlg2[nrm]; + move16(); + } + + return; +} +#endif void calc_norm_fx( const Word32 *L_x, /* i : Input vector. Qx */ const Word16 qx, /* i : Q value of input */ diff --git a/lib_com/prot.h b/lib_com/prot.h index 13606feb2..df837c21f 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -1782,7 +1782,7 @@ int16_t hvq_enc( const float *coefs, /* i : spectrum coefficients */ float *coefs_out /* o : encoded spectrum coefficients */ ); - +#ifndef IVAS_FLOAT_FIXED /*! r: Consumed bits */ int16_t hq_classifier_enc( Encoder_State *st, /* i/o: encoder state structure */ @@ -1795,7 +1795,7 @@ int16_t hq_classifier_enc( float *nf_gains, /* o : Noise-fill gains */ int16_t *hqswb_clas /* o : HQ class */ ); - +#endif /*! r: Consumed bits */ int16_t hq_classifier_dec( Decoder_State *st, /* i/o: decoder state structure */ @@ -5384,7 +5384,6 @@ void hq_hr_enc( const int16_t is_transient, /* i : transient flag */ const int16_t vad_hover_flag /* i : VAD hangover flag */ ); - void logqnorm( const float *x, /* i : coefficient vector */ int16_t *k, /* o : index */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index f5c8fba0e..0e05b8ced 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -125,7 +125,10 @@ Word16 L_get_q_buf1( float *ptr_flt, Word16 length ); /*================================================================================*/ /* conversion functions: */ /*================================================================================*/ - +Word32 sum_l_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec /* i : length of input vector */ +); Word16 norm_ul( UWord32 UL_var1 ); Word32 Mult_32_16( @@ -464,7 +467,25 @@ void calc_norm_fx( const Word16 *band_len, /* i : Length of bands Q0 */ const Word16 *band_start /* i : Start of bands Q0 */ ); - +#ifdef IVAS_FLOAT_FIXED +void calc_norm_ivas_fx( + const Word32 *x_fx, /* i : Input vector. */ + Word16 *norm, /* o : Quantization indices for norms */ + Word16 *normlg, /* o : Quantized norms in log2 */ + const Word16 start_band, /* i : Indice of band to start coding */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_len, /* i : Length of bands */ + const Word16 *band_start /* i : Start of bands */ +); +void logqnorm_ivas_fx( + const Word32 *x_fx, /* i : coefficient vector */ + const Word16 q, /* i : q of coefficient vector */ + Word16 *k_fx, /* o : index */ + const Word16 L, /* i : codebook length */ + const Word16 N, /* i : sub-vector size */ + const Word32 *thre_fxn /* i : quantization thresholds */ +); +#endif /*========================================================================================================/ hq_tools_fx.c /========================================================================================================*/ @@ -1530,7 +1551,12 @@ void interleave_spectrum_fx( const Word16 length /* i : length of spectrum Q0 */ ); // findpulse.c - +#ifdef IVAS_FLOAT_FIXED +void interleave_spectrum_ivas_fx( + Word32 *coefs, /* i/o: input and output coefficients Q12 */ + const Word16 length /* i : length of spectrum Q0 */ +); +#endif Word16 findpulse_fx( /* o : pulse position */ const Word16 L_frame, /* i : length of the frame */ const Word16 res[], /* i : Residual signal <12 bits */ @@ -3274,6 +3300,15 @@ void InitTnsConfiguration( const Word16 element_mode, const Word16 is_mct ); +void InitTnsConfiguration_ivas_fx( + const Word16 bwidth, + const Word16 frameLength, + STnsConfig *pTnsConfig, + const Word16 igfStopFreq, + const Word32 total_brate, + const Word16 element_mode, + const Word16 is_mct ); + /** Modify spectrum using TNS filter. * Modifies spectrum unsing TNS filter defined by pTnsData. * If fIsAnalyses is true considers spectrum to be @@ -3974,6 +4009,15 @@ void InitTnsConfigs( const Word16 element_mode, const Word16 is_mct ); +void InitTnsConfigs_ivas_fx( + const Word16 bwidth, + const Word16 L_frame, + STnsConfig tnsConfig[2][2], + const Word16 igfStopFreq, + const Word32 total_brate, + const Word16 element_mode, + const Word16 is_mct ); + #define IVAS_CODE_TCX_UTIL #ifdef IVAS_CODE_TCX_UTIL void SetAllowTnsOnWhite( diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index 838bbe9bd..a442ebd84 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -35032,7 +35032,50 @@ const Word16 swb_hr_env_code3_fx[NUM_ENVLOPE_CODE_HR_TR*N_BANDS_TRANS_BWE_HR] = 2538, 5306, 3962, 4430, 4730, 3610, 5225, 2877, 5450, 2240, 5970, 1779, 5553, 1364, 6003, 838 }; - +#ifdef IVAS_FLOAT_FIXED +const Word32 thren_HQ_fx[39] = +{//Q14 + 1805811328, + 1276901376, + 902905664, + 638450688, + 451452832, + 319225344, + 225726416, + 159612672, + 112863208, + 79806336, + 56431604, + 39903168, + 28215802, + 19951584, + 14107901, + 9975792, + 7053950, + 4987896, + 3526975, + 2493948, + 1763487, + 1246974, + 881743, + 623487, + 440871, + 311743, + 220435, + 155871, + 110217, + 77935, + 55108, + 38967, + 27554, + 19483, + 13777, + 9741, + 6888, + 4870, + 3444, +}; +#endif /* Searching thresholds for quantization of norms */ const float thren_HQ[39] = { @@ -36737,42 +36780,42 @@ const Word16 qGains[2][1 << kTcxHmNumGainBits] = const struct TnsParameters tnsParametersIGF32kHz_LowBR[1] = { - { 600, 3, 1.85f, 0.075f, 4.4f, 237/*1.85f Q7*/, 2458/*0.075f Q15*/ } + { 600, 3, 1.85f, 0.075f, 4.4f, 237/*1.85f Q7*/, 2458/*0.075f Q15*/,563 /*4.4f Q7*/ } }; const struct TnsParameters tnsParameters32kHz[2] = { - { 4500, 3, 1.35f, 0.0300f, 1.0f ,173/*1.35f Q7*/, 983/*0.0300f Q15*/}, - { 600, 1, 1.75f, 0.0625f, 4.4f ,224/*1.75f Q7*/, 2048/*0.0625f Q15*/} + { 4500, 3, 1.35f, 0.0300f, 1.0f ,173/*1.35f Q7*/, 983/*0.0300f Q15*/, 128/*1.0f Q7*/}, + { 600, 1, 1.75f, 0.0625f, 4.4f ,224/*1.75f Q7*/, 2048/*0.0625f Q15*/, 563 /*4.4f Q7*/ } }; const struct TnsParameters tnsParameters32kHz_grouped[2] = { - { 8400, 3, 1.375f, 0.03125f, 1.0f , 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ }, - { 800, 3, 1.375f, 0.03125f, 1.0f , 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ } + { 8400, 3, 1.375f, 0.03125f, 1.0f , 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ , 128/*1.0f Q7*/ }, + { 800, 3, 1.375f, 0.03125f, 1.0f , 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ , 128/*1.0f Q7*/} }; const struct TnsParameters tnsParameters16kHz[1] = { - { 600, 3, 1.5f, 0.05f, 4.4f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ } + { 600, 3, 1.5f, 0.05f, 4.4f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ ,563 /*4.4f Q7*/ } }; const struct TnsParameters tnsParameters16kHz_grouped[2] = { - { 4400, 3, 1.5f, 0.05f, 1.0f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ }, - { 800, 3, 1.5f, 0.05f, 1.0f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ } + { 4400, 3, 1.5f, 0.05f, 1.0f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ , 128/*1.0f Q7*/}, + { 800, 3, 1.5f, 0.05f, 1.0f, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ , 128/*1.0f Q7*/} }; const struct TnsParameters tnsParameters48kHz_grouped[2] = { - { 10400, 3, 1.375f, 0.03125f, 1.0f, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ }, - { 800, 3, 1.375f, 0.03125f, 1.0f, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ } + { 10400, 3, 1.375f, 0.03125f, 1.0f, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ , 128/*1.0f Q7*/}, + { 800, 3, 1.375f, 0.03125f, 1.0f, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ , 128/*1.0f Q7*/ } }; const struct TnsParameters tnsParameters32kHz_Stereo[2]= { - { 4500, 3, 1.35f, 0.0300f, 1.0f ,173/*1.35f Q7*/, 983/*0.0300f Q15*/}, - { 600, 3, 1.75f, 0.0625f, 4.4f ,224/*1.75f Q7*/, 2048/*0.0625f Q15*/} + { 4500, 3, 1.35f, 0.0300f, 1.0f ,173/*1.35f Q7*/, 983/*0.0300f Q15*/ , 128/*1.0f Q7*/}, + { 600, 3, 1.75f, 0.0625f, 4.4f ,224/*1.75f Q7*/, 2048/*0.0625f Q15*/ ,563 /*4.4f Q7*/ } }; const float tnsAcfWindow[TNS_MAX_FILTER_ORDER] = diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 48f78c8f5..c4774c8cc 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1095,6 +1095,9 @@ extern const float dicn[40]; extern const Word32 dicn_fx[40]; extern const float dicn_inv[40]; extern const float thren_HQ[39]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 thren_HQ_fx[39]; +#endif extern const int16_t dicnlg2_float[40]; extern const int16_t huffnorm[32]; extern const int16_t huffsizn[32]; diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h index d9baadc35..39265617e 100644 --- a/lib_com/stat_com.h +++ b/lib_com/stat_com.h @@ -651,6 +651,7 @@ struct TnsParameters float minEnergyChange_flt; /* Minimum energy change required to turn on the TNS filter */ Word16 minPredictionGain; /* Minimum prediction gain required to turn on the TNS filter. Exponent = PRED_GAIN_E */ Word16 minAvgSqrCoef; /* Minimum average square of coefficients required to turn on the TNS filter. Exponent = 0 */ + Word16 minEnergyChange; /* Minimum energy change required to turn on the TNS filter. Exponent = 8 */ }; /**********************************************/ diff --git a/lib_com/tcx_utils_fx.c b/lib_com/tcx_utils_fx.c index d6002cb42..6de09ab90 100644 --- a/lib_com/tcx_utils_fx.c +++ b/lib_com/tcx_utils_fx.c @@ -2056,6 +2056,23 @@ void InitTnsConfigs( InitTnsConfiguration( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag ); } +void InitTnsConfigs_ivas_fx( + const Word16 bwidth, + const Word16 L_frame, + STnsConfig tnsConfig[2][2], + const Word16 igfStopFreq, + const Word32 total_brate, + const Word16 element_mode, + const Word16 MCT_flag ) +{ + IF( GT_32( total_brate, ACELP_32k ) ) + { + InitTnsConfiguration_ivas_fx( bwidth, shr( L_frame, 1 ), &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag ); + } + InitTnsConfiguration_ivas_fx( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag ); + InitTnsConfiguration_ivas_fx( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag ); +} + void SetTnsConfig( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index b63ba4e8e..99a4e6763 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -219,6 +219,142 @@ void InitTnsConfiguration( return; /*TNS_NO_ERROR;*/ } +void InitTnsConfiguration_ivas_fx( + const Word16 bwidth, + const Word16 frameLength, + STnsConfig *pTnsConfig, + const Word16 igfStopFreq, + const Word32 total_brate, + const Word16 element_mode, + const Word16 is_mct ) +{ + Word16 iFilter = 0; + move16(); + Word16 *startLineFilter; + Word32 L_tmp; + Word32 nSampleRate; + Word16 s1; + Word16 s2; + + nSampleRate = bwMode2fs[bwidth]; + move32(); + startLineFilter = &pTnsConfig->iFilterBorders[1]; + + /* Sanity checks */ + assert( ( nSampleRate > 0 ) && ( frameLength > 0 ) && ( pTnsConfig != NULL ) ); + test(); + test(); + IF( ( nSampleRate <= 0 ) || ( frameLength <= 0 ) || ( pTnsConfig == NULL ) ) + { + return /*TNS_FATAL_ERROR*/; + } + + + /* Initialize TNS filter flag and maximum order */ + move16(); + pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER; + + IF( LE_32( total_brate, ACELP_32k ) ) + { + move16(); + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParametersIGF32kHz_LowBR ), sizeof( tnsParametersIGF32kHz_LowBR[0] ) ); + pTnsConfig->pTnsParameters = tnsParametersIGF32kHz_LowBR; + } + ELSE + { + test(); + IF( GT_32( nSampleRate, 32000 ) && EQ_32( nSampleRate, L_mult0( 100, frameLength ) ) ) + { + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParameters48kHz_grouped ), sizeof( tnsParameters48kHz_grouped[0] ) ); + move16(); + pTnsConfig->pTnsParameters = tnsParameters48kHz_grouped; + } + ELSE IF( GT_32( nSampleRate, INT_FS_16k ) ) + { + L_tmp = IVAS_32k; + move32(); + if ( !is_mct ) + { + L_tmp = IVAS_48k; + move32(); + } + test(); + IF( GT_16( element_mode, IVAS_SCE ) && GE_32( total_brate, L_tmp ) ) + { + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParameters32kHz_Stereo ), sizeof( tnsParameters32kHz_Stereo[0] ) ); + move16(); + IF( EQ_32( nSampleRate, L_mult0( 100, frameLength ) ) ) /* sub-frame length is <= 10 ms */ + { + pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped; + } + ELSE + { + pTnsConfig->pTnsParameters = tnsParameters32kHz_Stereo; + } + } + ELSE + { + + move16(); + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParameters32kHz ), sizeof( tnsParameters32kHz[0] ) ); + + pTnsConfig->pTnsParameters = tnsParameters32kHz; + + if ( EQ_32( nSampleRate, L_mult0( 100, frameLength ) ) ) /* sub-frame length is <= 10 ms */ + { + pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped; + } + } + } + ELSE + { + IF( EQ_32( nSampleRate, L_mult0( 100, frameLength ) ) ) /* sub-frame length is <= 10 ms */ + { + move16(); + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParameters16kHz_grouped ), sizeof( tnsParameters16kHz_grouped[0] ) ); + pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped; + } + ELSE + { + move16(); + pTnsConfig->nMaxFilters = (UWord8) idiv1616( sizeof( tnsParameters16kHz ), sizeof( tnsParameters16kHz[0] ) ); + pTnsConfig->pTnsParameters = tnsParameters16kHz; + } + } + } + + assert( pTnsConfig->nMaxFilters <= TNS_MAX_NUM_OF_FILTERS ); + + /* Set starting MDCT line for each filter based on the starting frequencies from the TNS table */ + + FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ ) + { + assert( pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f * nSampleRate ); + move16(); + startLineFilter[iFilter] = divide3232( L_mult0( frameLength, pTnsConfig->pTnsParameters[iFilter].startLineFrequency ), L_shl( nSampleRate, 14 ) ); + } + + IF( igfStopFreq > 0 ) + { + L_tmp = L_mult( frameLength, igfStopFreq ); + s1 = sub( norm_l( L_tmp ), 1 ); + s2 = norm_l( nSampleRate ); + + move16(); + pTnsConfig->iFilterBorders[0] = shr( div_l( L_shl( L_tmp, s1 ), extract_h( L_shl( nSampleRate, s2 ) ) ), sub( WORD16_BITS - 1, sub( s2, s1 ) ) ); + } + ELSE + { + move16(); + pTnsConfig->iFilterBorders[0] = frameLength; + } + + pTnsConfig->allowTnsOnWhite = 0; + move16(); + + return; /*TNS_NO_ERROR;*/ +} + /*-------------------------------------------------------------------* * ApplyTnsFilter() * diff --git a/lib_com/tools.c b/lib_com/tools.c index 834fbfdb8..bdaacdf98 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -153,7 +153,26 @@ int32_t sum_l( return tmpL; } +#ifdef IVAS_FLOAT_FIXED +/*! r: sum of all vector elements */ +Word32 sum_l_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 tmpL; + + tmpL = 0; + move32(); + FOR( i = 0; i < lvec; i++ ) + { + tmpL = L_add( tmpL, vec[i] ); + } + return tmpL; +} +#endif /*! r: sum of all vector elements */ float sum_f( const float *vec, /* i : input vector */ diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index f321a6c26..0c4007783 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -615,7 +615,7 @@ ivas_error acelp_core_enc( /* intra_frame prediction for the LSFs */ lsp2lsf_fx( lsp_new_fx, lsf_new_fx, M, 12800 ); - Unified_weighting_fx( &st->Bin_E_fx[L_FFT / 2], add( Q_new, ( QSCALE - 2 ) ), lsf_new_fx, lsf_wgts_fx, st->bwidth == NB, EQ_16( st->coder_type, UNVOICED ), st->sr_core, M ); + Unified_weighting_fx( &st->Bin_E_fx[L_FFT / 2], add( Q_new, ( QSCALE - 2 ) ), lsf_new_fx, lsf_wgts_fx, st->bwidth == NB, (Word16) EQ_16( st->coder_type, UNVOICED ), st->sr_core, M ); tdm_SCh_lsf_reuse_fx( ENC, st->element_brate, lsf_new_fx, lsp_new_fx, tdm_lsfQ_PCh_fx, lsf_wgts_fx, &beta_index ); diff --git a/lib_enc/cng_enc_fx.c b/lib_enc/cng_enc_fx.c index e94da2f7c..496b65b3a 100644 --- a/lib_enc/cng_enc_fx.c +++ b/lib_enc/cng_enc_fx.c @@ -1564,7 +1564,6 @@ static Word16 shb_DTX_fx( * * *---------------------------------------------------------------------*/ - void calculate_hangover_attenuation_gain_fx( Encoder_State *st, /* i : encoder state structure */ Word16 *att, /* o : attenuation factor */ diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index 86ca20698..3aeaa3a6d 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -719,6 +719,92 @@ void TNSAnalysis_fx( } } +void TNSAnalysis_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 L_frame, /* i : frame length */ + Word16 L_spec, /* i : length of the spectrum */ + Word16 transform_type, /* i : transform type for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */ + Word8 isAfterACELP, /* i : Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */ + Word32 spectrum[], /* i : MDCT spectrum Q=Qx*/ + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + Word16 ltp_gain, /* i : ltp gain Q=15*/ + STnsData *pTnsData, /* o : Tns data */ + Word8 *pfUseTns, /* o : Flag indicating if TNS is used */ + Word16 *predictionGain /* o : TNS prediction gain Q=7 */ +) +{ + Word32 buff[8]; + Word16 tmp = 0; /* initialization only to avoid compiler warning, not counted */ + Word16 tmp2 = 0; /* initialization only to avoid compiler warning, not counted */ + move16(); + move16(); + + /* Init TNS */ + *pfUseTns = 0; + move16(); + + IF( hTcxCfg->fIsTNSAllowed != 0 ) + { + hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[sub( transform_type, TCX_20 ) == 0][isAfterACELP]; + test(); + L_spec = hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]; + move16(); + + /*-----------------------------------------------------------* + * Temporal Noise Shaping analysis * + *-----------------------------------------------------------*/ + + IF( EQ_16( transform_type, TCX_5 ) ) + { + tmp = shr( L_frame, 2 ); + + /* rearrange LF sub-window lines prior to TNS analysis & filtering */ + tmp2 = shr( L_spec, 1 ); + + IF( LT_16( tmp2, tmp ) ) + { + Copy32( spectrum + 8, spectrum + 16, sub( tmp2, 8 ) ); + Copy32( spectrum + tmp, spectrum + 8, 8 ); + Copy32( spectrum + tmp + 8, spectrum + tmp2 + 8, sub( tmp2, 8 ) ); + } + ELSE + { + Copy32( spectrum + tmp, buff, 8 ); + Copy32( spectrum + 8, spectrum + 16, sub( tmp, 8 ) ); + Copy32( buff, spectrum + 8, 8 ); + } + } + + move16(); + *pfUseTns = (Word8) DetectTnsFilt_ivas_fx( hTcxCfg->pCurrentTnsConfig, spectrum, pTnsData, hTranDet, (Word8) NE_16( transform_type, TCX_20 ), ltp_gain, predictionGain ); + + /* If TNS should be used then get the residual after applying it inplace in spectrum */ + IF( *pfUseTns != 0 ) + { + ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1 ); + } + + IF( EQ_16( transform_type, TCX_5 ) ) + { + /* undo rearrangement of LF sub-window lines prior to TNS analysis */ + IF( LT_16( tmp2, tmp ) ) + { + Copy32( spectrum + tmp2 + 8, spectrum + tmp + 8, sub( tmp2, 8 ) ); + Copy32( spectrum + 8, spectrum + tmp, 8 ); + Copy32( spectrum + 16, spectrum + 8, sub( tmp2, 8 ) ); + set32_fx( spectrum + tmp2, 0, sub( tmp, tmp2 ) ); + set32_fx( spectrum + tmp + tmp2, 0, sub( tmp, tmp2 ) ); + } + ELSE + { + Copy32( spectrum + 8, buff, 8 ); + Copy32( spectrum + 16, spectrum + 8, sub( tmp, 8 ) ); + Copy32( buff, spectrum + tmp, 8 ); + } + } + } +} + void ShapeSpectrum_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c index 6005d9cf6..47dadb33d 100644 --- a/lib_enc/ext_sig_ana.c +++ b/lib_enc/ext_sig_ana.c @@ -41,7 +41,10 @@ #include "prot.h" #include "rom_com.h" #include "wmc_auto.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* * core_signal_analysis_high_bitrate() @@ -400,8 +403,48 @@ void core_signal_analysis_high_bitrate( if ( st->element_mode != IVAS_CPE_MDCT ) { +#ifndef IVAS_FLOAT_FIXED TNSAnalysis( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], ( frameno == 0 ) && ( st->last_core == ACELP_CORE ), hTcxEnc->spectrum[frameno], st->hTranDet, -1, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // q factor of spectrum + Word16 q_factor_spectrum = Q_factor_arrL( hTcxEnc->spectrum[frameno], N_MAX ) - 1; + + /* conv params to fix */ + // -1 = -32768 , Q=15 , ltp_gain + // spectrum_fx[]=fixed( (float)spectrum[]) , Q=q_factor_spectrum + floatToFixed_arrL( hTcxEnc->spectrum_long, hTcxEnc->spectrum_long_fx, q_factor_spectrum, N_MAX ); + + // subblockNrg=(fix)((float)subblockNrg_flt) + floatToFixed_arrL( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg, 7, 24 ); + + // subblockNrgChange=(fix)((float)subblockNrgChange_flt) + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, 24 ); +#endif + test(); + TNSAnalysis_ivas_fx( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], ( frameno == 0 ) && ( st->last_core == ACELP_CORE ), hTcxEnc->spectrum_fx[frameno], st->hTranDet, -32768, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ); + + // subblockNrg_flt=(float)((fixed)subblockNrg) + fixedToFloat_arrL( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrg_flt, 7, 24 ); + + // subblockNrgChange_flt=(float)((fixed)subblockNrgChange) + fixedToFloat_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, 7, 24 ); + } +#endif +#endif if ( st->hTcxCfg->fIsTNSAllowed ) { EncodeTnsData( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frameno], param_core + frameno * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, pTnsSize + frameno, pTnsBits + frameno ); diff --git a/lib_enc/hq_classifier_enc.c b/lib_enc/hq_classifier_enc.c index c8bb4b8a1..219e61208 100644 --- a/lib_enc/hq_classifier_enc.c +++ b/lib_enc/hq_classifier_enc.c @@ -41,25 +41,25 @@ #include "prot.h" #include "rom_com.h" #include "wmc_auto.h" - +#include "prot_fx.h" +#include "prot_fx_enc.h" /*-----------------------------------------------------------------* * Local constants *-----------------------------------------------------------------*/ -#define SHARP_DIST_THRES 22.2f -#define HALF_WIN_LENGTH 10 -#define L_SPEC_HB 320 -#define PEAK_THRESHOLD 0.1f +#define SHARP_DIST_THRES 22.2f +#define HALF_WIN_LENGTH 10 +#define L_SPEC_HB 320 +#define PEAK_THRESHOLD 0.1f + #define LOW_COUNT_THRESHOLD 220 /*-----------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static void hvq_classifier( const float *input, int16_t *prev_Npeaks, int16_t *prev_peaks, int16_t *hqswb_clas, int16_t *Npeaks, int16_t *peaks, const int32_t core_brate, const int16_t last_core, float *nf_gains, int16_t *hvq_hangover, float *pe_gains ); -static int16_t hf_spectrum_sparseness( Encoder_State *st, const float *coefs ); - /*--------------------------------------------------------------------------* * hq_classifier_enc() * @@ -109,7 +109,6 @@ int16_t hq_classifier_enc( *hqswb_clas = peak_avrg_ratio( st->total_brate, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1 ); harmonic_decision = hf_spectrum_sparseness( st, coefs ); - if ( *hqswb_clas == HQ_HARMONIC && !harmonic_decision ) { *hqswb_clas = HQ_NORMAL; @@ -145,7 +144,7 @@ int16_t hq_classifier_enc( return bits; } - +#endif /*--------------------------------------------------------------------------* * peak_avrg_ratio() * @@ -239,13 +238,12 @@ int16_t peak_avrg_ratio( return hqswb_clas; } - +#ifndef IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* * hvq_classifier() * * Classification of spectral content for HQ_HVQ mode *--------------------------------------------------------------------------*/ - static void hvq_classifier( const float *input, /* i : input signal */ int16_t *prev_Npeaks, /* i/o: Peak number memory */ @@ -623,3 +621,4 @@ static int16_t hf_spectrum_sparseness( return result; } +#endif diff --git a/lib_enc/hq_classifier_enc_fx.c b/lib_enc/hq_classifier_enc_fx.c index 842f2029e..1c5c1de71 100644 --- a/lib_enc/hq_classifier_enc_fx.c +++ b/lib_enc/hq_classifier_enc_fx.c @@ -8,6 +8,7 @@ #include "rom_com_fx.h" /* Static table prototypes */ #include "rom_com.h" /* Static table prototypes */ #include "prot_fx.h" /* Function prototypes */ +#include "prot.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ /*-----------------------------------------------------------------* @@ -18,7 +19,8 @@ #define HALF_WIN_LENGTH 10 #define L_SPEC_HB 320 -#define PEAK_THRESHOLD 3277 /*Q15 0.1f*/ +#define PEAK_THRESHOLD 3277 /*Q15 0.1f*/ +#define PEAK_THRESHOLD_FX 214748364 // 0.1f in Q31 #define LOW_COUNT_THRESHOLD 220 @@ -27,13 +29,144 @@ *-----------------------------------------------------------------*/ void hvq_classifier_fx( const Word32 *input, Word16 *prev_Npeaks, Word16 *prev_peaks, Word16 *hqswb_clas, Word16 *Npeaks, Word16 *peaks, const Word32 L_core_brate, const Word16 last_core, Word32 *L_nf_gains, Word16 *hvq_hangover, Word32 *L_pe_gains ); +#ifdef IVAS_FLOAT_FIXED +static Word16 hf_spectrum_sparseness_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 *coefs_fx /* i : MDCT spectrum */ +); +/*--------------------------------------------------------------------------* + * hf_spectrum_sparseness() + * + * Detection of sparse spectrum in high band for activation of harmonic + * modes HQ_HARMONIC and HQ_HVQ + *--------------------------------------------------------------------------*/ +/*! r: Harmonic decision for high band */ +static Word16 hf_spectrum_sparseness_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 *coefs_fx /* i : MDCT spectrum (Q12) */ +) +{ + Word16 i; + Word32 thr_fx; + Word16 low_count_fx; + Word32 Amax_fx; + Word32 movmean_fx; + Word64 inv_rms_fx; + Word32 inv_rms32_fx; + Word32 inv_rms32_div_fx; + Word32 crest_fx; + Word32 crest_mod_fx; + const Word16 *p_num_fx; + Word32 A_fx[960]; + int16_t result; + Word32 *crest_lp_fx; + Word32 *crest_mod_lp_fx; + + crest_lp_fx = &st->hHQ_core->crest_lp_fx; + crest_mod_lp_fx = &st->hHQ_core->crest_mod_lp_fx; + + result = TRUE; + move16(); + IF( st->element_mode != EVS_MONO ) + { + + FOR( i = 0; i < L_SPEC_HB; i++ ) + { + A_fx[i] = L_abs( coefs_fx[i + L_SPEC_HB] ); + move32(); + } + low_count_fx = 0; + move16(); + inv_rms_fx = 0; + move64(); + crest_mod_fx = 0; + move32(); + maximum_l( A_fx, L_SPEC_HB, &Amax_fx ); + thr_fx = Mpy_32_32( Amax_fx, PEAK_THRESHOLD_FX ); + movmean_fx = 0; /* avoid uninitialized warning */ + // p_num = &inv_tbl[HALF_WIN_LENGTH + 1]; /* Table for division 1./(11:21) */ + p_num_fx = &inv_tbl_fx[HALF_WIN_LENGTH + 1]; /* Table for division 1./(11:21) */ + FOR( i = 0; i < L_SPEC_HB; i++ ) + { + // inv_rms += A[i] * A[i]; + inv_rms_fx = W_add( inv_rms_fx, W_shr( W_mult0_32_32( A_fx[i], A_fx[i] ), Q9 ) ); // 2*Q12 -Q9 (Q9 for guard bits + + if ( LT_32( A_fx[i], thr_fx ) ) + { + low_count_fx = add( low_count_fx, 1 ); + } + IF( LE_16( i, HALF_WIN_LENGTH ) ) + { + IF( i == 0 ) + { + movmean_fx = Mpy_32_16_1( sum_l_fx( &A_fx[0], i + HALF_WIN_LENGTH + 1 ), ( *p_num_fx ) ); // Q12 + } + ELSE + { + + p_num_fx++; + movmean_fx = L_add( movmean_fx, Mpy_32_16_1( L_sub( A_fx[i + HALF_WIN_LENGTH], movmean_fx ), ( *p_num_fx ) ) ); // Q12 + } + } + ELSE + { + IF( LE_16( L_SPEC_HB, i + HALF_WIN_LENGTH ) ) + { + + p_num_fx--; + movmean_fx = L_add( movmean_fx, Mpy_32_16_1( L_sub( movmean_fx, A_fx[i - HALF_WIN_LENGTH - 1] ), ( *p_num_fx ) ) ); // Q12 + } + ELSE + { + movmean_fx = L_add( movmean_fx, Mpy_32_16_1( L_sub( A_fx[i + HALF_WIN_LENGTH], A_fx[i - HALF_WIN_LENGTH - 1] ), ( *p_num_fx ) ) ); // Q12 + } + } + + if ( LT_32( crest_mod_fx, movmean_fx ) ) + { + crest_mod_fx = movmean_fx; // Q12 + move32(); + } + } + Word16 l_shift = W_norm( inv_rms_fx ); + inv_rms32_fx = W_extract_h( W_shl( inv_rms_fx, l_shift ) ); // Q15+l_shift-32 + Word16 q_rms = sub( add( Q15, l_shift ), 32 ); // q_rms + Word16 inv_rms32_e = 0; + move16(); + inv_rms32_div_fx = BASOP_Util_Divide3232_Scale_cadence( inv_rms32_fx, L_SPEC_HB, &inv_rms32_e ); + inv_rms32_e = sub( 31, add( sub( Q31, inv_rms32_e ), q_rms ) ); + // inv_rms = 1.0f / (float) sqrtf( inv_rms / L_SPEC_HB ); + inv_rms32_fx = ISqrt32( inv_rms32_div_fx, &inv_rms32_e ); + + crest_fx = Mpy_32_32( Amax_fx, inv_rms32_fx ); // Q12 + (Q31-inv_rms32_e) -Q31 = Q12 - inv_rms32_e + crest_mod_fx = Mpy_32_32( crest_mod_fx, inv_rms32_fx ); // Q12 + (Q31-inv_rms32_e) -Q31 = Q12 - inv_rms32_e + *crest_lp_fx = L_shr( *crest_lp_fx, sub( st->hHQ_core->crest_lp_q, sub( Q12, inv_rms32_e ) ) ); + move32(); + st->hHQ_core->crest_lp_q = sub( Q12, inv_rms32_e ); + *crest_lp_fx = L_add( Mpy_32_32( HQ_CREST_FAC_SM_FX, ( *crest_lp_fx ) ), Mpy_32_32( ONE_IN_Q31 - HQ_CREST_FAC_SM_FX, crest_fx ) ); // Q12 - inv_rms32_e + *crest_mod_lp_fx = L_shr( *crest_mod_lp_fx, sub( st->hHQ_core->crest_mod_lp_q, sub( Q12, inv_rms32_e ) ) ); + st->hHQ_core->crest_mod_lp_q = sub( Q12, inv_rms32_e ); + *crest_mod_lp_fx = L_add( Mpy_32_32( HQ_CREST_FAC_SM_FX, ( *crest_mod_lp_fx ) ), Mpy_32_32( L_sub( ONE_IN_Q31, HQ_CREST_FAC_SM_FX ), crest_mod_fx ) ); // Q12 - inv_rms32_e + Word32 hq_crest_threshold = L_shr( HQ_CREST_THRESHOLD_FX, sub( Q28, sub( Q12, inv_rms32_e ) ) ); + Word32 hq_crest_mod_threshold = L_shr( HQ_CREST_MOD_THRESHOLD_FX, sub( Q29, sub( Q12, inv_rms32_e ) ) ); + + test(); + test(); + if ( GT_32( ( *crest_lp_fx ), hq_crest_threshold ) && GT_32( ( *crest_mod_lp_fx ), hq_crest_mod_threshold ) && GT_16( low_count_fx, LOW_COUNT_THRESHOLD ) ) + { + result = FALSE; + move16(); + } + } + return result; +} +#endif /*--------------------------------------------------------------------------* * hq_classifier_enc_fx() * * HQ mode selector (decision_matrix) *--------------------------------------------------------------------------*/ - Word16 hq_classifier_enc_fx( /* o : Consumed bits Q0 */ Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 length, /* i : Frame length Q0 */ @@ -164,7 +297,7 @@ Word16 hq_classifier_enc_fx( /* o : Consumed bits /* Detect HQ_HARMONIC mode */ *hqswb_clas = peak_avrg_ratio_fx( st_fx->total_brate, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12 ); -#ifdef ADD_IVAS_HQ_CODE +#if 0 harmonic_decision = hf_spectrum_sparseness( st, coefs ); #else harmonic_decision = 0; @@ -210,7 +343,214 @@ Word16 hq_classifier_enc_fx( /* o : Consumed bits #endif return bits; } +#ifdef IVAS_FLOAT_FIXED +Word16 hq_classifier_enc_ivas_fx( /* o : Consumed bits Q0 */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +) +{ + + + Word16 bits; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + Word32 max_brate; + Word16 harmonic_decision; + + + max_brate = HQ_32k; + move32(); + if ( st_fx->element_mode > EVS_MONO ) + { + max_brate = HQ_48k; + move32(); + } + + *hqswb_clas = HQ_NORMAL; + bits = 1; + move16(); + IF( EQ_16( is_transient, 1 ) ) + { + *hqswb_clas = HQ_TRANSIENT; + move16(); + } + + /* classification and limit bandwidth for bit allocation */ + test(); + IF( EQ_16( length, L_SPEC32k ) || EQ_16( length, L_SPEC48k ) ) + { + IF( LE_32( st_fx->core_brate, max_brate ) ) + { + test(); + IF( !is_transient && EQ_16( st_fx->bwidth, st_fx->last_bwidth ) ) + { + /* Detect HQ_HARMONIC mode */ + + *hqswb_clas = peak_avrg_ratio_ivas_fx( st_fx->total_brate, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12 ); + + harmonic_decision = hf_spectrum_sparseness_fx( st_fx, coefs ); + + + test(); + IF( EQ_16( *hqswb_clas, HQ_HARMONIC ) && !harmonic_decision ) + { + *hqswb_clas = HQ_NORMAL; + move16(); + } + ELSE + { + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_ivas_fx( coefs, &hHQ_core->prev_Npeaks, hHQ_core->prev_peaks, hqswb_clas, Npeaks, peaks, st_fx->core_brate, st_fx->last_core, nf_gains, &hHQ_core->hvq_hangover, pe_gains ); + } + } + bits = 2; + move16(); + } + } + ELSE IF( EQ_16( length, L_SPEC16k_EXT ) || EQ_16( length, L_SPEC48k_EXT ) ) + { + bits = 0; /* HQ_NORMAL only -- no signalling needed */ + move16(); + } + /* write signalling info to the bitstream */ + push_indice( st_fx->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); + + IF( LE_32( st_fx->core_brate, HQ_32k ) && EQ_16( *hqswb_clas, HQ_NORMAL ) ) + { + IF( EQ_16( length, L_SPEC32k ) ) + { + *hqswb_clas = HQ_GEN_SWB; + move16(); + } + ELSE IF( EQ_16( length, L_SPEC48k ) ) + { + *hqswb_clas = HQ_GEN_FB; + move16(); + } + } + + return bits; +} +#endif +#ifdef IVAS_FLOAT_FIXED +/*--------------------------------------------------------------------------* + * peak_avrg_ratio() + * + * Classify the input signal and decide if it has a harmonic structure + *--------------------------------------------------------------------------*/ +Word16 peak_avrg_ratio_ivas_fx( + const Word32 total_brate, /* i : total bitrate */ + const Word32 *input_hi_fx, /* i : input signal Q_coeff */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count Q0*/ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count Q0*/ + Word16 Q_coeff ) +{ + Word16 i, j, q, k, k1, hqswb_clas; + Word32 mean_fx, peak_fx; + Word32 input_abs_fx[L_FRAME32k]; + Word32 peak_th_fx; + + FOR( i = 96; i < length; i++ ) + { + input_abs_fx[i] = L_abs( input_hi_fx[i] ); + move32(); + } + + hqswb_clas = HQ_NORMAL; + move16(); + peak_th_fx = L_shl( 10L, sub( Q_coeff, 5 ) ); /* 5 is safe shift */ + + k = 0; + move16(); + k1 = 0; + move16(); + q = 96; /* q used for indexing */ + + FOR( i = 3; i < 17; i++ ) + { + peak_fx = L_deposit_l( 0 ); + mean_fx = L_deposit_l( 1 ); + + /*for(j = 0; j < 32; j ++, q ++) */ + FOR( j = 0; j < 32; j++ ) + { + input_abs_fx[q] = L_shr( input_abs_fx[q], 5 ); /*Q_coeff-5 */ + move32(); + mean_fx = L_add( mean_fx, input_abs_fx[q] ); /*Q_coeff-5 */ + IF( GT_32( input_abs_fx[q], peak_fx ) ) + { + peak_fx = input_abs_fx[q]; /*Q_coeff-5 */ + } + q = add( q, 1 ); + } + + IF( LT_16( i, 8 ) ) + { + if ( GT_32( peak_fx, Mult_32_16( mean_fx, 4608 ) ) ) /* Q15 0.140625 */ + { + k = add( k, 1 ); + } + } + ELSE + { + test(); + if ( GT_32( peak_fx, Mult_32_16( mean_fx, 3686 ) ) /*Q15 0.1125 */ + && GT_32( peak_fx, peak_th_fx ) ) /*Q27 10 */ + { + k1 = add( k1, 1 ); + } + } + } + + test(); + IF( GE_16( add( k, k1 ), 10 ) && GT_16( k1, 5 ) ) + { + if ( LT_16( *mode_count, 8 ) ) + { + *mode_count = add( *mode_count, 1 ); + } + + if ( *mode_count1 > 0 ) + { + *mode_count1 = sub( *mode_count1, 1 ); + } + } + ELSE + { + if ( LT_16( *mode_count1, 8 ) ) + { + *mode_count1 = add( *mode_count1, 1 ); + } + + if ( *mode_count > 0 ) + { + *mode_count = sub( *mode_count, 1 ); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + if ( ( GE_16( add( k, k1 ), 5 ) && GT_16( k1, 2 ) && LT_32( total_brate, HQ_BWE_CROSSOVER_BRATE ) ) || ( ( ( GE_16( add( k, k1 ), 10 ) && GT_16( k1, 5 ) ) || GE_16( *mode_count, 5 ) ) && LT_16( *mode_count1, 5 ) ) ) + { + hqswb_clas = HQ_HARMONIC; + move16(); + } + + return hqswb_clas; +} +#endif /*--------------------------------------------------------------------------* * peak_avrg_ratio() * @@ -329,7 +669,446 @@ Word16 peak_avrg_ratio_fx( * * Classification of harmonic low band content for Harmonic VQ *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void hvq_classifier_ivas_fx( + const Word32 *input, /* i : input signal Q12 */ + Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ + Word16 *prev_peaks, /* i/o: Peak indices memory Q0 */ + Word16 *hqswb_clas, /* i/o: HQ class Q0 */ + Word16 *Npeaks, /* o : Number of peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + const Word32 L_core_brate, /* i : Core bit-rate Q0 */ + const Word16 last_core, /* i : Last core used Q0 */ + Word32 *L_nf_gains, /* o : Noisefloor gains Q12 */ + Word16 *hvq_hangover, /* i/o: Mode-switch hangover Q0 */ + Word32 *L_pe_gains /* o : peak gains Q12 */ +) +{ + const Word16 *p_adj; + UWord16 lsb; + Word32 L_input_abs[L_FRAME32k]; + Word32 L_input_max; + Word32 L_thr[L_FRAME16k]; + Word32 L_thr_tmp; + Word32 L_m; + Word32 L_tmp; + Word32 L_d; + Word32 L_peak; + Word32 L_nf, L_pe; + Word32 L_pe_mean[HVQ_NSUB_32k], L_nf_mean[HVQ_NSUB_32k]; + + Word16 inv_nsub; + Word16 sharp_dist; + Word16 exp1, exp2; + Word16 tmp; + Word16 shift; + Word16 idx; + Word16 frac; + Word16 inv_nf_mean; + Word16 inv_gains_nsub; + Word16 nf_mean_norm; + Word16 num_sharp_bands, i, j, k, q, peak_th, nsub, pindx, N, offset; + Word16 num_peak_cands, high, low; + Word16 sharp[HVQ_NSUB_32k]; + Word16 peak_cand_idx[HVQ_THRES_BIN_32k], avail_peaks[HVQ_NSUB_32k]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); +#endif + Word16 temp_e = 0; + move16(); + L_input_max = L_deposit_l( 0 ); + set32_fx( L_thr, 0, L_FRAME16k ); + + IF( LT_32( L_core_brate, HQ_BWE_CROSSOVER_BRATE ) ) + { + nsub = HVQ_NSUB_24k; + move16(); + inv_nsub = 4681; + move16(); /* 1/7 in Q15 */ + inv_gains_nsub = 10923; + move16(); /* 1/3 in Q15 */ + } + ELSE + { + nsub = HVQ_NSUB_32k; + move16(); + inv_nsub = 3277; + move16(); /* 1/10 in Q15 */ + inv_gains_nsub = 6554; + move16(); /* 1/5 in Q15 */ + } + + N = shl( nsub, 5 ); /* Mult by 32 (HVQ_BW) */ + + test(); + test(); + IF( EQ_16( *hqswb_clas, HQ_HARMONIC ) && last_core != ACELP_CORE && NE_16( last_core, AMR_WB_CORE ) ) + { + FOR( i = 0; i < N; i++ ) + { + L_input_abs[i] = L_abs( input[i] ); + if ( L_input_abs[i] > L_input_max ) + { + L_input_max = L_input_abs[i]; + move16(); + } + } + + exp1 = norm_l( L_input_max ); + + *Npeaks = 0; + move16(); + L_nf = 3276800; + move32(); /* 800 in Q12 */ + L_pe = 3276800; + move32(); /* 800 in Q12 */ + num_sharp_bands = 0; + move16(); + k = 0; + move16(); + q = 0; + move16(); + sharp_dist = 0; + move16(); + + /* Find peak threshold */ + FOR( i = 0; i < nsub; i++ ) + { + L_peak = 0; + L_nf_mean[i] = 0; + L_pe_mean[i] = 0; + move32(); + move32(); + move32(); + + FOR( j = 0; j < HVQ_BW; j++ ) + { + L_d = L_input_abs[q]; + IF( GT_32( L_d, L_nf ) ) + { + /*nf = HVQ_NF_WEIGHT1 * nf + (1 - HVQ_NF_WEIGHT1) * d; */ + Mpy_32_16_ss( L_d, HVQ_NF_WEIGHT1B, &L_tmp, &lsb ); /* 12+15-15=12 */ + Mpy_32_16_ss( L_nf, HVQ_NF_WEIGHT1_FX, &L_nf, &lsb ); /* 12+15-15=12 */ + L_nf = L_add( L_nf, L_tmp ); /*Q12 */ + } + ELSE + { + /*nf = HVQ_NF_WEIGHT2 * nf + (1 - HVQ_NF_WEIGHT2) * d; */ + Mpy_32_16_ss( L_d, HVQ_NF_WEIGHT2B, &L_tmp, &lsb ); /* 12+15-15=12 */ + Mpy_32_16_ss( L_nf, HVQ_NF_WEIGHT2_FX, &L_nf, &lsb ); /* 12+15-15=12 */ + L_nf = L_add( L_nf, L_tmp ); /*Q12 */ + } + + IF( GT_32( L_d, L_pe ) ) + { + /*pe = HVQ_PE_WEIGHT1 * pe + (1 - HVQ_PE_WEIGHT1) * d; */ + Mpy_32_16_ss( L_d, HVQ_PE_WEIGHT1B, &L_tmp, &lsb ); /* 12+15-15=12 */ + Mpy_32_16_ss( L_pe, HVQ_PE_WEIGHT1_FX, &L_pe, &lsb ); /* 12+15-15=12 */ + L_pe = L_add( L_pe, L_tmp ); /*Q12 */ + } + ELSE + { + /*pe = HVQ_PE_WEIGHT2 * pe + (1 - HVQ_PE_WEIGHT2) * d; */ + Mpy_32_16_ss( L_d, HVQ_PE_WEIGHT2B, &L_tmp, &lsb ); /* 12+15-15=12 */ + Mpy_32_16_ss( L_pe, HVQ_PE_WEIGHT2_FX, &L_pe, &lsb ); /* 12+15-15=12 */ + L_pe = L_add( L_pe, L_tmp ); /*Q12 */ + } + +#ifdef BASOP_NOGLOB + L_nf_mean[i] = L_add_sat( L_nf_mean[i], L_nf ); + L_pe_mean[i] = L_add_sat( L_pe_mean[i], L_pe ); +#else + L_nf_mean[i] = L_add( L_nf_mean[i], L_nf ); + L_pe_mean[i] = L_add( L_pe_mean[i], L_pe ); +#endif + move32(); + move32(); + IF( GT_32( L_d, L_peak ) ) + { + L_peak = L_add( L_d, 0 ); + } + + q = add( q, 1 ); + } + L_nf_mean[i] = L_shr( L_nf_mean[i], 5 ); /* Divide by 5 (HVQ_BW) */ + L_pe_mean[i] = L_shr( L_pe_mean[i], 5 ); /* Divide by 5 (HVQ_BW) */ + move32(); + move32(); + /*thr_tmp = (float)pow( pe_mean[i]/nf_mean[i], HVQ_THR_POW ) * nf_mean[i]; */ + exp1 = norm_l( L_nf_mean[i] ); + nf_mean_norm = extract_h( L_shl( L_nf_mean[i], exp1 ) ); /* 12+s-16=s-4 */ + IF( nf_mean_norm == 0 ) + { + inv_nf_mean = 0; + } + ELSE + { + inv_nf_mean = div_s( 1 << 14, nf_mean_norm ); /* 15+14-s+4=33-s */ + } + Mpy_32_16_ss( L_pe_mean[i], inv_nf_mean, &L_tmp, &lsb ); /*12+33-s-15=30-s */ + + exp2 = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp2 ) ); /* Q15 */ + exp2 = sub( exp1, exp2 ); /* Q0 */ + L_tmp = Mpy_32_16( exp2, tmp, 32767 ); /* 1 in Q15. Q16 */ + Mpy_32_16_ss( L_tmp, 28836, &L_tmp, &lsb ); /* 16+15-15=16 */ + frac = L_Extract_lc( L_tmp, &tmp ); /* Q15 and Q0 */ + L_tmp = Pow2( 14, frac ); /* Q14 */ + L_tmp = L_shl( L_tmp, tmp ); /* Q14 */ + + Mpy_32_16_ss( L_tmp, nf_mean_norm, &L_tmp, &lsb ); /*14+s-4-15=s-5 */ + shift = sub( 17, exp1 ); /* 16-(s-5)=17-s */ + L_thr_tmp = L_shl( L_tmp, shift ); /* Q16 */ + L_thr_tmp = L_add( L_thr_tmp, lshr( lsb, sub( 16, shift ) ) ); /*Q16 */ + + set32_fx( &L_thr[k], L_thr_tmp, HVQ_BW ); + k = add( k, HVQ_BW ); + + /*sharp[i] = peak/nf_mean[i]; */ + Mpy_32_16_ss( L_peak, inv_nf_mean, &L_tmp, &lsb ); /* 12+33-s-15=30-s */ + shift = sub( exp1, 8 ); + sharp[i] = extract_h( L_shl( L_tmp, shift ) ); /* 30-s+s-8-16 -> Q6 */ + move16(); + /*sharp_dist += (sharp[i]-HVQ_SHARP_THRES); */ +#ifdef BASOP_NOGLOB + sharp_dist = add_o( sharp_dist, sub( sharp[i], HVQ_SHARP_THRES_FX ), &Overflow ); +#else + sharp_dist = add( sharp_dist, sub( sharp[i], HVQ_SHARP_THRES_FX ) ); +#endif + if ( GT_16( sharp[i], HVQ_SHARP_THRES_FX ) ) + { + num_sharp_bands = add( num_sharp_bands, 1 ); + } + } + + /* Estimate noise floor gains */ + offset = s_and( nsub, 1 ); + FOR( i = 0; i < s_and( nsub, (Word16) 0xFFFE ); i++ ) + { + /*(2*i+1)/nsub */ + idx = mult( add( shl( i, 1 ), 1 ), add( inv_nsub, 1 ) ); /*0+15-15 = 0 */ + L_nf_gains[idx] = L_add( L_nf_gains[idx], L_nf_mean[i + offset] ); + L_pe_gains[idx] = L_add( L_pe_gains[idx], L_pe_mean[i + offset] ); + move32(); + move32(); + } + + FOR( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + Mpy_32_16_ss( L_nf_gains[i], inv_gains_nsub, &L_nf_gains[i], &lsb ); /*12+15-15=12 */ + Mpy_32_16_ss( L_pe_gains[i], inv_gains_nsub, &L_pe_gains[i], &lsb ); /*12+15-15=12 */ + } + + /* Allocate available peaks */ + FOR( i = 0; i < nsub; i++ ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP1; + move16(); + idx = mult( add( shl( i, 1 ), 1 ), add( inv_nsub, 1 ) ); /*0+15-15 = 0 */ + Mpy_32_16_ss( L_nf_gains[idx], HVQ_PA_FAC_FX, &L_tmp, &lsb ); /* 12+15-15 -> Q12 */ + IF( LT_32( L_nf_mean[i], L_tmp ) ) + { + IF( LT_16( sharp[i], HVQ_PA_SHARP_THRES3_FX ) ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP3; + move16(); + } + ELSE IF( LT_16( sharp[i], HVQ_PA_SHARP_THRES2_FX ) ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP2; + move16(); + } + } + } + + + /* Adjust threshold around previous peaks */ + FOR( i = 0; i < *prev_Npeaks; i++ ) + { + j = sub( prev_peaks[i], 2 ); + k = add( prev_peaks[i], 2 ); + p_adj = hvq_thr_adj_fx; + + FOR( q = j; q < k; q++ ) + { + Mpy_32_16_ss( L_thr[q], *p_adj++, &L_thr[q], &lsb ); /* 12+15-15=12 */ + move32(); + } + } + + num_peak_cands = 0; + move16(); + + /* Remove everything below threshold for peak search */ + L_input_abs[0] = L_deposit_l( 0 ); + L_input_abs[1] = L_deposit_l( 0 ); + L_input_abs[N - 2] = L_deposit_l( 0 ); + L_input_abs[N - 1] = L_deposit_l( 0 ); + move32(); + move32(); + move32(); + move32(); + FOR( i = 0; i < N - 2; i++ ) + { + IF( LT_32( L_input_abs[i], L_thr[i] ) ) + { + L_input_abs[i] = L_deposit_l( 0 ); + move32(); + } + ELSE + { + L_input_abs[num_peak_cands] = L_input_abs[i]; + move32(); + peak_cand_idx[num_peak_cands] = i; + move16(); + num_peak_cands = add( num_peak_cands, 1 ); + } + } + + peak_th = (Word16) BASOP_Util_Divide3232_Scale( L_add( W_extract_l( W_mult0_32_32( L_core_brate, HVQ_PEAKS_PER_DELTA_THR ) ), HVQ_PEAKS_PER_DELTA_THR_OFFS ), HVQ_PEAKS_BPS_DELTA, &temp_e ); + peak_th = shr( peak_th, sub( 15, temp_e ) ); + /* Find peaks */ + pindx = maximum_32_fx( L_input_abs, num_peak_cands, &L_m ); + i = 0; + move16(); + + WHILE( L_m > 0 && LT_16( i, peak_th + 1 ) ) + { + idx = mult( peak_cand_idx[pindx], INV_HVQ_BW ); /* 0+15-15=0 */ + IF( avail_peaks[idx] > 0 ) + { + peaks[i++] = peak_cand_idx[pindx]; + avail_peaks[idx]--; + } + + j = sub( pindx, 2 ); + k = add( pindx, 2 ); + + if ( j < 0 ) + { + j = 0; + move16(); + } + + tmp = sub( num_peak_cands, 1 ); + if ( GT_16( k, tmp ) ) + { + k = tmp; + move16(); + } + + low = sub( peak_cand_idx[pindx], 2 ); + high = add( peak_cand_idx[pindx], 2 ); + + if ( low < 0 ) + { + low = 0; + move16(); + } + + tmp = sub( N, 1 ); + if ( GT_16( high, tmp ) ) + { + high = tmp; + move16(); + } + + FOR( q = j; q <= pindx; q++ ) + { + IF( GE_16( peak_cand_idx[q], low ) ) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + FOR( q = pindx + 1; q <= k; q++ ) + { + IF( LE_16( peak_cand_idx[q], high ) ) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + pindx = maximum_32_fx( L_input_abs, num_peak_cands, &L_m ); + } + + *Npeaks = i; + move16(); + IF( GT_16( *Npeaks, HVQ_MIN_PEAKS ) ) + { + test(); + IF( GT_16( num_sharp_bands, sub( nsub, 3 ) ) && LE_16( *Npeaks, peak_th ) ) + { + sharp_dist = mult( sharp_dist, inv_nsub ); /*x+15-15=x */ + test(); + IF( LE_16( sharp_dist, SHARP_DIST_THRES_FX ) && *hvq_hangover < 0 ) + { + *hvq_hangover = add( *hvq_hangover, 1 ); + } + ELSE + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = 2; + move16(); + } + + /* update memory */ + *prev_Npeaks = *Npeaks; + move16(); + Copy( peaks, prev_peaks, *Npeaks ); + } + ELSE + { + IF( *hvq_hangover > 0 ) + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = sub( *hvq_hangover, 1 ); + move16(); + } + ELSE + { + *hvq_hangover = -1; + move16(); + } + } + } + ELSE + { + /* Zero peaks, likely silence input. */ + *hvq_hangover = -1; + move16(); + } + + //*Npeaks = (int16_t) ( s_min( ( L_core_brate * HVQ_PEAKS_PER_DELTA + HVQ_PEAKS_PER_DELTA_OFFS ) / HVQ_PEAKS_BPS_DELTA, *Npeaks ) ); + temp_e = 0; + move16(); + Word16 Npeaks_temp = *Npeaks; + *Npeaks = BASOP_Util_Divide3232_Scale( L_add( W_extract_l( W_mult0_32_32( L_core_brate, HVQ_PEAKS_PER_DELTA ) ), HVQ_PEAKS_PER_DELTA_OFFS ), HVQ_PEAKS_BPS_DELTA, &temp_e ); + *Npeaks = s_min( shr( *Npeaks, sub( 15, temp_e ) ), Npeaks_temp ); + } + ELSE + { + *prev_Npeaks = 0; + move16(); + *hvq_hangover = 0; + move16(); + } + + + return; +} + +#endif void hvq_classifier_fx( const Word32 *input, /* i : input signal Q12 */ Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c index c3571735b..da055a340 100644 --- a/lib_enc/hq_core_enc.c +++ b/lib_enc/hq_core_enc.c @@ -247,8 +247,12 @@ void hq_core_enc( } else { +#ifdef IVAS_FLOAT_FIXED /* HQ high rate encoder */ hq_hr_enc( st, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag ); +#else + hq_hr_enc( st, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag ); +#endif } /* write all unused bits to the bitstream */ diff --git a/lib_enc/hq_env_enc_fx.c b/lib_enc/hq_env_enc_fx.c index 1d5ac96b8..a133f2ce6 100644 --- a/lib_enc/hq_env_enc_fx.c +++ b/lib_enc/hq_env_enc_fx.c @@ -10,7 +10,7 @@ #include "stl.h" #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ -#include "prot.h" +#include "prot.h" /* Function prototypes */ /*--------------------------------------------------------------------------------------* * encode_envelope_indices_fx() @@ -553,7 +553,6 @@ Word16 encode_envelope_indices_fx( /* o : Number of b return hcode_l; } - #ifdef IVAS_FLOAT_FIXED Word16 encode_envelope_indices_ivas_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ BSTR_ENC_HANDLE hBstr, /* i : handle to the bitstream */ diff --git a/lib_enc/hq_hr_enc.c b/lib_enc/hq_hr_enc.c index 506a90e43..d1aecb8a8 100644 --- a/lib_enc/hq_hr_enc.c +++ b/lib_enc/hq_hr_enc.c @@ -40,6 +40,8 @@ #include "prot.h" #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" +#include "ivas_prot_fx.h" +#include "prot_fx_enc.h" #endif #include "rom_enc.h" #include "rom_com.h" @@ -254,6 +256,7 @@ void hq_hr_enc( return; } #else + void hq_hr_enc( Encoder_State *st, /* i/o: encoder state structure */ float *t_audio, /* i/o: transform-domain coefficients */ @@ -268,6 +271,7 @@ void hq_hr_enc( int16_t difidx[NB_SFM]; int16_t normqlg2[NB_SFM], ynrm[NB_SFM]; int16_t nf_idx; + Word16 bits; int16_t LCmode; int16_t shape_bits, num_sfm, numnrmibits; int16_t hqswb_clas; @@ -282,6 +286,7 @@ void hq_hr_enc( float t_audio_q[L_SPEC48k_EXT]; float nf_gains[HVQ_NF_GROUPS], pe_gains[HVQ_NF_GROUPS]; float noise_level[HVQ_BWE_NOISE_BANDS]; + Word16 noise_level_fx[HVQ_BWE_NOISE_BANDS]; int16_t hq_generic_offset; float hq_generic_fenv[HQ_FB_FENV]; int16_t hq_generic_exc_clas = 0; @@ -291,10 +296,12 @@ void hq_hr_enc( const int16_t *subband_search_offset; int16_t wBands[2]; int16_t b_delta_env; - float att; + // float att; HQ_ENC_HANDLE hHQ_core = st->hHQ_core; BSTR_ENC_HANDLE hBstr = st->hBstr; #ifdef IVAS_FLOAT_FIXED + Word16 att_fx; + Word32 nf_gains_fx[HVQ_NF_GROUPS], pe_gains_fx[HVQ_NF_GROUPS]; Word32 t_audio_fx[L_FRAME48k_EXT]; Word16 hq_generic_fenv_fx[HQ_FB_FENV]; #endif @@ -309,37 +316,65 @@ void hq_hr_enc( set_f( t_audio_q, 0.0f, L_FRAME48k ); set_f( nf_gains, 0.0f, HVQ_NF_GROUPS ); set_f( pe_gains, 0.0f, HVQ_NF_GROUPS ); - + set_l( nf_gains_fx, 0, HVQ_NF_GROUPS ); + set_l( pe_gains_fx, 0, HVQ_NF_GROUPS ); /*------------------------------------------------------------------* * Classification *------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Word32 coefs_fx[960]; + floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + Word16 temp_e; - *num_bits -= hq_classifier_enc( st, length, t_audio, is_transient, &Npeaks, peaks, pe_gains, nf_gains, &hqswb_clas ); + f2me( st->hHQ_core->crest_lp, &st->hHQ_core->crest_lp_fx, &temp_e ); + st->hHQ_core->crest_lp_q = 31 - temp_e; + f2me( st->hHQ_core->crest_mod_lp, &st->hHQ_core->crest_mod_lp_fx, &temp_e ); + st->hHQ_core->crest_mod_lp_q = 31 - temp_e; + } +#endif + + bits = hq_classifier_enc_ivas_fx( st, length, t_audio_fx, is_transient, &Npeaks, peaks, pe_gains_fx, nf_gains_fx, &hqswb_clas ); + *num_bits = sub( *num_bits, bits ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( NE_16( st->element_mode, EVS_MONO ) ) + { + + st->hHQ_core->crest_lp = fix_to_float( st->hHQ_core->crest_lp_fx, st->hHQ_core->crest_lp_q ); + st->hHQ_core->crest_mod_lp = fix_to_float( st->hHQ_core->crest_mod_lp_fx, st->hHQ_core->crest_mod_lp_q ); + } + fixedToFloat_arrL32( nf_gains_fx, nf_gains, Q12, HVQ_NF_GROUPS ); + fixedToFloat_arrL32( pe_gains_fx, pe_gains, Q12, HVQ_NF_GROUPS ); +#endif /*------------------------------------------------------------------* * Set quantization parameters *------------------------------------------------------------------*/ - hq_configure( length, hqswb_clas, st->core_brate, &num_sfm, &nb_sfm, &start_norm, &num_env_bands, &numnrmibits, &hq_generic_offset, sfmsize, sfm_start, sfm_end ); + hq_configure_fx( length, hqswb_clas, st->core_brate, &num_sfm, &nb_sfm, &start_norm, &num_env_bands, &numnrmibits, &hq_generic_offset, sfmsize, sfm_start, sfm_end ); /*------------------------------------------------------------------* * Transient frame handling *------------------------------------------------------------------*/ - /* Interleave MLT coefficients of 4 sub-vectors in case of transient frame */ - if ( is_transient ) + IF( is_transient ) { - interleave_spectrum( t_audio, length ); + interleave_spectrum_ivas_fx( t_audio_fx, length ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k_EXT ); +#endif } - - if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) + test(); + IF( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { - calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); - if ( att != 1.0f ) - { - v_multc( t_audio, att, t_audio, sfm_end[num_sfm - 1] ); - } + calculate_hangover_attenuation_gain_fx( st, &att_fx, vad_hover_flag ); + // att = fix16_to_float( att_fx, Q15 ); + v_multc_att32( t_audio_fx, att_fx, t_audio_fx, sfm_end[sub( num_sfm, 1 )] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( t_audio_fx, t_audio, Q12, L_FRAME48k_EXT ); +#endif } /*------------------------------------------------------------------* @@ -348,48 +383,69 @@ void hq_hr_enc( *------------------------------------------------------------------*/ /* calculate and quantize norms */ - calc_norm( t_audio, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + // calc_norm_fx( t_audio_fx, 12, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + calc_norm_ivas_fx( t_audio_fx, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + // calc_norm( t_audio, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); +#if 0 + FILE *fp = fopen( "Fixed_code_ynrm.txt", "ab+" ); + FILE *fp1 = fopen( "Fixed_code_normqlg2.txt", "ab+" ); + for (int i = 0; i < 44; i++) + { + //fprintf( fp, "%d\t%d\t", frame,i ); + fprintf( fp, "%d\n", ynrm[i] ); + //fprintf( fp1, "%d\t%d\t", frame, i ); + fprintf( fp1, "%d\n", normqlg2[i] ); + } + fclose( fp ); + fclose( fp1 ); +#endif /* create differential code of quantized norm indices */ - diff_envelope_coding( is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx ); + diff_envelope_coding_fx( is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx ); /* Find norm coding mode and calculate number of bits */ - hcode_l = encode_envelope_indices( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); - *num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; - + hcode_l = encode_envelope_indices_ivas_fx( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); + //*num_bits -= hcode_l + NORM0_BITS + FLAGS_BITS; + *num_bits = sub( *num_bits, add( hcode_l, NORM0_BITS + FLAGS_BITS ) ); /* Encode norm indices */ - encode_envelope_indices( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); + encode_envelope_indices_ivas_fx( hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); /*------------------------------------------------------------------* * HQ GENERIC BWE encoding *------------------------------------------------------------------*/ - if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB ) + test(); + IF( EQ_16( hqswb_clas, HQ_GEN_SWB ) || EQ_16( hqswb_clas, HQ_GEN_FB ) ) { #ifdef IVAS_FLOAT_FIXED -#ifdef MSAN_FIX - floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k ); -#else - floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); -#endif + //#ifdef MSAN_FIX + // floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k ); + //#else + // floatToFixed_arrL32( t_audio, t_audio_fx, Q12, L_FRAME48k_EXT ); + //#endif hq_generic_hf_encoding_fx( t_audio_fx, hq_generic_fenv_fx, hq_generic_offset, st, &hq_generic_exc_clas, length ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS fixedToFloat_arr( hq_generic_fenv_fx, hq_generic_fenv, Q1, HQ_FB_FENV ); +#endif #else hq_generic_hf_encoding( t_audio, hq_generic_fenv, hq_generic_offset, st, &hq_generic_exc_clas, length ); #endif - if ( hq_generic_exc_clas == HQ_GENERIC_SP_EXC ) + IF( EQ_16( hq_generic_exc_clas, HQ_GENERIC_SP_EXC ) ) { - ( *num_bits )++; /* conditional 1 bit saving for representing FD3 BWE excitation class */ + *num_bits = add( *num_bits, 1 ); /* conditional 1 bit saving for representing FD3 BWE excitation class */ + move16(); } - map_hq_generic_fenv_norm( hqswb_clas, hq_generic_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); + map_hq_generic_fenv_norm_fx( hqswb_clas, hq_generic_fenv_fx, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); } /*------------------------------------------------------------------* * Bit allocation *------------------------------------------------------------------*/ - hq_bit_allocation( st->core_brate, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level, R, Rsubband, &sum, &core_sfm, num_env_bands ); - + ivas_hq_bit_allocation_fx( st->core_brate, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level_fx, R, Rsubband, &sum, &core_sfm, num_env_bands ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( noise_level_fx, noise_level, Q15, HVQ_BWE_NOISE_BANDS ); +#endif /*------------------------------------------------------------------* * Normalize coefficients with quantized norms *------------------------------------------------------------------*/ diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index c0b30eba8..c473752dc 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -409,11 +409,10 @@ ivas_error ivas_cpe_enc( // printf("\n%f %f ", hCPE->hStereoClassif->is_speech, hCPE->hCoreCoder[0]->hSpMusClas->past_dlp[0]); if ( hCPE->element_mode == IVAS_CPE_DFT ) { - stereo_dft_hybrid_ITD_flag( hCPE->hStereoDft->hConfig, input_Fs, hCPE->hStereoDft->hItd->hybrid_itd_max ); -#ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 i; /* flt2fix: to be removed */ - FOR( int i = 0; i < CPE_CHANNELS; i++ ) + FOR( i = 0; i < CPE_CHANNELS; i++ ) { sts[i]->q_inp = Q_factor_arr( sts[i]->old_input_signal, 1965 ); // check length #ifndef MSAN_FIX @@ -428,10 +427,67 @@ ivas_error ivas_cpe_enc( } floatToFixed_arrL( hCPE->hStereoDft->side_gain, hCPE->hStereoDft->side_gain_fx, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); floatToFixed_arrL( hCPE->hStereoDft->gipd, hCPE->hStereoDft->gipd_fx, Q13, STEREO_DFT_ENC_DFT_NB ); - floatToFixed_arrL( hCPE->hStereoDft->hItd->itd, hCPE->hStereoDft->hItd->itd_fx, Q16, STEREO_DFT_ENC_DFT_NB ); - floatToFixed_arrL( hCPE->hStereoDft->hItd->deltaItd, hCPE->hStereoDft->hItd->deltaItd_fx, Q16, STEREO_DFT_ENC_DFT_NB ); /* flt2fix end */ + + + /*flt2fix: dft_td_itd*/ + f2me_buf( hCPE->hStereoDft->xspec_smooth, hCPE->hStereoDft->xspec_smooth_fx, &hCPE->hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); + f2me_buf( hCPE->hStereoDft->Spd_L_smooth, hCPE->hStereoDft->Spd_L_smooth_fx, &hCPE->hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + f2me_buf( hCPE->hStereoDft->Spd_R_smooth, hCPE->hStereoDft->Spd_R_smooth_fx, &hCPE->hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); + floatToFixed_arrL( hCPE->hStereoDft->hItd->itd, hCPE->hStereoDft->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_fv, hCPE->hStereoClassif->xtalk_fv_fx, 15, SSC_MAX_NFEA ); + floatToFixed_arrL( hCPE->hStereoClassif->unclr_fv, hCPE->hStereoClassif->unclr_fv_fx, 15, SSC_MAX_NFEA ); + f2me( hCPE->hStereoClassif->ave_ener_L, &hCPE->hStereoClassif->ave_ener_L_fx, &hCPE->hStereoClassif->ave_ener_L_fx_e ); + f2me( hCPE->hStereoClassif->ave_ener_R, &hCPE->hStereoClassif->ave_ener_R_fx, &hCPE->hStereoClassif->ave_ener_R_fx_e ); + f2me( hCPE->hStereoDft->hItd->currFlatness, &hCPE->hStereoDft->hItd->currFlatness_fx, &hCPE->hStereoDft->hItd->currFlatness_fx_e ); + +#ifndef MSAN_FIX + hCPE->hStereoClassif->xtalk_score_fx = floatToFixed( hCPE->hStereoClassif->xtalk_score, 31 ); +#endif // !MSAN_FIX + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_score_buf, hCPE->hStereoClassif->xtalk_score_buf_fx, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore_fx = floatToFixed( hCPE->hStereoClassif->xtalk_wscore, 31 ); + + /*flt2fix: dft_compute_prm*/ + floatToFixed_arrL( hCPE->hStereoDft->sidSideGain, hCPE->hStereoDft->sidSideGain_fx, Q31, STEREO_DFT_ERB4_BANDS ); + hCPE->hStereoDft->sid_gipd_fx = floatToFixed( hCPE->hStereoDft->sid_gipd, Q13 ); + + hCPE->hStereoClassif->relE_0_1_fx = floatToFixed( hCPE->hStereoClassif->relE_0_1, 31 ); + floatToFixed_arrL( hCPE->hStereoClassif->unclr_relE_0_1_LT, hCPE->hStereoClassif->unclr_relE_0_1_LT_fx, 31, UNCLR_RC_ORDER ); + hCPE->hStereoClassif->unclr_wscore_fx = floatToFixed( hCPE->hStereoClassif->unclr_wscore, 31 ); + + for ( i = 0; i < 2; i++ ) + { + f2me( hCPE->hStereoDft->nrg_L[i], &hCPE->hStereoDft->nrg_L_fx[i], &hCPE->hStereoDft->nrg_L_fx_e[i] ); + f2me( hCPE->hStereoDft->nrg_R[i], &hCPE->hStereoDft->nrg_R_fx[i], &hCPE->hStereoDft->nrg_R_fx_e[i] ); + f2me( hCPE->hStereoDft->nrg_DMX[i], &hCPE->hStereoDft->nrg_DMX_fx[i], &hCPE->hStereoDft->nrg_DMX_fx_e[i] ); + } + for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) + { + f2me( hCPE->hStereoDft->res_cod_NRG_M[i], &hCPE->hStereoDft->res_cod_NRG_M_fx[i], &hCPE->hStereoDft->res_cod_NRG_M_fx_e[i] ); + f2me( hCPE->hStereoDft->res_cod_NRG_S[i], &hCPE->hStereoDft->res_cod_NRG_S_fx[i], &hCPE->hStereoDft->res_cod_NRG_S_fx_e[i] ); + } + + /* flt2fix: to be removed */ + floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, 15, 3 ); + /* flt2fix end */ + + /*flt2fix: dft_synthesize*/ + if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + floatToFixed_arr( sts[1]->old_inp_12k8, sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); + } + f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); + f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); + /*flt2fix end*/ #endif +#ifdef IVAS_FLOAT_FIXED + stereo_dft_hybrid_ITD_flag( hCPE->hStereoDft->hConfig, input_Fs, hCPE->hStereoDft->hItd->hybrid_itd_max ); /* Time Domain ITD compensation using extrapolation */ stereo_td_itd_fx( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd_fx, hCPE->hStereoDft->q_input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); @@ -445,45 +501,13 @@ ivas_error ivas_cpe_enc( stereo_dft_enc_analyze( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT, hCPE->input_mem ); #endif - sts[0]->total_brate = ( sts[0]->bits_frame_nominal + 10 ) * FRAMES_PER_SEC; /* add small overhead; st[0]->total_brate used in coder_type_modif() */ + sts[0]->total_brate = L_mult0( add( sts[0]->bits_frame_nominal, 10 ), FRAMES_PER_SEC ); /* add small overhead; st[0]->total_brate used in coder_type_modif() */ /* Update DFT Stereo memories */ stereo_dft_enc_update_fx( hCPE->hStereoDft, sts[0]->max_bwidth ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - /* fix2flt: to be removed */ - fixedToFloat_arrL( hCPE->hStereoDft->side_gain_fx, hCPE->hStereoDft->side_gain, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); - fixedToFloat_arrL( hCPE->hStereoDft->gipd_fx, hCPE->hStereoDft->gipd, Q13, STEREO_DFT_ENC_DFT_NB ); - fixedToFloat_arrL( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoDft->hItd->itd, Q16, STEREO_DFT_ENC_DFT_NB ); - fixedToFloat_arrL( hCPE->hStereoDft->hItd->deltaItd_fx, hCPE->hStereoDft->hItd->deltaItd, Q16, STEREO_DFT_ENC_DFT_NB ); - - - FOR( int i = 0; i < CPE_CHANNELS; i++ ) - { - // fixedToFloat_arr( sts[i]->input_fx, sts[i]->input, sts[i]->q_inp, 1965 ); - // fixedToFloat_arr(sts[i]->old_input_signal_fx, sts[i]->old_input_signal, sts[i]->q_old_inp, 1965); - fixedToFloat_arr( &hCPE->input_mem_fx[i][0], &hCPE->input_mem[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); - // fixedToFloat_arrL( &hCPE->hStereoDft->DFT_fx[i][0], &hCPE->hStereoDft->DFT[i][0], hCPE->hStereoDft->DFT_q_fx[i], STEREO_DFT_N_MAX_ENC ); - me2f_buf( hCPE->hStereoDft->DFT_fx[i], hCPE->hStereoDft->DFT_fx_e[i], hCPE->hStereoDft->DFT[i], STEREO_DFT_N_MAX_ENC ); -#ifdef MSAN_FIX - IF( hCPE->hStereoDft->hItd->td_itd[STEREO_DFT_OFFSET] != 0 && EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) - { - fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], hCPE->hStereoDft->dft_ovl ); - } -#else - fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], STEREO_DFT_OVL_MAX ); -#endif // MSAN_FIX - } - /* fix2flt end */ -#endif /* DFT stereo processing */ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - /* flt2fix: to be removed */ - hCPE->hStereoDft->voicing_lt_fx = floatToFixed( hCPE->hStereoDft->voicing_lt, 31 ); - floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, 15, 3 ); - /* flt2fix end */ -#endif - stereo_dft_enc_process( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); + stereo_dft_enc_process_fx( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); } else if ( hCPE->element_mode == IVAS_CPE_TD ) { @@ -524,23 +548,6 @@ ivas_error ivas_cpe_enc( /* iDFT at input sampling rate */ #ifdef IVAS_FLOAT_FIXED - /*flt2fix*/ - f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); - f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); - if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) - { - floatToFixed_arr( sts[1]->old_inp_12k8, sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); - } - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); - /*flt2fix end*/ - // stereo_dft_enc_synthesize( hCPE->hStereoDft, sts[0]->input, 0, input_Fs, input_Fs, 0 ); Word16 out_start_ind, out_end_ind; Word16 out_12k8_start_ind[CPE_CHANNELS], out_12k8_end_ind[CPE_CHANNELS]; @@ -581,7 +588,63 @@ ivas_error ivas_cpe_enc( Copy_Scale_sig_32_16( old_inp_12k8_fx[1] + L_FRAME8k, sts[1]->old_inp_12k8_fx, L_INP_MEM, 0 - 16 ); } - /*fix2flt*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 i; + /* fix2flt: to be removed */ + fixedToFloat_arrL( hCPE->hStereoDft->side_gain_fx, hCPE->hStereoDft->side_gain, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); + fixedToFloat_arrL( hCPE->hStereoDft->gipd_fx, hCPE->hStereoDft->gipd, Q13, STEREO_DFT_ENC_DFT_NB ); + + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + // fixedToFloat_arr( sts[i]->input_fx, sts[i]->input, sts[i]->q_inp, 1965 ); + // fixedToFloat_arr(sts[i]->old_input_signal_fx, sts[i]->old_input_signal, sts[i]->q_old_inp, 1965); + fixedToFloat_arr( &hCPE->input_mem_fx[i][0], &hCPE->input_mem[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + me2f_buf( hCPE->hStereoDft->DFT_fx[i], hCPE->hStereoDft->DFT_fx_e[i], hCPE->hStereoDft->DFT[i], STEREO_DFT_N_MAX_ENC ); +#ifdef MSAN_FIX + IF( hCPE->hStereoDft->hItd->td_itd[STEREO_DFT_OFFSET] != 0 && EQ_16( sts[0]->element_mode, IVAS_CPE_DFT ) ) + { + fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], hCPE->hStereoDft->dft_ovl ); + } +#else + fixedToFloat_arr( &hCPE->hStereoDft->input_mem_itd_fx[i][0], &hCPE->hStereoDft->input_mem_itd[i][0], hCPE->hStereoDft->q_input_mem_itd[i], STEREO_DFT_OVL_MAX ); +#endif // MSAN_FIX + } + /* fix2flt end */ + + + /*fix2flt: dft_td_itd*/ + me2f_buf( hCPE->hStereoDft->xspec_smooth_fx, hCPE->hStereoDft->xspec_smooth_fx_e, hCPE->hStereoDft->xspec_smooth, STEREO_DFT_N_32k_ENC ); + me2f_buf( hCPE->hStereoDft->Spd_L_smooth_fx, hCPE->hStereoDft->Spd_L_smooth_fx_e, hCPE->hStereoDft->Spd_L_smooth, STEREO_DFT_N_32k_ENC / 2 ); + me2f_buf( hCPE->hStereoDft->Spd_R_smooth_fx, hCPE->hStereoDft->Spd_R_smooth_fx_e, hCPE->hStereoDft->Spd_R_smooth, STEREO_DFT_N_32k_ENC / 2 ); + fixedToFloat_arrL( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoDft->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, 15, SSC_MAX_NFEA ); + fixedToFloat_arrL( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, 15, SSC_MAX_NFEA ); + hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); + hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); + hCPE->hStereoClassif->xtalk_score = fixedToFloat( hCPE->hStereoClassif->xtalk_score_fx, 31 ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_score_buf_fx, hCPE->hStereoClassif->xtalk_score_buf, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore = fixedToFloat( hCPE->hStereoClassif->xtalk_wscore_fx, 31 ); + + fixedToFloat_arrL( hCPE->hStereoDft->sidSideGain_fx, hCPE->hStereoDft->sidSideGain, Q31, STEREO_DFT_ERB4_BANDS ); + hCPE->hStereoDft->sid_gipd = fixedToFloat( hCPE->hStereoDft->sid_gipd_fx, Q13 ); + /*local fix2flt*/ + + fixedToFloat_arrL( hCPE->hStereoClassif->unclr_relE_0_1_LT_fx, hCPE->hStereoClassif->unclr_relE_0_1_LT, 31, UNCLR_RC_ORDER ); + hCPE->hStereoClassif->unclr_wscore = fixedToFloat( hCPE->hStereoClassif->unclr_wscore_fx, 31 ); + + for ( i = 0; i < 2; i++ ) + { + hCPE->hStereoDft->nrg_L[i] = me2f( hCPE->hStereoDft->nrg_L_fx[i], hCPE->hStereoDft->nrg_L_fx_e[i] ); + hCPE->hStereoDft->nrg_R[i] = me2f( hCPE->hStereoDft->nrg_R_fx[i], hCPE->hStereoDft->nrg_R_fx_e[i] ); + hCPE->hStereoDft->nrg_DMX[i] = me2f( hCPE->hStereoDft->nrg_DMX_fx[i], hCPE->hStereoDft->nrg_DMX_fx_e[i] ); + } + for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) + { + hCPE->hStereoDft->res_cod_NRG_M[i] = me2f( hCPE->hStereoDft->res_cod_NRG_M_fx[i], hCPE->hStereoDft->res_cod_NRG_M_fx_e[i] ); + hCPE->hStereoDft->res_cod_NRG_S[i] = me2f( hCPE->hStereoDft->res_cod_NRG_S_fx[i], hCPE->hStereoDft->res_cod_NRG_S_fx_e[i] ); + } + + /*fix2flt: dft_synthesize*/ hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); fixedToFloat_arrL( sts[0]->input32_fx + out_start_ind, sts[0]->input + out_start_ind, 16, out_end_ind - out_start_ind ); @@ -599,6 +662,7 @@ ivas_error ivas_cpe_enc( fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); /*fix2flt end*/ +#endif #else stereo_dft_enc_synthesize( hCPE->hStereoDft, sts[0]->input, 0, input_Fs, input_Fs, 0 ); @@ -1859,6 +1923,9 @@ ivas_error create_cpe_enc( } stereo_classifier_init( hCPE->hStereoClassif ); +#ifdef IVAS_FLOAT_FIXED + stereo_classifier_init_fx( hCPE->hStereoClassif ); +#endif /*-----------------------------------------------------------------* * Metadata: allocate and initialize diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index f1fcdc80a..e291f7e04 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -672,8 +672,7 @@ void ivas_mdct_core_whitening_enc( st->currEnergyHF_e_fx = sub( Q31, q_com ); IF( st->hTranDet ) { - st->hTranDet->subblockEnergies.q_subblockNrgChange = L_get_q_buf1( st->hTranDet->subblockEnergies.subblockNrgChange_flt, NSUBBLOCKS + MAX_TD_DELAY ); - floatToFixed_arrL32( st->hTranDet->subblockEnergies.subblockNrgChange_flt, st->hTranDet->subblockEnergies.subblockNrgChange_32, st->hTranDet->subblockEnergies.q_subblockNrgChange, NSUBBLOCKS + MAX_TD_DELAY ); + floatToFixed_arr( st->hTranDet->subblockEnergies.subblockNrgChange_flt, st->hTranDet->subblockEnergies.subblockNrgChange, Q15 - NRG_CHANGE_E, NSUBBLOCKS + MAX_TD_DELAY ); } IF( st->hTcxEnc ) { diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index a07346292..b318fd695 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -74,21 +74,42 @@ const int16_t unclr_isel_dft[SIZE_UNCLR_ISEL_DFT] = }; /* UNCLR classifier in DFT stereo: mean & scale for normalization */ +#ifdef IVAS_FLOAT_FIXED +const Word32 unclr_mean_dft_Q15[SIZE_UNCLR_ISEL_DFT] = +{ + 13920, -152730, 17610, 792661, 1153203, 90241, -106132544, 9412 +}; +#else const float unclr_mean_dft[SIZE_UNCLR_ISEL_DFT] = { 0.424806f, -4.660972f, 0.537442f, 24.190099f, 35.192984f, 2.753954f, -3238.908177f, 0.287240f }; +#endif +#ifdef IVAS_FLOAT_FIXED +const Word32 unclr_scale_dft_Q15[SIZE_UNCLR_ISEL_DFT] = +{ + 11084, 110512, 17867, 97544, 2400784, 106505, 9133285, 7412 +}; +#else const float unclr_scale_dft[SIZE_UNCLR_ISEL_DFT] = { 0.338259f, 3.372571f, 0.545282f, 2.976819f, 73.266110f, 3.250287f, 278.725735f, 0.226197f }; +#endif /* UNCLR classifier in DFT stereo: classifier parameters for logistic regression */ +#ifdef IVAS_FLOAT_FIXED +const Word32 unclr_coef_dft_Q28[SIZE_UNCLR_ISEL_DFT] = +{ + 122724664, -426667424, -93744376, -365534720, 1127074816, 406588992, -220729920, -818419200 +}; +#else const float unclr_coef_dft[SIZE_UNCLR_ISEL_DFT] = { 0.457185f, -1.589460f, -0.349225f, -1.361723f, 4.198681f, 1.514662f, -0.822283f, -3.048849f }; +#endif /* xtalk clasifier in TD stereo: list of selected features */ const int16_t xtalk_isel_td[SIZE_XTALK_ISEL_TD] = diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index d7479f70a..6b6fa1c78 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -62,9 +62,15 @@ extern const float xtalk_coef_dft[]; extern const Word32 xtalk_coef_dft_q30[]; extern const int16_t unclr_isel_dft[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 unclr_mean_dft_Q15[]; +extern const Word32 unclr_scale_dft_Q15[]; +extern const Word32 unclr_coef_dft_Q28[]; +#else extern const float unclr_mean_dft[]; extern const float unclr_scale_dft[]; extern const float unclr_coef_dft[]; +#endif /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 5ae9a546e..8fb7d7114 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -239,7 +239,7 @@ typedef struct stereo_dft_enc_data_struct float sid_gipd; int16_t coh_fade_counter; float prev_sid_gipd; - Word32 prev_sid_gipd_fx; + Word32 prev_sid_gipd_fx; // Q13 int16_t prev_sid_no_ipd_flag; /*IPD*/ @@ -324,7 +324,8 @@ typedef struct stereo_dft_enc_data_struct Word16 lbEner_fx_e; #endif int16_t flip_sign; - Word32 dmx_res_all_prev_fx; /* energy of the previous frame Q31*/ + Word32 dmx_res_all_prev_fx; /* energy of the previous frame Q(31 - dmx_res_all_prev_fx_e) */ + Word16 dmx_res_all_prev_fx_e; /* energy of the previous frame */ Word16 switch_fade_factor_fx; /* Adaptive fade factor for switch frame Q15*/ Word32 res_dmx_ratio_lt_fx; /* long term energy ratio between RES and DMX Q31*/ Word32 pre_sub_nrg_DMX_fx[STEREO_DFT_BAND_MAX]; // Q(31 - pre_sub_nrg_DMX_fx_e[]) @@ -335,9 +336,12 @@ typedef struct stereo_dft_enc_data_struct Word16 diff_r_h_sm_fx_e; Word32 prev_fac2_fx; // Q31 Word32 res_pred_gain_f_fx[STEREO_DFT_BAND_MAX]; // Q31 - Word32 nrg_L_fx[2]; - Word32 nrg_R_fx[2]; - Word32 nrg_DMX_fx[2]; + Word32 nrg_L_fx[2]; // Q(31 - nrg_L_fx_e[]) + Word16 nrg_L_fx_e[2]; + Word32 nrg_R_fx[2]; // Q(31 - nrg_R_fx_e[]) + Word16 nrg_R_fx_e[2]; + Word32 nrg_DMX_fx[2]; // Q(31 - nrg_DMX_fx_e[]) + Word16 nrg_DMX_fx_e[2]; Word32 res_pred_gain_fx[STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX]; /*prediction gain for the residual HFs */ /* Q31 */ Word32 gainIPD_sm_fx; /* long-term gain IPD for NIPD detection */ // Q31 Word32 sfm_fx; // Q31 @@ -380,9 +384,12 @@ typedef struct stereo_dft_enc_data_struct Word32 output_mem_res_8k_fx[STEREO_DFT_OVL_8k]; // Q16 - Word32 res_cod_NRG_M_fx[STEREO_DFT_BAND_MAX]; - Word32 res_cod_NRG_S_fx[STEREO_DFT_BAND_MAX]; - Word32 res_cod_SNR_M_fx[STEREO_DFT_BAND_MAX]; + Word32 res_cod_NRG_M_fx[STEREO_DFT_BAND_MAX]; // Q(31 - res_cod_NRG_M_fx_e[]) + Word16 res_cod_NRG_M_fx_e[STEREO_DFT_BAND_MAX]; + Word32 res_cod_NRG_S_fx[STEREO_DFT_BAND_MAX]; // Q(31 - res_cod_NRG_S_fx_e[]) + Word16 res_cod_NRG_S_fx_e[STEREO_DFT_BAND_MAX]; + Word32 res_cod_SNR_M_fx[STEREO_DFT_BAND_MAX]; // Q(31 - res_cod_SNR_M_fx_e[]) + Word16 res_cod_SNR_M_fx_e[STEREO_DFT_BAND_MAX]; Word32 old_snr_fx; Word32 past_nrgL_fx[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; // Q(31 - past_nrgL_fx_e[]) Word16 past_nrgL_fx_e[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; @@ -693,7 +700,7 @@ typedef struct ivas_stereo_classifier_data_structure Word32 ps_diff_ch1_fx, ps_diff_ch2_fx; float ps_sta_ch1, ps_sta_ch2; float prev_g_IPD; - float prev_IPD; // Q29 + float prev_IPD; float prev_ratio_m1_m2; float ratio_L; Word16 vad_flag_glob; @@ -745,18 +752,18 @@ typedef struct ivas_stereo_classifier_data_structure Word32 prev_IPD_fx; // Q29 Word32 prev_ratio_m1_m2_fx; // Q31 Word32 ratio_L_fx; - Word32 ave_ener_L_fx; /* average energy of the L channel */ - Word16 ave_ener_L_fx_e; /* average energy of the L channel */ - Word32 ave_ener_R_fx; /* average energy of the R channel */ - Word16 ave_ener_R_fx_e; /* average energy of the R channel */ - Word32 Etot_dn_fx; /* average energy in dB - lower bound */ - Word32 Etot_up_fx; /* average energy in dB - upper bound */ - Word32 relE_buf_fx[UNCLR_L_RELE]; /* running buffer for relative energy */ - Word32 Etot_buf_fx[UNCLR_L_ETOT]; /* running buffer for average energy in dB */ - Word32 relE_0_1_fx; /* relative energy in the current frame normalized to (0,1) */ - Word32 relE_0_1_LT_fx; - Word32 unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER]; - Word32 unclr_wscore_fx; + Word32 ave_ener_L_fx; /* average energy of the L channel Q(31-ave_ener_L_fx_e) */ + Word16 ave_ener_L_fx_e; /* average energy of the L channel */ + Word32 ave_ener_R_fx; /* average energy of the R channel Q(31-ave_ener_R_fx_e) */ + Word16 ave_ener_R_fx_e; /* average energy of the R channel */ + Word32 Etot_dn_fx; /* average energy in dB - lower bound */ + Word32 Etot_up_fx; /* average energy in dB - upper bound */ + Word32 relE_buf_fx[UNCLR_L_RELE]; /* running buffer for relative energy Q31 */ + Word32 Etot_buf_fx[UNCLR_L_ETOT]; /* running buffer for average energy in dB */ + Word32 relE_0_1_fx; /* relative energy in the current frame normalized to (0,1) Q31 */ + Word32 relE_0_1_LT_fx; // Q31 + Word32 unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER]; // Q31 + Word32 unclr_wscore_fx; // Q31 Word32 unclr_fv_fx[SSC_MAX_NFEA]; /* UNCLR - feature vector */ // Q15 Word32 xtalk_score_buf_fx[XTALK_SCORE_BUF_LEN]; // Q31 Word32 xtalk_fv_fx[SSC_MAX_NFEA]; /* xtalk - feature vector */ // Q15 diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 9f1275e97..1d5624037 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -49,7 +49,9 @@ *-------------------------------------------------------------------*/ #define RC_FACT_UP 0.3f +#define RC_FACT_UP_Q31 644245094 #define RC_FACT_DOWN 0.7f +#define RC_FACT_DOWN_Q31 1503238554 #define UNCLR_SCORE_THR 4.0f #define XTALK_SCORE_THR_DFT 4.0f #define XTALK_SCORE_THR_DFT_Q27 ( 1 << 29 ) @@ -58,6 +60,7 @@ #define UNCLR_INTERCEPT_TD 0.780313f #define UNCLR_INTERCEPT_DFT 1.226513f +#define UNCLR_INTERCEPT_DFT_Q30 1316958306 #define XTALK_INTERCEPT_TD -1.770983f #define XTALK_INTERCEPT_DFT -0.758556f #define XTALK_INTERCEPT_DFT_Q31 -1628986606 @@ -73,6 +76,7 @@ * Local function prototypes *-------------------------------------------------------------------*/ +static void rc_filter_fx( const Word32 x, Word32 *y, const Word16 order, const Word32 tau ); static void rc_filter( const float x, float *y, const int16_t order, const float tau ); static void edge_detect( const float *inp, const int16_t len, const float inp_min, const float inp_max, float *edge_str, int16_t *edge_type ); @@ -192,6 +196,9 @@ int16_t select_stereo_mode( /* reset stereo classifier when switching from MDCT stereo to Unified stereo */ stereo_classifier_init( hCPE->hStereoClassif ); +#ifdef IVAS_FLOAT_FIXED + stereo_classifier_init_fx( hCPE->hStereoClassif ); +#endif hStereoClassif->lrtd_mode = lrtd_mode; } @@ -300,63 +307,102 @@ void stereo_classifier_init_fx( { /* initialization of features for xtalk classifier and UNCLR classifier */ hStereoClassif->clas_ch1 = 0; + move16(); set16_fx( hStereoClassif->pitch_ch1, 0, 3 ); set_zero_fx( hStereoClassif->voicing_ch1_fx, 3 ); hStereoClassif->cor_map_sum_ch1_fx = 0; + move32(); set_zero_fx( hStereoClassif->lsf_ch1_fx, M ); hStereoClassif->lepsP_ch1_fx = 0; + move32(); hStereoClassif->dE1_ch1_fx = 0; + move32(); hStereoClassif->dE1_ch2_fx = 0; + move32(); hStereoClassif->nchar_ch1_fx = 0; + move32(); hStereoClassif->nchar_ch2_fx = 0; + move32(); hStereoClassif->non_sta_ch1_fx = 0; + move32(); hStereoClassif->sp_div_ch1_fx = 0; + move32(); hStereoClassif->ps_diff_ch1_fx = 0; + move32(); hStereoClassif->ps_diff_ch2_fx = 0; + move32(); hStereoClassif->ps_sta_ch1_fx = 0; + move32(); hStereoClassif->ps_sta_ch2_fx = 0; - hStereoClassif->prev_g_IPD_fx = 1073741824; // Q31 + move32(); + hStereoClassif->prev_g_IPD_fx = ONE_IN_Q28; // 0.5f in Q29 + move32(); hStereoClassif->prev_IPD_fx = 0; + move32(); hStereoClassif->prev_ratio_m1_m2_fx = 0; + move32(); set_zero_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN ); hStereoClassif->ratio_L_fx = 1073741824; // Q31 - hStereoClassif->vad_flag_glob = 0; // Q31 - hStereoClassif->vad_relE = 0; // Q31 - hStereoClassif->is_speech_fx = 0; // Q31 + move32(); + hStereoClassif->vad_flag_glob = 0; + move16(); + hStereoClassif->vad_relE = 0; + move16(); + hStereoClassif->is_speech_fx = 0; // Q31 + move32(); set16_fx( hStereoClassif->aEn_raw, 0, CPE_CHANNELS ); hStereoClassif->Etot_dn_fx = 0; + move32(); hStereoClassif->Etot_up_fx = 0; + move32(); set_zero_fx( hStereoClassif->relE_buf_fx, UNCLR_L_RELE ); set_zero_fx( hStereoClassif->Etot_buf_fx, UNCLR_L_ETOT ); set_zero_fx( hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER ); hStereoClassif->unclr_sw_enable_cnt[0] = 0; + move16(); hStereoClassif->unclr_sw_enable_cnt[1] = 0; + move16(); hStereoClassif->unclr_decision = 0; + move16(); hStereoClassif->unclr_wscore_fx = 0; + move32(); - set32_fx( hStereoClassif->unclr_fv_fx, -2147483647 - 1, SSC_MAX_NFEA ); // Q31 + set32_fx( hStereoClassif->unclr_fv_fx, -32768, SSC_MAX_NFEA ); // Q15 hStereoClassif->unclr_corrLagMax_prev = 0; + move16(); hStereoClassif->ave_ener_L_fx = 0; + move32(); hStereoClassif->ave_ener_L_fx_e = 0; + move16(); hStereoClassif->ave_ener_R_fx = 0; + move32(); hStereoClassif->ave_ener_R_fx_e = 0; - hStereoClassif->relE_0_1_fx = 21474836; // Q31 - hStereoClassif->relE_0_1_LT_fx = 21474836; // Q31 + move16(); + hStereoClassif->relE_0_1_fx = 21474836; // 0.01f in Q31 + move32(); + hStereoClassif->relE_0_1_LT_fx = 21474836; // 0.01f in Q31 + move32(); - set32_fx( hStereoClassif->xtalk_fv_fx, -2147483647 - 1, SSC_MAX_NFEA ); // Q31 + set32_fx( hStereoClassif->xtalk_fv_fx, -32768, SSC_MAX_NFEA ); // Q15 hStereoClassif->xtalk_wscore_fx = 0; + move32(); hStereoClassif->xtalk_decision = 0; + move16(); hStereoClassif->xtalk_score_wrelE_fx = 0; + move32(); hStereoClassif->lrtd_mode = 0; + move16(); hStereoClassif->prev_lrtd_mode = 0; + move16(); hStereoClassif->silence_flag = 0; + move16(); return; } @@ -680,7 +726,103 @@ void unclr_classifier_td( * * Classifies current DFT frame as uncorrelated L/R (1) or normal stereo (0) *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void unclr_classifier_dft_fx( + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +) +{ + Word16 i, ind; + Word16 edge, edge_0_1; + Word32 relE_ST; + Word32 score, fvn[SSC_MAX_NFEA]; + Word16 score_e, fvn_e[SSC_MAX_NFEA]; + + STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif; + + /* calculate raw score based on LR */ + score = UNCLR_INTERCEPT_DFT_Q30; + move32(); + score_e = 1; + move16(); + FOR( i = 0; i < SIZE_UNCLR_ISEL_DFT; i++ ) + { + ind = unclr_isel_dft[i]; + move16(); + + /* mean & std removal */ + // fvn[i] = (hStereoClassif->unclr_fv[ind] - unclr_mean_dft[i]) / unclr_scale_dft[i]; + fvn[i] = BASOP_Util_Divide3232_Scale_cadence( L_sub( hStereoClassif->unclr_fv_fx[ind], unclr_mean_dft_Q15[i] ), unclr_scale_dft_Q15[i], &fvn_e[i] ); + move32(); + + /* LR */ + // score += fvn[i] * unclr_coef_dft[i]; + score = BASOP_Util_Add_Mant32Exp( score, score_e, Mpy_32_32( fvn[i], unclr_coef_dft_Q28[i] ), add( fvn_e[i], 3 ), &score_e ); + } + + + /* normalize score to -1:+1 */ + /*if (score > UNCLR_SCORE_THR) + { + score = UNCLR_SCORE_THR; + } + else if (score < -UNCLR_SCORE_THR) + { + score = -UNCLR_SCORE_THR; + } + score /= 2 * UNCLR_SCORE_THR;*/ + score = L_shr_r_sat( score, sub( 3, score_e ) ); // Q31 + + /* weight raw score with relative energy */ + // score *= hStereoClassif->relE_0_1; + score = Mpy_32_32( score, hStereoClassif->relE_0_1_fx ); // Q31 + + if ( !hStereoClassif->vad_flag_glob ) + { + score = 0; + move32(); + } + + /* rising edge detector on relE */ + // relE_ST = mean(hStereoClassif->relE_buf, UNCLR_L_RELE); + relE_ST = Mean32( hStereoClassif->relE_buf_fx, UNCLR_L_RELE ); // Q31 + IF( GT_32( hStereoClassif->relE_0_1_fx, relE_ST ) ) + { + // rc_filter(hStereoClassif->relE_0_1, hStereoClassif->unclr_relE_0_1_LT, UNCLR_RC_ORDER, RC_FACT_UP); + rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_UP_Q31 ); + } + ELSE + { + // rc_filter(hStereoClassif->relE_0_1, hStereoClassif->unclr_relE_0_1_LT, UNCLR_RC_ORDER, RC_FACT_DOWN); + rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_DOWN_Q31 ); + } + + // edge = hStereoClassif->relE_0_1 - hStereoClassif->unclr_relE_0_1_LT[UNCLR_RC_ORDER - 1]; + edge = extract_h( L_sub( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER - 1] ) ); // Q15 + // edge_0_1 = lin_interp(edge, 0.0f, 0.95f, 1.0f, 0.9f, 1); + edge_0_1 = lin_interp_ivas_fx( edge, 0, 31129 /*0.95f*/, MAX_16, 29491 /*0.9f*/, 1 ); + /* LT average */ + // hStereoClassif->unclr_wscore = edge_0_1 * hStereoClassif->unclr_wscore + (1 - edge_0_1) * score; + hStereoClassif->unclr_wscore_fx = L_add( Mpy_32_16_1( hStereoClassif->unclr_wscore_fx, edge_0_1 ), Mpy_32_16_1( score, sub( MAX_16, edge_0_1 ) ) ); // Q31 + move32(); + + /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */ + // if (((hStereoClassif->unclr_decision == 0 && hStereoClassif->unclr_wscore > 0.1f) || (hStereoClassif->unclr_decision == 1 && hStereoClassif->unclr_wscore < -0.07f)) && (hStereoClassif->unclr_sw_enable_cnt[0] > 0)) + test(); + test(); + test(); + test(); + if ( ( ( hStereoClassif->unclr_decision == 0 && GT_32( hStereoClassif->unclr_wscore_fx, 214748365 /*0.1f*/ ) ) || ( EQ_16( hStereoClassif->unclr_decision, 1 ) && LT_32( hStereoClassif->unclr_wscore_fx, -150323855 /*-0.07f*/ ) ) ) && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 ) ) + { + /* let's switch the binary decision */ + hStereoClassif->unclr_decision = !hStereoClassif->unclr_decision; + move16(); + } + + + return; +} +#else void unclr_classifier_dft( CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ) @@ -751,7 +893,7 @@ void unclr_classifier_dft( return; } - +#endif /*-------------------------------------------------------------------* * Function xtalk_classifier_td() @@ -1261,7 +1403,26 @@ void xtalk_classifier_dft( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void rc_filter_fx( + const Word32 x, // Q31 + Word32 *y, // Q31 + const Word16 order, + const Word32 tau ) // Q31 +{ + Word16 i; + + y[0] = L_add( Mpy_32_32( tau, y[0] ), Mpy_32_32( L_sub( MAX_32, tau ), x ) ); + move32(); + FOR( i = 1; i < order; i++ ) + { + y[i] = L_add( Mpy_32_32( tau, y[i] ), Mpy_32_32( L_sub( MAX_32, tau ), y[i - 1] ) ); + move32(); + } + return; +} +#endif static void rc_filter( const float x, float *y, diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index 2dddb2bd1..f294a3081 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -137,10 +137,31 @@ static void side_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int1 static void res_pred_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int16_t encoded_ind_pred_GR[], const int16_t k_offset, const int32_t last_core_brate ); +#ifdef IVAS_FLOAT_FIXED +static void stereo_dft_enc_calculate_nrg_for_icbwe_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ + const Word16 *DFT_L_e, + const Word16 *DFT_R_e, + const Word32 *DMX, /* i : DFT Stereo downmix Q(31-DMX_e[]) */ + const Word16 *DMX_e, /* i : DFT Stereo downmix */ + const Word32 input_Fs /* i : input sampling rate */ +); +#else static void stereo_dft_enc_calculate_nrg_for_icbwe( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, const float *DMX, const int32_t input_Fs ); +#endif +#ifdef IVAS_FLOAT_FIXED +static void stereo_dft_enc_get_res_cod_mode_flag_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, + const Word32 res_nrg_all_curr, + const Word16 res_nrg_all_curr_e, + const Word32 dmx_nrg_all_curr, + const Word16 dmx_nrg_all_curr_e, + Word32 *res_dmx_ratio, // Q31 + Word32 *frame_nrg_ratio ); // Q28 +#else static void stereo_dft_enc_get_res_cod_mode_flag( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, const float res_nrg_all_curr, const float dmx_nrg_all_curr, float *res_dmx_ratio, float *frame_nrg_ratio ); - +#endif /*------------------------------------------------------------------------- * stereo_dft_quantize_res_gains() @@ -1086,8 +1107,12 @@ void stereo_dft_enc_reset_fx( { hStereoDft->res_cod_NRG_M_fx[i] = 0; move32(); + hStereoDft->res_cod_NRG_M_fx_e[i] = 0; + move16(); hStereoDft->res_cod_NRG_S_fx[i] = 0; move32(); + hStereoDft->res_cod_NRG_S_fx_e[i] = 0; + move16(); } hStereoDft->old_snr_fx = 0; move32(); @@ -2523,60 +2548,53 @@ float stereo_dft_enc_synthesize( * 2) Mid/Side computation *-------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -void stereo_dft_enc_process( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const int16_t vad_flag_dtx[], /* i : VAD dtx flags */ - const int16_t vad_hover_flag[], /* i : VAD hangover flags */ - const int16_t input_frame /* i : input frame length */ +void stereo_dft_enc_process_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : input frame length */ ) { - int16_t i, j, b; - float *pDFT_L, *pDFT_R; -#ifdef IVAS_FLOAT_FIXED + Word16 i, j, b; Word32 *pDFT_L_fx, *pDFT_R_fx; -#endif - float *pDFT_DMX; - float *pDFT_RES; - int16_t k_offset; - float *pgIpd; - float *pSideGain; - float c /*, alpha*/, g; - Word16 c_fx, alpha_fx /*Q13*/ /*, g_fx*/; - float wL, wR, wS; - float tmp; + Word32 *pDFT_DMX; + Word32 *pDFT_RES; + Word16 k_offset; + Word32 *pgIpd; + Word32 *pSideGain; + Word16 c_fx /*Q15*/, alpha_fx /*Q13*/; + Word32 g_fx; // Q31 + Word32 wL, wR; + Word16 wL_e, wR_e; + Word16 wS; Word16 tmp_fx; Word32 tmp_32fx; - float s /*, c1, s1*/; - Word16 s_fx, c1_fx, s1_fx; - float fac_att; - Word16 fac_att_fx; + Word16 s_fx /*Q15*/, c1_fx /*Q15*/, s1_fx /*Q15*/; + Word16 fac_att_fx; // Q15 STEREO_DFT_ENC_DATA_HANDLE hStereoDft; - float DFT_DMX[STEREO_DFT_N_MAX_ENC]; - float DFT_RES[STEREO_DFT_N_8k_ENC]; - int32_t input_Fs; - float bin_nrgL[STEREO_DFT_N_MAX_ENC]; -#ifdef IVAS_FLOAT_FIXED + Word32 DFT_DMX[STEREO_DFT_N_MAX_ENC]; + Word16 DFT_DMX_e[STEREO_DFT_N_MAX_ENC]; + Word32 DFT_RES[STEREO_DFT_N_8k_ENC]; + Word16 DFT_RES_e[STEREO_DFT_N_8k_ENC]; + Word32 input_Fs; Word32 bin_nrgL_fx[STEREO_DFT_N_MAX_ENC]; Word16 bin_nrgL_fx_e[STEREO_DFT_N_MAX_ENC]; -#endif - float bin_nrgR[STEREO_DFT_N_MAX_ENC]; -#ifdef IVAS_FLOAT_FIXED Word32 bin_nrgR_fx[STEREO_DFT_N_MAX_ENC]; Word16 bin_nrgR_fx_e[STEREO_DFT_N_MAX_ENC]; -#endif - float *pNrgL, *pNrgR; - float res_nrg_all_curr, dmx_nrg_all_curr; - float res_dmx_ratio, frame_nrg_ratio; + Word32 *pNrgL, *pNrgR; + Word32 res_nrg_all_curr, dmx_nrg_all_curr; + Word16 res_nrg_all_curr_e, dmx_nrg_all_curr_e; + Word32 res_dmx_ratio /*Q31*/, frame_nrg_ratio /*Q28*/; Word32 dot_prod_nrg_ratio_fx[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands Q31 */ Word16 dot_prod_nrg_ratio_fx_e[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands Q31 */ - float dot_prod_nrg_ratio[STEREO_DFT_BAND_MAX]; /* contains only dot product for higher bands */ - float sum_nrg_L2, sum_nrg_R2, dot_prod_real2; - float sum_nrg_Mid, sum_abs; + Word32 sum_nrg_L2, sum_nrg_R2, dot_prod_real2; + Word16 sum_nrg_L2_e, sum_nrg_R2_e, dot_prod_real2_e; + Word32 sum_nrg_Mid, sum_abs; + Word16 sum_nrg_Mid_e, sum_abs_e; Word16 tmp_e; - /*Word64 W_tmp; - Word16 W_shift;*/ - Word32 DFT_L_tmp[STEREO_DFT_N_MAX_ENC], DFT_R_tmp[STEREO_DFT_N_MAX_ENC]; Word16 DFT_L_e_tmp[STEREO_DFT_N_MAX_ENC], DFT_R_e_tmp[STEREO_DFT_N_MAX_ENC]; + Word32 L_tmp1, L_tmp2, L_tmp3; + Word16 L_tmp1_e, L_tmp2_e, L_tmp3_e; /*------------------------------------------------------------------* * Initialization @@ -2587,41 +2605,52 @@ void stereo_dft_enc_process( hStereoDft = hCPE->hStereoDft; wL = 0; /* avoid compilation warning */ + move32(); + wL_e = 0; /* avoid compilation warning */ + move16(); wR = 0; /* avoid compilation warning */ + move32(); + wR_e = 0; /* avoid compilation warning */ + move16(); /* Initialization */ k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ + move16(); hStereoDft->gipd_band_max = dft_band_ipd[1][3]; + move16(); hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->res_cod_mode[k_offset]]; + move16(); // hStereoDft->res_cod_line_max = (int16_t) ( 0.5f + ( hStereoDft->band_limits[hStereoDft->res_cod_band_max] - 1 ) * 2.f * input_frame / (float) ( hStereoDft->NFFT ) ); tmp_32fx = L_shl( L_mult0( sub( hStereoDft->band_limits[hStereoDft->res_cod_band_max], 1 ), input_frame ), 1 ); tmp_32fx = BASOP_Util_Divide3216_Scale( tmp_32fx, hStereoDft->NFFT, &tmp_e ); hStereoDft->res_cod_line_max = extract_l( L_shr_r( tmp_32fx, sub( 31, tmp_e ) ) ); + move16(); + // hStereoDft->res_cod_line_max = 8 * (hStereoDft->res_cod_line_max / 8); hStereoDft->res_cod_line_max = shl( shr( hStereoDft->res_cod_line_max, 3 ), 3 ); + move16(); hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); - + move16(); // hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[0]; // hStereoDft->voicing_lt = 0.75f * hStereoDft->voicing_lt + 0.25f * hCPE->hCoreCoder[0]->voicing[1]; hStereoDft->voicing_lt_fx = L_add( Mpy_32_16_1( hStereoDft->voicing_lt_fx, 24576 ), L_mult( 8192, hCPE->hCoreCoder[0]->voicing_fx[0] ) ); + move32(); hStereoDft->voicing_lt_fx = L_add( Mpy_32_16_1( hStereoDft->voicing_lt_fx, 24576 ), L_mult( 8192, hCPE->hCoreCoder[0]->voicing_fx[1] ) ); + move32(); /*------------------------------------------------------------------* * Compute stereo parameters *-----------------------------------------------------------------*/ /*ITD in Frequency domain*/ - fac_att = 1.0f; + // fac_att = 1.0f; fac_att_fx = MAX_16; move16(); - pDFT_L = hStereoDft->DFT[0]; - pDFT_R = hStereoDft->DFT[1]; -#ifdef IVAS_FLOAT_FIXED - pDFT_L_fx = DFT_L_tmp; - pDFT_R_fx = DFT_R_tmp; + pDFT_L_fx = hStereoDft->DFT_fx[0]; + pDFT_R_fx = hStereoDft->DFT_fx[1]; #ifdef MSAN_FIX FOR( i = 0; i < hStereoDft->NFFT; i++ ) #else @@ -2639,64 +2668,10 @@ void stereo_dft_enc_process( DFT_R_e_tmp[i] = sub( hStereoDft->DFT_fx_e[1], tmp_e ); move16(); } -#endif - { -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - /*flt2fix*/ - hStereoDft->sfm_fx = floatToFixed( hStereoDft->sfm, 31 ); - f2me_buf( hStereoDft->xspec_smooth, hStereoDft->xspec_smooth_fx, &hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); - f2me_buf( hStereoDft->Spd_L_smooth, hStereoDft->Spd_L_smooth_fx, &hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); - f2me_buf( hStereoDft->Spd_R_smooth, hStereoDft->Spd_R_smooth_fx, &hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); - floatToFixed_arrL( hStereoDft->hItd->itd, hStereoDft->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); - floatToFixed_arrL( hStereoDft->hItd->deltaItd, hStereoDft->hItd->deltaItd_fx, 16, STEREO_DFT_ENC_DFT_NB ); - floatToFixed_arrL( hCPE->hStereoClassif->xtalk_fv, hCPE->hStereoClassif->xtalk_fv_fx, 15, SSC_MAX_NFEA ); - floatToFixed_arrL( hCPE->hStereoClassif->unclr_fv, hCPE->hStereoClassif->unclr_fv_fx, 15, SSC_MAX_NFEA ); - f2me( hCPE->hStereoClassif->ave_ener_L, &hCPE->hStereoClassif->ave_ener_L_fx, &hCPE->hStereoClassif->ave_ener_L_fx_e ); - f2me( hCPE->hStereoClassif->ave_ener_R, &hCPE->hStereoClassif->ave_ener_R_fx, &hCPE->hStereoClassif->ave_ener_R_fx_e ); - hStereoDft->hItd->prev_m1_fx = floatToFixed( hStereoDft->hItd->prev_m1, 31 ); - hStereoDft->hItd->prev_m2_fx = floatToFixed( hStereoDft->hItd->prev_m2, 31 ); - f2me( hStereoDft->hItd->currFlatness, &hStereoDft->hItd->currFlatness_fx, &hStereoDft->hItd->currFlatness_fx_e ); -#ifdef MSAN_FIX - hCPE->hStereoClassif->prev_IPD_fx = floatToFixed( hCPE->hStereoClassif->prev_IPD, Q29 ); - hCPE->hStereoClassif->prev_g_IPD_fx = floatToFixed( hCPE->hStereoClassif->prev_g_IPD, Q29 ); - hCPE->hStereoClassif->prev_ratio_m1_m2_fx = floatToFixed( hCPE->hStereoClassif->prev_ratio_m1_m2, Q31 ); -#endif - -#ifndef MSAN_FIX - hCPE->hStereoClassif->xtalk_score_fx = floatToFixed( hCPE->hStereoClassif->xtalk_score, 31 ); -#endif // !MSAN_FIX - floatToFixed_arrL( hCPE->hStereoClassif->xtalk_score_buf, hCPE->hStereoClassif->xtalk_score_buf_fx, 31, XTALK_SCORE_BUF_LEN ); - hCPE->hStereoClassif->xtalk_wscore_fx = floatToFixed( hCPE->hStereoClassif->xtalk_wscore, 31 ); -#endif + { stereo_dft_enc_compute_itd_fx( hCPE, pDFT_L_fx, DFT_L_e_tmp, pDFT_R_fx, DFT_R_e_tmp, k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL_fx, bin_nrgL_fx_e, bin_nrgR_fx, bin_nrgR_fx_e ); - /*fix2flt*/ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS -#ifdef MSAN_FIX - hCPE->hStereoClassif->prev_ratio_m1_m2 = fixedToFloat( hCPE->hStereoClassif->prev_ratio_m1_m2_fx, Q31 ); - hCPE->hStereoClassif->prev_IPD = fixedToFloat( hCPE->hStereoClassif->prev_IPD_fx, Q29 ); -#endif - hStereoDft->sfm = fixedToFloat( hStereoDft->sfm_fx, 31 ); - me2f_buf( hStereoDft->xspec_smooth_fx, hStereoDft->xspec_smooth_fx_e, hStereoDft->xspec_smooth, STEREO_DFT_N_32k_ENC ); - me2f_buf( hStereoDft->Spd_L_smooth_fx, hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_L_smooth, STEREO_DFT_N_32k_ENC / 2 ); - me2f_buf( hStereoDft->Spd_R_smooth_fx, hStereoDft->Spd_R_smooth_fx_e, hStereoDft->Spd_R_smooth, STEREO_DFT_N_32k_ENC / 2 ); - fixedToFloat_arrL( hStereoDft->hItd->itd_fx, hStereoDft->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); - fixedToFloat_arrL( hStereoDft->hItd->deltaItd_fx, hStereoDft->hItd->deltaItd, 16, STEREO_DFT_ENC_DFT_NB ); - fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, 15, SSC_MAX_NFEA ); - fixedToFloat_arrL( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, 15, SSC_MAX_NFEA ); - hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); - hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); - hStereoDft->hItd->prev_m1 = fixedToFloat( hStereoDft->hItd->prev_m1_fx, 31 ); - hStereoDft->hItd->prev_m2 = fixedToFloat( hStereoDft->hItd->prev_m2_fx, 31 ); - hCPE->hStereoClassif->xtalk_score = fixedToFloat( hCPE->hStereoClassif->xtalk_score_fx, 31 ); - fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_score_buf_fx, hCPE->hStereoClassif->xtalk_score_buf, 31, XTALK_SCORE_BUF_LEN ); - hCPE->hStereoClassif->xtalk_wscore = fixedToFloat( hCPE->hStereoClassif->xtalk_wscore_fx, 31 ); -#endif -#else - stereo_dft_enc_compute_itd( hCPE, pDFT_L, pDFT_R, k_offset, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL, bin_nrgR ); -#endif IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) { return; @@ -2796,273 +2771,509 @@ void stereo_dft_enc_process( } /* DFT stereo parameters */ - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arrL( hStereoDft->side_gain, hStereoDft->side_gain_fx, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); - floatToFixed_arrL( hStereoDft->sidSideGain, hStereoDft->sidSideGain_fx, Q31, STEREO_DFT_ERB4_BANDS ); - floatToFixed_arrL( hStereoDft->gipd, hStereoDft->gipd_fx, Q13, STEREO_DFT_ENC_DFT_NB ); -#endif stereo_dft_enc_compute_prm_fx( hStereoDft, pDFT_L_fx, DFT_L_e_tmp, pDFT_R_fx, DFT_R_e_tmp, k_offset, 1, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->vad_flag, bin_nrgL_fx, bin_nrgL_fx_e, bin_nrgR_fx, bin_nrgR_fx_e, dot_prod_nrg_ratio_fx, dot_prod_nrg_ratio_fx_e ); // printf("\n%f ", (float)hStereoDft->res_pred_gain_fx[0] / 0x7fffffff); - // printf("\n%f ", (float)hStereoDft->sum_dot_prod_img_fx / powf(2, 31 - hStereoDft->sum_dot_prod_img_fx_e)); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arrL( hStereoDft->side_gain_fx, hStereoDft->side_gain, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX ); - fixedToFloat_arrL( hStereoDft->sidSideGain_fx, hStereoDft->sidSideGain, Q31, STEREO_DFT_ERB4_BANDS ); - fixedToFloat_arrL( hStereoDft->gipd_fx, hStereoDft->gipd, Q13, STEREO_DFT_ENC_DFT_NB ); - /*local fix2flt*/ - FOR( i = 0; i < CPE_CHANNELS; i++ ) - { - me2f_buf( hCPE->hStereoDft->DFT_fx[i], hCPE->hStereoDft->DFT_fx_e[i], hCPE->hStereoDft->DFT[i], STEREO_DFT_N_MAX_ENC ); - } - for ( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) - { - bin_nrgL[i] = me2f( bin_nrgL_fx[i], bin_nrgL_fx_e[i] ); - bin_nrgR[i] = me2f( bin_nrgR_fx[i], bin_nrgR_fx_e[i] ); - } - hCPE->hStereoDft->voicing_lt = fixedToFloat( hCPE->hStereoDft->voicing_lt_fx, 31 ); - fac_att = fixedToFloat( fac_att_fx, 15 ); - for ( i = 0; i < STEREO_DFT_BAND_MAX; i++ ) - { - dot_prod_nrg_ratio[i] = me2f( dot_prod_nrg_ratio_fx[i], dot_prod_nrg_ratio_fx_e[i] ); - } - // fixedToFloat_arrL(dot_prod_nrg_ratio_fx, dot_prod_nrg_ratio, Q31, STEREO_DFT_ENC_DFT_NB * STEREO_DFT_BAND_MAX); - for ( i = 0; i < hStereoDft->NFFT; i++ ) - { - hStereoDft->DFT[0][i] = me2f( pDFT_L_fx[i], DFT_L_e_tmp[i] ); - hStereoDft->DFT[1][i] = me2f( pDFT_R_fx[i], DFT_R_e_tmp[i] ); - } -#endif + // printf("\n%f ", (float)hStereoDft->sum_dot_prod_img_fx / powf(2, 31 - hStereoDft->sum_dot_prod_img_fx_e - if ( vad_flag_dtx[0] == 0 ) + IF( vad_flag_dtx[0] == 0 ) { - if ( hCPE->hStereoCng->cng_counter == 0 && !hCPE->hStereoCng->first_SID_after_TD ) + test(); + IF( hCPE->hStereoCng->cng_counter == 0 && !hCPE->hStereoCng->first_SID_after_TD ) { - hStereoDft->sid_gipd = hStereoDft->prev_sid_gipd; + hStereoDft->sid_gipd_fx = hStereoDft->prev_sid_gipd_fx; + move32(); hStereoDft->no_ipd_flag = hStereoDft->prev_sid_no_ipd_flag; + move16(); } - if ( hCPE->hStereoCng->cng_counter > ITD_SID_PREV_FRAMES ) + IF( GT_16( hCPE->hStereoCng->cng_counter, ITD_SID_PREV_FRAMES ) ) { - hStereoDft->prev_sid_gipd = hStereoDft->sid_gipd; + hStereoDft->prev_sid_gipd_fx = hStereoDft->sid_gipd_fx; + move32(); hStereoDft->prev_sid_no_ipd_flag = hStereoDft->no_ipd_flag; + move16(); } } + /*----------------------------------------------------------------* * UNCLR classifier (detection of uncorrelated L and R channels) *----------------------------------------------------------------*/ - unclr_classifier_dft( hCPE ); + unclr_classifier_dft_fx( hCPE ); /*------------------------------------------------------------------* * Channel mapping: computation of DMX and RES *-----------------------------------------------------------------*/ - res_nrg_all_curr = EPSILON; - dmx_nrg_all_curr = EPSILON; + res_nrg_all_curr = EPSILON_FX_M; + move32(); + res_nrg_all_curr_e = EPSILON_FX_E; + move16(); + dmx_nrg_all_curr = EPSILON_FX_M; + move32(); + dmx_nrg_all_curr_e = EPSILON_FX_E; + move16(); pDFT_DMX = DFT_DMX; pDFT_RES = DFT_RES; - pNrgL = bin_nrgL; - pNrgR = bin_nrgR; + pNrgL = bin_nrgL_fx; + pNrgR = bin_nrgR_fx; - set_zero( pDFT_DMX, STEREO_DFT_N_MAX_ENC ); - set_zero( pDFT_RES, STEREO_DFT_N_8k_ENC ); + set_zero_fx( pDFT_DMX, STEREO_DFT_N_MAX_ENC ); + set16_zero_fx( DFT_DMX_e, STEREO_DFT_N_MAX_ENC ); + set_zero_fx( pDFT_RES, STEREO_DFT_N_8k_ENC ); + set16_zero_fx( DFT_RES_e, STEREO_DFT_N_8k_ENC ); - pgIpd = hStereoDft->gipd + k_offset; - pSideGain = hStereoDft->side_gain + k_offset * STEREO_DFT_BAND_MAX; + pgIpd = hStereoDft->gipd_fx + k_offset; + pSideGain = hStereoDft->side_gain_fx + k_offset * STEREO_DFT_BAND_MAX; - if ( hStereoDft->hConfig->dmx_active ) + + IF( hStereoDft->hConfig->dmx_active ) { /*Active DMX*/ // alpha = 0; /* to avoid compilation warning */ alpha_fx = 0; /* to avoid compilation warning */ move16(); - g = 1.f; + g_fx = MAX_32; + move32(); /*Apply active DMX*/ - pDFT_DMX[0] = 0.f; - pDFT_RES[0] = 0.f; - for ( b = 0; b < hStereoDft->nbands_dmx; b++ ) + pDFT_DMX[0] = 0; + move32(); + DFT_DMX_e[0] = 0; + move16(); + pDFT_RES[0] = 0; + move32(); + DFT_RES_e[0] = 0; + move16(); + FOR( b = 0; b < hStereoDft->nbands_dmx; b++ ) { - g = pSideGain[b]; + g_fx = pSideGain[b]; + move32(); - if ( pgIpd[0] != 0.f ) + IF( pgIpd[0] != 0 ) { - c = cosf( pgIpd[0] ); - s = sinf( pgIpd[0] ); - for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + c_fx = shl_sat( getCosWord16( (Word16) pgIpd[0] ), 1 ); // Q15 saturation expected + s_fx = getSinWord16( (Word16) pgIpd[0] ); // Q15 + FOR( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) { /*rotate L*/ - tmp = pDFT_L[2 * i] * c + pDFT_L[2 * i + 1] * s; - pDFT_L[2 * i + 1] = pDFT_L[2 * i + 1] * c - pDFT_L[2 * i] * s; - pDFT_L[2 * i] = tmp; + // tmp = pDFT_L[2 * i] * c + pDFT_L[2 * i + 1] * s; + tmp_32fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( pDFT_L_fx[2 * i], c_fx ), DFT_L_e_tmp[2 * i], Mpy_32_16_1( pDFT_L_fx[2 * i + 1], s_fx ), DFT_L_e_tmp[2 * i + 1], &tmp_e ); + // pDFT_L[2 * i + 1] = pDFT_L[2 * i + 1] * c - pDFT_L[2 * i] * s; + pDFT_L_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( pDFT_L_fx[2 * i + 1], c_fx ), DFT_L_e_tmp[2 * i + 1], L_negate( Mpy_32_16_1( pDFT_L_fx[2 * i], s_fx ) ), DFT_L_e_tmp[2 * i], &DFT_L_e_tmp[2 * i + 1] ); + move32(); + // pDFT_L[2 * i] = tmp; + pDFT_L_fx[2 * i] = tmp_32fx; + move32(); + DFT_L_e_tmp[2 * i] = tmp_e; + move16(); } } - if ( b < hStereoDft->res_cod_band_max && vad_flag_dtx[0] ) + test(); + IF( LT_16( b, hStereoDft->res_cod_band_max ) && vad_flag_dtx[0] ) { /*Get the previous frame energy*/ - if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + IF( hStereoDft->hConfig->ada_wb_res_cod_mode ) { /*Calculate the energy of RES and DMX*/ /* 90% of old frame ... */ - dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.9f; - res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.9f; + // dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.9f; + dmx_nrg_all_curr = BASOP_Util_Add_Mant32Exp( dmx_nrg_all_curr, dmx_nrg_all_curr_e, Mpy_32_32( hStereoDft->res_cod_NRG_M_fx[b], 1932735283 /*0.9f*/ ), hStereoDft->res_cod_NRG_M_fx_e[b], &dmx_nrg_all_curr_e ); + // res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.9f; + res_nrg_all_curr = BASOP_Util_Add_Mant32Exp( res_nrg_all_curr, res_nrg_all_curr_e, Mpy_32_32( hStereoDft->res_cod_NRG_S_fx[b], 1932735283 /*0.9f*/ ), hStereoDft->res_cod_NRG_S_fx_e[b], &res_nrg_all_curr_e ); } - hStereoDft->res_cod_NRG_M[b] = EPSILON; - hStereoDft->res_cod_NRG_S[b] = EPSILON; + hStereoDft->res_cod_NRG_M_fx[b] = EPSILON_FX_M; + move32(); + hStereoDft->res_cod_NRG_M_fx_e[b] = EPSILON_FX_E; + move16(); + hStereoDft->res_cod_NRG_S_fx[b] = EPSILON_FX_M; + move32(); + hStereoDft->res_cod_NRG_S_fx_e[b] = EPSILON_FX_E; + move16(); - for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) { - pDFT_DMX[2 * i] = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * 0.5f; - pDFT_DMX[2 * i + 1] = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * 0.5f; + // pDFT_DMX[2 * i] = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * 0.5f; + pDFT_DMX[2 * i] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i], DFT_L_e_tmp[2 * i], pDFT_R_fx[2 * i], DFT_R_e_tmp[2 * i], &DFT_DMX_e[2 * i] ); + move32(); + DFT_DMX_e[2 * i] = sub( DFT_DMX_e[2 * i], 1 ); // * 0.5f + move16(); + // pDFT_DMX[2 * i + 1] = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * 0.5f; + pDFT_DMX[2 * i + 1] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i + 1], DFT_L_e_tmp[2 * i + 1], pDFT_R_fx[2 * i + 1], DFT_R_e_tmp[2 * i + 1], &DFT_DMX_e[2 * i + 1] ); + move32(); + DFT_DMX_e[2 * i + 1] = sub( DFT_DMX_e[2 * i + 1], 1 ); // * 0.5f + move16(); - pDFT_RES[2 * i] = ( pDFT_L[2 * i] - pDFT_R[2 * i] ) * 0.5f; - pDFT_RES[2 * i + 1] = ( pDFT_L[2 * i + 1] - pDFT_R[2 * i + 1] ) * 0.5f; + // pDFT_RES[2 * i] = ( pDFT_L[2 * i] - pDFT_R[2 * i] ) * 0.5f; + pDFT_RES[2 * i] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i], DFT_L_e_tmp[2 * i], L_negate( pDFT_R_fx[2 * i] ), DFT_R_e_tmp[2 * i], &DFT_RES_e[2 * i] ); + move32(); + DFT_RES_e[2 * i] = sub( DFT_RES_e[2 * i], 1 ); // * 0.5f + move16(); + // pDFT_RES[2 * i + 1] = ( pDFT_L[2 * i + 1] - pDFT_R[2 * i + 1] ) * 0.5f; + pDFT_RES[2 * i + 1] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i + 1], DFT_L_e_tmp[2 * i + 1], L_negate( pDFT_R_fx[2 * i + 1] ), DFT_R_e_tmp[2 * i + 1], &DFT_RES_e[2 * i + 1] ); + move32(); + DFT_RES_e[2 * i + 1] = sub( DFT_RES_e[2 * i + 1], 1 ); // * 0.5f + move16(); /*Prediction of RES with DMX*/ - pDFT_RES[2 * i] = pDFT_RES[2 * i] - g * pDFT_DMX[2 * i]; - pDFT_RES[2 * i + 1] = pDFT_RES[2 * i + 1] - g * pDFT_DMX[2 * i + 1]; + // pDFT_RES[2 * i] = pDFT_RES[2 * i] - g * pDFT_DMX[2 * i]; + pDFT_RES[2 * i] = BASOP_Util_Add_Mant32Exp( pDFT_RES[2 * i], DFT_RES_e[2 * i], L_negate( Mpy_32_32( g_fx, pDFT_DMX[2 * i] ) ), DFT_DMX_e[2 * i], &DFT_RES_e[2 * i] ); + move32(); + // pDFT_RES[2 * i + 1] = pDFT_RES[2 * i + 1] - g * pDFT_DMX[2 * i + 1]; + pDFT_RES[2 * i + 1] = BASOP_Util_Add_Mant32Exp( pDFT_RES[2 * i + 1], DFT_RES_e[2 * i + 1], L_negate( Mpy_32_32( g_fx, pDFT_DMX[2 * i + 1] ) ), DFT_DMX_e[2 * i + 1], &DFT_RES_e[2 * i + 1] ); + move32(); - pDFT_RES[2 * i] *= fac_att; - pDFT_RES[2 * i + 1] *= fac_att; + // pDFT_RES[2 * i] *= fac_att; + pDFT_RES[2 * i] = Mpy_32_16_1( pDFT_RES[2 * i], fac_att_fx ); + move32(); + // pDFT_RES[2 * i + 1] *= fac_att; + pDFT_RES[2 * i + 1] = Mpy_32_16_1( pDFT_RES[2 * i + 1], fac_att_fx ); + move32(); /*Energy of the DMX and RES*/ - hStereoDft->res_cod_NRG_M[b] += pDFT_DMX[2 * i] * pDFT_DMX[2 * i] + pDFT_DMX[2 * i + 1] * pDFT_DMX[2 * i + 1]; - hStereoDft->res_cod_NRG_S[b] += pDFT_RES[2 * i] * pDFT_RES[2 * i] + pDFT_RES[2 * i + 1] * pDFT_RES[2 * i + 1]; + // hStereoDft->res_cod_NRG_M[b] += pDFT_DMX[2 * i] * pDFT_DMX[2 * i] + pDFT_DMX[2 * i + 1] * pDFT_DMX[2 * i + 1]; + tmp_32fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_DMX[2 * i], pDFT_DMX[2 * i] ), shl( DFT_DMX_e[2 * i], 1 ), Mpy_32_32( pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1] ), shl( DFT_DMX_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->res_cod_NRG_M_fx[b] = BASOP_Util_Add_Mant32Exp( hStereoDft->res_cod_NRG_M_fx[b], hStereoDft->res_cod_NRG_M_fx_e[b], tmp_32fx, tmp_e, &hStereoDft->res_cod_NRG_M_fx_e[b] ); + move32(); + // hStereoDft->res_cod_NRG_S[b] += pDFT_RES[2 * i] * pDFT_RES[2 * i] + pDFT_RES[2 * i + 1] * pDFT_RES[2 * i + 1]; + tmp_32fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_RES[2 * i], pDFT_RES[2 * i] ), shl( DFT_RES_e[2 * i], 1 ), Mpy_32_32( pDFT_RES[2 * i + 1], pDFT_RES[2 * i + 1] ), shl( DFT_RES_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->res_cod_NRG_S_fx[b] = BASOP_Util_Add_Mant32Exp( hStereoDft->res_cod_NRG_S_fx[b], hStereoDft->res_cod_NRG_S_fx_e[b], tmp_32fx, tmp_e, &hStereoDft->res_cod_NRG_S_fx_e[b] ); + move32(); } - if ( hStereoDft->hConfig->ada_wb_res_cod_mode ) + IF( hStereoDft->hConfig->ada_wb_res_cod_mode ) { /*Calculate the energy of RES and DMX*/ /* ... + 10% of current frame. */ - dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.1f; - res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.1f; + // dmx_nrg_all_curr += hStereoDft->res_cod_NRG_M[b] * 0.1f; + dmx_nrg_all_curr = BASOP_Util_Add_Mant32Exp( dmx_nrg_all_curr, dmx_nrg_all_curr_e, Mpy_32_32( hStereoDft->res_cod_NRG_M_fx[b], 214748365 /*0.1f*/ ), hStereoDft->res_cod_NRG_M_fx_e[b], &dmx_nrg_all_curr_e ); + // res_nrg_all_curr += hStereoDft->res_cod_NRG_S[b] * 0.1f; + res_nrg_all_curr = BASOP_Util_Add_Mant32Exp( res_nrg_all_curr, res_nrg_all_curr_e, Mpy_32_32( hStereoDft->res_cod_NRG_S_fx[b], 214748365 /*0.1f*/ ), hStereoDft->res_cod_NRG_S_fx_e[b], &res_nrg_all_curr_e ); } } - else + ELSE { - int16_t upper_border; - int16_t triple_bin; - float frac_dot_prod; /* fraction of dot product according to energy ratio of current bins and whole band */ - float Sr, Si; - float comb_nrgL, comb_nrgR; + Word16 upper_border; + Word16 triple_bin; + Word32 frac_dot_prod; /* fraction of dot product according to energy ratio of current bins and whole band */ + Word16 frac_dot_prod_e; /* fraction of dot product according to energy ratio of current bins and whole band */ + Word32 Sr, Si; + Word16 Sr_e, Si_e; + Word32 comb_nrgL, comb_nrgR; + Word16 comb_nrgL_e, comb_nrgR_e; - upper_border = min( STEREO_DFT_DMX_CROSSOVER, hStereoDft->band_limits_dmx[b + 1] ); + upper_border = s_min( STEREO_DFT_DMX_CROSSOVER, hStereoDft->band_limits_dmx[b + 1] ); triple_bin = 0; - if ( upper_border > hStereoDft->band_limits_dmx[b] && ( upper_border - hStereoDft->band_limits_dmx[b] ) % 2 ) + move16(); + + test(); + IF( GT_16( upper_border, hStereoDft->band_limits_dmx[b] ) && sub( upper_border, hStereoDft->band_limits_dmx[b] ) % 2 ) { /* if odd number of bins in band, combine last 3 bins */ triple_bin = 1; - upper_border -= 3; + move16(); + upper_border = sub( upper_border, 3 ); } - for ( i = hStereoDft->band_limits_dmx[b]; i < upper_border; i += 2 ) + FOR( i = hStereoDft->band_limits_dmx[b]; i < upper_border; i += 2 ) { - comb_nrgL = pNrgL[i] + pNrgL[i + 1]; - comb_nrgR = pNrgR[i] + pNrgR[i + 1]; - Sr = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * ( pDFT_L[2 * i] + pDFT_R[2 * i] ) + ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ) * ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ); - Si = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) + ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ) * ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ); - - sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; - frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; - wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; - - wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + // comb_nrgL = pNrgL[i] + pNrgL[i + 1]; + comb_nrgL = BASOP_Util_Add_Mant32Exp( pNrgL[i], bin_nrgL_fx_e[i], pNrgL[i + 1], bin_nrgL_fx_e[i + 1], &comb_nrgL_e ); + // comb_nrgR = pNrgR[i] + pNrgR[i + 1]; + comb_nrgR = BASOP_Util_Add_Mant32Exp( pNrgR[i], bin_nrgR_fx_e[i], pNrgR[i + 1], bin_nrgR_fx_e[i + 1], &comb_nrgR_e ); + + // Sr = ( pDFT_L[2 * i] + pDFT_R[2 * i] ) * ( pDFT_L[2 * i] + pDFT_R[2 * i] ) + ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ) * ( pDFT_L[2 * i + 2] + pDFT_R[2 * i + 2] ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i], DFT_L_e_tmp[2 * i], pDFT_R_fx[2 * i], DFT_R_e_tmp[2 * i], &L_tmp1_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i + 2], DFT_L_e_tmp[2 * i + 2], pDFT_R_fx[2 * i + 2], DFT_R_e_tmp[2 * i + 2], &L_tmp2_e ); + Sr = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_tmp1, L_tmp1 ), shl( L_tmp1_e, 1 ), Mpy_32_32( L_tmp2, L_tmp2 ), shl( L_tmp2_e, 1 ), &Sr_e ); + + // Si = ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) * ( pDFT_L[2 * i + 1] + pDFT_R[2 * i + 1] ) + ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ) * ( pDFT_L[2 * i + 3] + pDFT_R[2 * i + 3] ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i + 1], DFT_L_e_tmp[2 * i + 1], pDFT_R_fx[2 * i + 1], DFT_R_e_tmp[2 * i + 1], &L_tmp1_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * i + 3], DFT_L_e_tmp[2 * i + 3], pDFT_R_fx[2 * i + 3], DFT_R_e_tmp[2 * i + 3], &L_tmp2_e ); + Si = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_tmp1, L_tmp1 ), shl( L_tmp1_e, 1 ), Mpy_32_32( L_tmp2, L_tmp2 ), shl( L_tmp2_e, 1 ), &Si_e ); + + // sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + L_tmp1 = comb_nrgL; + move32(); + L_tmp1_e = comb_nrgL_e; + move16(); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = comb_nrgR; + move32(); + L_tmp2_e = comb_nrgR_e; + move16(); + L_tmp2 = Sqrt32( L_tmp2, &L_tmp2_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( L_tmp1, L_tmp1_e, L_tmp2, L_tmp2_e, &sum_abs_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( sum_abs, sum_abs_e, EPSILON_FX_M, EPSILON_FX_E, &sum_abs_e ); + + // frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( comb_nrgL, comb_nrgL_e, comb_nrgR, comb_nrgR_e, &L_tmp1_e ); + frac_dot_prod = Mpy_32_32( L_tmp1, dot_prod_nrg_ratio_fx[b] ); + frac_dot_prod_e = add( L_tmp1_e, dot_prod_nrg_ratio_fx_e[b] ); + + // wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp1, sub( L_tmp1_e, 1 ), frac_dot_prod, frac_dot_prod_e, &L_tmp1_e ); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + wR = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &wR_e ); + wR_e = add( wR_e, sub( L_tmp1_e, sum_abs_e ) ); + + // wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( Sr, Sr_e, Si, Si_e, &L_tmp1_e ); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &L_tmp2_e ); + L_tmp2_e = add( L_tmp2_e, sub( L_tmp1_e, sum_abs_e ) ); + L_tmp2 = L_shl_sat( L_tmp2, L_tmp2_e ); // Q31 saturation expected + L_tmp1 = L_sub( MAX_32, L_tmp2 ); // Q31 + L_tmp1 = Mpy_32_32( 1518500250 /*sqrtf(2.f) in Q30*/, L_tmp1 ); // Q30 + wL = BASOP_Util_Add_Mant32Exp( wR, wR_e, L_tmp1, 1 /*Q30*/, &wL_e ); /*DMX Mapping*/ - pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; - pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; - pDFT_DMX[2 * i + 2] = ( wL * pDFT_L[2 * i + 2] + wR * pDFT_R[2 * i + 2] ) * INV_SQRT_2; - pDFT_DMX[2 * i + 3] = ( wL * pDFT_L[2 * i + 3] + wR * pDFT_R[2 * i + 3] ) * INV_SQRT_2; + // pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i] ), add( wL_e, DFT_L_e_tmp[2 * i] ), Mpy_32_32( wR, pDFT_R_fx[2 * i] ), add( wR_e, DFT_R_e_tmp[2 * i] ), &DFT_DMX_e[2 * i] ), INV_SQRT_2_Q31 ); + move32(); + // pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i + 1] ), add( wL_e, DFT_L_e_tmp[2 * i + 1] ), Mpy_32_32( wR, pDFT_R_fx[2 * i + 1] ), add( wR_e, DFT_R_e_tmp[2 * i + 1] ), &DFT_DMX_e[2 * i + 1] ), INV_SQRT_2_Q31 ); + move32(); + // pDFT_DMX[2 * i + 2] = ( wL * pDFT_L[2 * i + 2] + wR * pDFT_R[2 * i + 2] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 2] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i + 2] ), add( wL_e, DFT_L_e_tmp[2 * i + 2] ), Mpy_32_32( wR, pDFT_R_fx[2 * i + 2] ), add( wR_e, DFT_R_e_tmp[2 * i + 2] ), &DFT_DMX_e[2 * i + 2] ), INV_SQRT_2_Q31 ); + move32(); + // pDFT_DMX[2 * i + 3] = ( wL * pDFT_L[2 * i + 3] + wR * pDFT_R[2 * i + 3] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 3] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i + 3] ), add( wL_e, DFT_L_e_tmp[2 * i + 3] ), Mpy_32_32( wR, pDFT_R_fx[2 * i + 3] ), add( wR_e, DFT_R_e_tmp[2 * i + 3] ), &DFT_DMX_e[2 * i + 3] ), INV_SQRT_2_Q31 ); + move32(); } - if ( triple_bin ) + IF( triple_bin ) { - comb_nrgL = comb_nrgR = 0.f; - Sr = Si = 0.f; - for ( j = i; j < i + 3; j++ ) + comb_nrgL = comb_nrgR = 0; + move32(); + move32(); + comb_nrgL_e = comb_nrgR_e = 0; + move16(); + move16(); + Sr = Si = 0; + move32(); + move32(); + Sr_e = Si_e = 0; + move16(); + move16(); + FOR( j = i; j < i + 3; j++ ) { - comb_nrgL += pNrgL[j]; - comb_nrgR += pNrgR[j]; - Sr += ( pDFT_L[2 * j] + pDFT_R[2 * j] ) * ( pDFT_L[2 * j] + pDFT_R[2 * j] ); - Si += ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ) * ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ); + // comb_nrgL += pNrgL[j]; + comb_nrgL = BASOP_Util_Add_Mant32Exp( comb_nrgL, comb_nrgL_e, pNrgL[j], bin_nrgL_fx_e[j], &comb_nrgL_e ); + + // comb_nrgR += pNrgR[j]; + comb_nrgR = BASOP_Util_Add_Mant32Exp( comb_nrgR, comb_nrgR_e, pNrgR[j], bin_nrgR_fx_e[j], &comb_nrgR_e ); + + // Sr += ( pDFT_L[2 * j] + pDFT_R[2 * j] ) * ( pDFT_L[2 * j] + pDFT_R[2 * j] ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * j], DFT_L_e_tmp[2 * j], pDFT_R_fx[2 * j], DFT_R_e_tmp[2 * j], &L_tmp1_e ); + L_tmp1 = Mpy_32_32( L_tmp1, L_tmp1 ); + L_tmp1_e = shl( L_tmp1_e, 1 ); + Sr = BASOP_Util_Add_Mant32Exp( Sr, Sr_e, L_tmp1, L_tmp1_e, &Sr_e ); + + // Si += ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ) * ( pDFT_L[2 * j + 1] + pDFT_R[2 * j + 1] ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[2 * j + 1], DFT_L_e_tmp[2 * j + 1], pDFT_R_fx[2 * j + 1], DFT_R_e_tmp[2 * j + 1], &L_tmp2_e ); + L_tmp2 = Mpy_32_32( L_tmp2, L_tmp2 ); + L_tmp2_e = shl( L_tmp2_e, 1 ); + Si = BASOP_Util_Add_Mant32Exp( Si, Si_e, L_tmp2, L_tmp2_e, &Si_e ); } - sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; - frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; - wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; - wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); - - for ( j = i; j < i + 3; j++ ) + // sum_abs = sqrtf( comb_nrgL ) + sqrtf( comb_nrgR ) + EPSILON; + L_tmp1 = comb_nrgL; + move32(); + L_tmp1_e = comb_nrgL_e; + move16(); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = comb_nrgR; + move32(); + L_tmp2_e = comb_nrgR_e; + move16(); + L_tmp2 = Sqrt32( L_tmp2, &L_tmp2_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( L_tmp1, L_tmp1_e, L_tmp2, L_tmp2_e, &sum_abs_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( sum_abs, sum_abs_e, EPSILON_FX_M, EPSILON_FX_E, &sum_abs_e ); + + // frac_dot_prod = ( comb_nrgL + comb_nrgR ) * dot_prod_nrg_ratio[b]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( comb_nrgL, comb_nrgL_e, comb_nrgR, comb_nrgR_e, &L_tmp1_e ); + frac_dot_prod = Mpy_32_32( L_tmp1, dot_prod_nrg_ratio_fx[b] ); + frac_dot_prod_e = add( L_tmp1_e, dot_prod_nrg_ratio_fx_e[b] ); + + // wR = sqrtf( 0.5f * ( comb_nrgL + comb_nrgR ) + frac_dot_prod ) / sum_abs; + L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp1, sub( L_tmp1_e, 1 ), frac_dot_prod, frac_dot_prod_e, &L_tmp1_e ); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + wR = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &wR_e ); + wR_e = add( wR_e, sub( L_tmp1_e, sum_abs_e ) ); + + // wL = wR + sqrtf( 2.f ) * ( 1.f - ( sqrtf( Sr + Si ) / sum_abs ) ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( Sr, Sr_e, Si, Si_e, &L_tmp1_e ); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &L_tmp2_e ); + L_tmp2_e = add( L_tmp2_e, sub( L_tmp1_e, sum_abs_e ) ); + L_tmp2 = L_shl_sat( L_tmp2, L_tmp2_e ); // Q31 saturation expected + L_tmp1 = L_sub( MAX_32, L_tmp2 ); // Q31 + L_tmp1 = Mpy_32_32( 1518500250 /*sqrtf(2.f) in Q30*/, L_tmp1 ); // Q30 + wL = BASOP_Util_Add_Mant32Exp( wR, wR_e, L_tmp1, 1 /*Q30*/, &wL_e ); + + FOR( j = i; j < i + 3; j++ ) { - pDFT_DMX[2 * j] = ( wL * pDFT_L[2 * j] + wR * pDFT_R[2 * j] ) * INV_SQRT_2; - pDFT_DMX[2 * j + 1] = ( wL * pDFT_L[2 * j + 1] + wR * pDFT_R[2 * j + 1] ) * INV_SQRT_2; + // pDFT_DMX[2 * j] = ( wL * pDFT_L[2 * j] + wR * pDFT_R[2 * j] ) * INV_SQRT_2; + pDFT_DMX[2 * j] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * j] ), add( wL_e, DFT_L_e_tmp[2 * j] ), Mpy_32_32( wR, pDFT_R_fx[2 * j] ), add( wR_e, DFT_R_e_tmp[2 * j] ), &DFT_DMX_e[2 * j] ), INV_SQRT_2_Q31 ); + move32(); + // pDFT_DMX[2 * j + 1] = ( wL * pDFT_L[2 * j + 1] + wR * pDFT_R[2 * j + 1] ) * INV_SQRT_2; + pDFT_DMX[2 * j + 1] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * j + 1] ), add( wL_e, DFT_L_e_tmp[2 * j + 1] ), Mpy_32_32( wR, pDFT_R_fx[2 * j + 1] ), add( wR_e, DFT_R_e_tmp[2 * j + 1] ), &DFT_DMX_e[2 * j + 1] ), INV_SQRT_2_Q31 ); + move32(); } - i += 3; + i = add( i, 3 ); } - if ( i < hStereoDft->band_limits_dmx[b + 1] ) + IF( LT_16( i, hStereoDft->band_limits_dmx[b + 1] ) ) { - sum_nrg_L2 = EPSILON; - sum_nrg_R2 = EPSILON; - dot_prod_real2 = EPSILON; - for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + sum_nrg_L2 = EPSILON_FX_M; + move32(); + sum_nrg_L2_e = EPSILON_FX_E; + move16(); + sum_nrg_R2 = EPSILON_FX_M; + move32(); + sum_nrg_R2_e = EPSILON_FX_E; + move16(); + dot_prod_real2 = EPSILON_FX_M; + move32(); + dot_prod_real2_e = EPSILON_FX_E; + move16(); + FOR( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) { - sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; - sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; - dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + // sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L_fx[2 * j], pDFT_L_fx[2 * j] ), shl( DFT_L_e_tmp[2 * j], 1 ), Mpy_32_32( pDFT_L_fx[2 * j + 1], pDFT_L_fx[2 * j + 1] ), shl( DFT_L_e_tmp[2 * j + 1], 1 ), &L_tmp1_e ); + sum_nrg_L2 = BASOP_Util_Add_Mant32Exp( sum_nrg_L2, sum_nrg_L2_e, L_tmp1, L_tmp1_e, &sum_nrg_L2_e ); + // sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R_fx[2 * j], pDFT_R_fx[2 * j] ), shl( DFT_R_e_tmp[2 * j], 1 ), Mpy_32_32( pDFT_R_fx[2 * j + 1], pDFT_R_fx[2 * j + 1] ), shl( DFT_R_e_tmp[2 * j + 1], 1 ), &L_tmp1_e ); + sum_nrg_R2 = BASOP_Util_Add_Mant32Exp( sum_nrg_R2, sum_nrg_R2_e, L_tmp1, L_tmp1_e, &sum_nrg_R2_e ); + // dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L_fx[2 * j], pDFT_R_fx[2 * j] ), add( DFT_L_e_tmp[2 * j], DFT_R_e_tmp[2 * j] ), Mpy_32_32( pDFT_L_fx[2 * j + 1], pDFT_R_fx[2 * j + 1] ), add( DFT_L_e_tmp[2 * j + 1], DFT_R_e_tmp[2 * j + 1] ), &L_tmp1_e ); + dot_prod_real2 = BASOP_Util_Add_Mant32Exp( dot_prod_real2, dot_prod_real2_e, L_tmp1, L_tmp1_e, &dot_prod_real2_e ); } - sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); - sum_abs = sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) + EPSILON; - wR = sqrtf( 0.5f * ( sum_nrg_L2 + sum_nrg_R2 ) + dot_prod_nrg_ratio[b] ) / sum_abs; - wL = wR + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs ); + // sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + L_tmp3 = BASOP_Util_Add_Mant32Exp( sum_nrg_L2, sum_nrg_L2_e, sum_nrg_R2, sum_nrg_R2_e, &L_tmp3_e ); + sum_nrg_Mid = BASOP_Util_Add_Mant32Exp( L_tmp3, L_tmp3_e, dot_prod_real2, add( dot_prod_real2_e, 1 ), &sum_nrg_Mid_e ); + IF( sum_nrg_Mid < 0 ) + { + sum_nrg_Mid = 0; + move32(); + sum_nrg_Mid_e = 0; + move16(); + } + + // sum_abs = sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) + EPSILON; + L_tmp1 = sum_nrg_L2; + move32(); + L_tmp1_e = sum_nrg_L2_e; + move16(); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = sum_nrg_R2; + move32(); + L_tmp2_e = sum_nrg_R2_e; + move16(); + L_tmp2 = Sqrt32( L_tmp2, &L_tmp2_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( L_tmp1, L_tmp1_e, L_tmp2, L_tmp2_e, &sum_abs_e ); + sum_abs = BASOP_Util_Add_Mant32Exp( sum_abs, sum_abs_e, EPSILON_FX_M, EPSILON_FX_E, &sum_abs_e ); + + // wR = sqrtf( 0.5f * ( sum_nrg_L2 + sum_nrg_R2 ) + dot_prod_nrg_ratio[b] ) / sum_abs; + L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp3, sub( L_tmp3_e, 1 ), dot_prod_nrg_ratio_fx[b], dot_prod_nrg_ratio_fx_e[b], &L_tmp1_e ); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + wR = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &wR_e ); + wR_e = add( wR_e, sub( L_tmp1_e, sum_abs_e ) ); + + // wL = wR + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs ); + L_tmp1 = sum_nrg_Mid; + move32(); + L_tmp1_e = sum_nrg_Mid_e; + move16(); + L_tmp1 = Sqrt32( L_tmp1, &L_tmp1_e ); + L_tmp2 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, sum_abs, &L_tmp2_e ); + L_tmp2_e = add( L_tmp2_e, sub( L_tmp1_e, sum_abs_e ) ); + L_tmp2 = L_shl_sat( L_tmp2, L_tmp2_e ); // Q31 saturation expected + L_tmp1 = L_sub( MAX_32, L_tmp2 ); // Q31 + L_tmp1 = Mpy_32_32( 1518500250 /*sqrtf(2.f) in Q30*/, L_tmp1 ); // Q30 + wL = BASOP_Util_Add_Mant32Exp( wR, wR_e, L_tmp1, 1 /*Q30*/, &wL_e ); } - for ( ; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) + FOR( ; i < hStereoDft->band_limits_dmx[b + 1]; i++ ) { /*DMX Mapping*/ - pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; - pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + // pDFT_DMX[2 * i] = ( wL * pDFT_L[2 * i] + wR * pDFT_R[2 * i] ) * INV_SQRT_2; + pDFT_DMX[2 * i] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i] ), add( wL_e, DFT_L_e_tmp[2 * i] ), Mpy_32_32( wR, pDFT_R_fx[2 * i] ), add( wR_e, DFT_R_e_tmp[2 * i] ), &DFT_DMX_e[2 * i] ), INV_SQRT_2_Q31 ); + move32(); + // pDFT_DMX[2 * i + 1] = ( wL * pDFT_L[2 * i + 1] + wR * pDFT_R[2 * i + 1] ) * INV_SQRT_2; + pDFT_DMX[2 * i + 1] = Mpy_32_32( BASOP_Util_Add_Mant32Exp( Mpy_32_32( wL, pDFT_L_fx[2 * i + 1] ), add( wL_e, DFT_L_e_tmp[2 * i + 1] ), Mpy_32_32( wR, pDFT_R_fx[2 * i + 1] ), add( wR_e, DFT_R_e_tmp[2 * i + 1] ), &DFT_DMX_e[2 * i + 1] ), INV_SQRT_2_Q31 ); + move32(); } } } - for ( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->NFFT / 2; i++ ) + FOR( i = hStereoDft->band_limits_dmx[b]; i < hStereoDft->NFFT / 2; i++ ) { - pDFT_DMX[2 * i] = 0.f; - pDFT_DMX[2 * i + 1] = 0.f; + pDFT_DMX[2 * i] = 0; + move32(); + DFT_DMX_e[2 * i] = 0; + move16(); + pDFT_DMX[2 * i + 1] = 0; + move32(); + DFT_DMX_e[2 * i + 1] = 0; + move16(); } /*Nyquist Freq.*/ - if ( hStereoDft->band_limits_dmx[b] >= hStereoDft->NFFT / 2 ) + IF( GE_16( hStereoDft->band_limits_dmx[b], shr( hStereoDft->NFFT, 1 ) ) ) { - pDFT_DMX[1] = ( pDFT_L[1] + pDFT_R[1] ) * 0.5f; + // pDFT_DMX[1] = ( pDFT_L[1] + pDFT_R[1] ) * 0.5f; + pDFT_DMX[1] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[1], DFT_L_e_tmp[1], pDFT_R_fx[1], DFT_R_e_tmp[1], &DFT_DMX_e[1] ); + move32(); + DFT_DMX_e[1] = sub( DFT_DMX_e[1], 1 ); + move16(); } - else + ELSE { - pDFT_DMX[1] = 0.f; + pDFT_DMX[1] = 0; + move32(); + DFT_DMX_e[1] = 0; + move16(); } /* DC component */ - pDFT_DMX[0] = ( pDFT_L[0] + pDFT_R[0] ) * 0.5f; + // pDFT_DMX[0] = ( pDFT_L[0] + pDFT_R[0] ) * 0.5f; + pDFT_DMX[0] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[0], DFT_L_e_tmp[0], pDFT_R_fx[0], DFT_R_e_tmp[0], &DFT_DMX_e[0] ); + move32(); + DFT_DMX_e[0] = sub( DFT_DMX_e[0], 1 ); + move16(); } - else + ELSE { /*passive DMX*/ assert( hStereoDft->nbands == hStereoDft->nbands_dmx && "Don't use coarser stereo parameter resolution for residual coding bitrates!" ); - for ( i = 0; i < hStereoDft->band_limits[hStereoDft->res_cod_band_max]; i++ ) + FOR( i = 0; i < hStereoDft->band_limits[hStereoDft->res_cod_band_max]; i++ ) { - pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; - pDFT_RES[i] = ( pDFT_L[i] - pDFT_R[i] ) * 0.5f; + // pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + pDFT_DMX[i] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[i], DFT_L_e_tmp[i], pDFT_R_fx[i], DFT_R_e_tmp[i], &DFT_DMX_e[i] ); + move32(); + DFT_DMX_e[i] = sub( DFT_DMX_e[i], 1 ); + move16(); + // pDFT_RES[i] = ( pDFT_L[i] - pDFT_R[i] ) * 0.5f; + pDFT_RES[i] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[i], DFT_L_e_tmp[i], L_negate( pDFT_R_fx[i] ), DFT_R_e_tmp[i], &DFT_RES_e[i] ); + move32(); + DFT_RES_e[i] = sub( DFT_RES_e[i], 1 ); + move16(); } - for ( ; i < hStereoDft->NFFT; i++ ) + FOR( ; i < hStereoDft->NFFT; i++ ) { - pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + // pDFT_DMX[i] = ( pDFT_L[i] + pDFT_R[i] ) * 0.5f; + pDFT_DMX[i] = BASOP_Util_Add_Mant32Exp( pDFT_L_fx[i], DFT_L_e_tmp[i], pDFT_R_fx[i], DFT_R_e_tmp[i], &DFT_DMX_e[i] ); + move32(); + DFT_DMX_e[i] = sub( DFT_DMX_e[i], 1 ); + move16(); } } @@ -3070,61 +3281,167 @@ void stereo_dft_enc_process( * Recalculate RES and DMX *-----------------------------------------------------------------*/ - if ( hStereoDft->NFFT == STEREO_DFT_N_16k_ENC && hStereoDft->hConfig->ada_wb_res_cod_mode ) + test(); + IF( EQ_16( hStereoDft->NFFT, STEREO_DFT_N_16k_ENC ) && hStereoDft->hConfig->ada_wb_res_cod_mode ) { - stereo_dft_enc_get_res_cod_mode_flag( hStereoDft, res_nrg_all_curr, dmx_nrg_all_curr, &res_dmx_ratio, &frame_nrg_ratio ); + stereo_dft_enc_get_res_cod_mode_flag_fx( hStereoDft, res_nrg_all_curr, res_nrg_all_curr_e, dmx_nrg_all_curr, dmx_nrg_all_curr_e, &res_dmx_ratio, &frame_nrg_ratio ); - if ( hStereoDft->res_cod_sw_flag ) + IF( hStereoDft->res_cod_sw_flag ) { - int16_t res_cod_band_max; + Word16 res_cod_band_max; + + res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->hConfig->ada_wb_res_cod_mode]; + move16(); + + /* Recalculate RES and DMX */ + FOR( b = 0; b < res_cod_band_max; b++ ) + { + sum_nrg_L2 = EPSILON_FX_M; + move32(); + sum_nrg_L2_e = EPSILON_FX_E; + move16(); + sum_nrg_R2 = EPSILON_FX_M; + move32(); + sum_nrg_R2_e = EPSILON_FX_E; + move16(); + dot_prod_real2 = EPSILON_FX_M; + move32(); + dot_prod_real2_e = EPSILON_FX_E; + move16(); + FOR( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + { + // sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L_fx[2 * j], pDFT_L_fx[2 * j] ), shl( DFT_L_e_tmp[2 * j], 1 ), Mpy_32_32( pDFT_L_fx[2 * j + 1], pDFT_L_fx[2 * j + 1] ), shl( DFT_L_e_tmp[2 * j + 1], 1 ), &L_tmp1_e ); + sum_nrg_L2 = BASOP_Util_Add_Mant32Exp( sum_nrg_L2, sum_nrg_L2_e, L_tmp1, L_tmp1_e, &sum_nrg_L2_e ); + + // sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; + L_tmp2 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R_fx[2 * j], pDFT_R_fx[2 * j] ), shl( DFT_R_e_tmp[2 * j], 1 ), Mpy_32_32( pDFT_R_fx[2 * j + 1], pDFT_R_fx[2 * j + 1] ), shl( DFT_R_e_tmp[2 * j + 1], 1 ), &L_tmp2_e ); + sum_nrg_R2 = BASOP_Util_Add_Mant32Exp( sum_nrg_R2, sum_nrg_R2_e, L_tmp2, L_tmp2_e, &sum_nrg_R2_e ); + + // dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + L_tmp3 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L_fx[2 * j], pDFT_R_fx[2 * j] ), add( DFT_L_e_tmp[2 * j], DFT_R_e_tmp[2 * j] ), Mpy_32_32( pDFT_L_fx[2 * j + 1], pDFT_R_fx[2 * j + 1] ), add( DFT_L_e_tmp[2 * j + 1], DFT_R_e_tmp[2 * j + 1] ), &L_tmp3_e ); + dot_prod_real2 = BASOP_Util_Add_Mant32Exp( dot_prod_real2, dot_prod_real2_e, L_tmp3, L_tmp3_e, &dot_prod_real2_e ); + } - res_cod_band_max = dft_band_res_cod[hStereoDft->band_res[k_offset]][hStereoDft->hConfig->ada_wb_res_cod_mode]; + // sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( sum_nrg_L2, sum_nrg_L2_e, sum_nrg_R2, sum_nrg_R2_e, &L_tmp1_e ); + sum_nrg_Mid = BASOP_Util_Add_Mant32Exp( L_tmp1, L_tmp1_e, dot_prod_real2, add( dot_prod_real2_e, 1 ), &sum_nrg_Mid_e ); + IF( sum_nrg_Mid < 0 ) + { + sum_nrg_Mid = 0; + move32(); + sum_nrg_Mid_e = 0; + move16(); + } - /* Recalculate RES and DMX */ - for ( b = 0; b < res_cod_band_max; b++ ) - { - sum_nrg_L2 = EPSILON; - sum_nrg_R2 = EPSILON; - dot_prod_real2 = EPSILON; - for ( j = hStereoDft->band_limits_dmx[b]; j < hStereoDft->band_limits_dmx[b + 1]; j++ ) + // wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) * inv_sqrt( sum_nrg_L2 + EPSILON ); + L_tmp1_e = sum_nrg_L2_e; + move16(); + L_tmp1 = Sqrt32( sum_nrg_L2, &L_tmp1_e ); + L_tmp2_e = sum_nrg_R2_e; + move16(); + L_tmp2 = Sqrt32( sum_nrg_R2, &L_tmp2_e ); + L_tmp3_e = sum_nrg_Mid_e; + move16(); + L_tmp3 = Sqrt32( sum_nrg_Mid, &L_tmp3_e ); + wL = BASOP_Util_Add_Mant32Exp( L_tmp1, L_tmp1_e, L_tmp2, L_tmp2_e, &wL_e ); + wL = BASOP_Util_Add_Mant32Exp( wL, wL_e, L_negate( L_tmp3 ), L_tmp3_e, &wL_e ); + IF( wL < 0 ) { - sum_nrg_L2 += pDFT_L[2 * j] * pDFT_L[2 * j] + pDFT_L[2 * j + 1] * pDFT_L[2 * j + 1]; - sum_nrg_R2 += pDFT_R[2 * j] * pDFT_R[2 * j] + pDFT_R[2 * j + 1] * pDFT_R[2 * j + 1]; - dot_prod_real2 += pDFT_L[2 * j] * pDFT_R[2 * j] + pDFT_L[2 * j + 1] * pDFT_R[2 * j + 1]; + wL = 0; // Q31 + move32(); + } + ELSE + { + L_tmp1 = BASOP_Util_Add_Mant32Exp( sum_nrg_L2, sum_nrg_L2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp1_e ); + L_tmp1 = ISqrt32( L_tmp1, &L_tmp1_e ); + wL = Mpy_32_32( wL, L_tmp1 ); + wL_e = sub( add( wL_e, L_tmp1_e ), 1 ); // *0.5f + wL = L_shl( wL, wL_e ); // Q31 } - sum_nrg_Mid = max( 0.f, sum_nrg_L2 + sum_nrg_R2 + 2.f * dot_prod_real2 ); - wL = 0.5f * max( sqrtf( sum_nrg_L2 ) + sqrtf( sum_nrg_R2 ) - sqrtf( sum_nrg_Mid ), 0 ) * inv_sqrt( sum_nrg_L2 + EPSILON ); - wS = 1; + wS = MAX_16; // Q15 + move16(); - if ( hStereoDft->res_cod_sw_flag ) + IF( hStereoDft->res_cod_sw_flag ) { - wL *= ( 1 - hStereoDft->switch_fade_factor ); - wS = hStereoDft->switch_fade_factor; + // wL *= ( 1 - hStereoDft->switch_fade_factor ); + wL = Mpy_32_16_1( wL, sub( MAX_16, hStereoDft->switch_fade_factor_fx ) ); // Q31 + // wS = hStereoDft->switch_fade_factor; + wS = hStereoDft->switch_fade_factor_fx; // Q15 + move16(); } - for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) + FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ ) { /*DMX Recalculation*/ - DFT_DMX[2 * i] += wL * pDFT_L[2 * i]; - DFT_DMX[2 * i + 1] += wL * pDFT_L[2 * i + 1]; + // DFT_DMX[2 * i] += wL * pDFT_L[2 * i]; + DFT_DMX[2 * i] = BASOP_Util_Add_Mant32Exp( DFT_DMX[2 * i], DFT_DMX_e[2 * i], Mpy_32_32( pDFT_L_fx[2 * i], wL ), DFT_L_e_tmp[2 * i], &DFT_DMX_e[2 * i] ); + move32(); + // DFT_DMX[2 * i + 1] += wL * pDFT_L[2 * i + 1]; + DFT_DMX[2 * i + 1] = BASOP_Util_Add_Mant32Exp( DFT_DMX[2 * i + 1], DFT_DMX_e[2 * i + 1], Mpy_32_32( pDFT_L_fx[2 * i + 1], wL ), DFT_L_e_tmp[2 * i + 1], &DFT_DMX_e[2 * i + 1] ); + move32(); /*RES Recalculation*/ - DFT_RES[2 * i] *= wS; - DFT_RES[2 * i + 1] *= wS; + // DFT_RES[2 * i] *= wS; + DFT_RES[2 * i] = Mpy_32_16_1( DFT_RES[2 * i], wS ); + move32(); + // DFT_RES[2 * i + 1] *= wS; + DFT_RES[2 * i + 1] = Mpy_32_16_1( DFT_RES[2 * i + 1], wS ); + move32(); } } } } - if ( input_Fs >= 32000 ) + IF( GE_32( input_Fs, 32000 ) ) { - stereo_dft_enc_calculate_nrg_for_icbwe( hStereoDft, DFT_DMX, input_Fs ); + stereo_dft_enc_calculate_nrg_for_icbwe_fx( hStereoDft, DFT_L_e_tmp, DFT_R_e_tmp, DFT_DMX, DFT_DMX_e, input_Fs ); } - mvr2r( DFT_DMX, hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ); - mvr2r( DFT_RES, hStereoDft->DFT[1], STEREO_DFT_N_8k_ENC ); - set_zero( hStereoDft->DFT[1] + STEREO_DFT_N_8k_ENC, STEREO_DFT_N_MAX_ENC - STEREO_DFT_N_8k_ENC ); +#if 0 // def IVAS_FLOAT_FIXED_CONVERSIONS + float DFT_DMX_flt[STEREO_DFT_N_MAX_ENC]; + float DFT_RES_flt[STEREO_DFT_N_8k_ENC]; + + for (i = 0; i < STEREO_DFT_N_MAX_ENC; i++) { + DFT_DMX_flt[i] = me2f(DFT_DMX[i], DFT_DMX_e[i]); + } + for (i = 0; i < STEREO_DFT_N_8k_ENC; i++) { + DFT_RES_flt[i] = me2f(DFT_RES[i], DFT_RES_e[i]); + } +#endif + // making exp common + Word16 max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + max_exp = s_max( max_exp, DFT_DMX_e[i] ); + } + FOR( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + DFT_DMX[i] = L_shr_r( DFT_DMX[i], sub( max_exp, DFT_DMX_e[i] ) ); + move32(); + } + hStereoDft->DFT_fx_e[0] = max_exp; + move16(); + + max_exp = MIN_16; + move16(); + FOR( i = 0; i < STEREO_DFT_N_8k_ENC; i++ ) + { + max_exp = s_max( max_exp, DFT_RES_e[i] ); + } + FOR( i = 0; i < STEREO_DFT_N_8k_ENC; i++ ) + { + DFT_RES[i] = L_shr_r( DFT_RES[i], sub( max_exp, DFT_RES_e[i] ) ); + move32(); + } + hStereoDft->DFT_fx_e[1] = max_exp; + move16(); + + Copy32( DFT_DMX, hStereoDft->DFT_fx[0], STEREO_DFT_N_MAX_ENC ); + Copy32( DFT_RES, hStereoDft->DFT_fx[1], STEREO_DFT_N_8k_ENC ); + set_zero_fx( hStereoDft->DFT_fx[1] + STEREO_DFT_N_8k_ENC, STEREO_DFT_N_MAX_ENC - STEREO_DFT_N_8k_ENC ); return; } @@ -3557,7 +3874,231 @@ void stereo_dft_enc_process( * * Get the residual signal coding flag *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void stereo_dft_enc_get_res_cod_mode_flag_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, + const Word32 res_nrg_all_curr, // Q(31-res_nrg_all_curr_e) + const Word16 res_nrg_all_curr_e, + const Word32 dmx_nrg_all_curr, // Q(31-dmx_nrg_all_curr_e) + const Word16 dmx_nrg_all_curr_e, + Word32 *res_dmx_ratio, // Q31 + Word32 *frame_nrg_ratio ) // Q28 +{ + Word16 b, k_offset; + Word32 dmx_res_all, g /*Q31*/; + Word16 dmx_res_all_e; + Word16 fast_update_flag; + Word16 prev_res_cod_mode_flag, res_cod_mode_flag; + Word32 L_tmp1, L_tmp2; + Word16 L_tmp1_e, L_tmp2_e; + + k_offset = STEREO_DFT_OFFSET; /*Add an offset at encoder*/ + move16(); + + /*Calculate energy ratio between residual signal and downmix signal */ + *res_dmx_ratio = 0; + move32(); + + FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ ) + { + // g = fabsf(hStereoDft->side_gain[(k_offset)*STEREO_DFT_BAND_MAX + b]); + g = L_abs( hStereoDft->side_gain_fx[(k_offset) *STEREO_DFT_BAND_MAX + b] ); + //*res_dmx_ratio = max(hStereoDft->res_cod_NRG_S[b] / (hStereoDft->res_cod_NRG_S[b] + (1 - g) * (1 - g) * hStereoDft->res_cod_NRG_M[b] + 1), *res_dmx_ratio); + L_tmp1 = L_sub( MAX_32, g ); // Q31 + L_tmp2 = BASOP_Util_Add_Mant32Exp( hStereoDft->res_cod_NRG_S_fx[b], hStereoDft->res_cod_NRG_S_fx_e[b], Mpy_32_32( Mpy_32_32( L_tmp1, L_tmp1 ), hStereoDft->res_cod_NRG_M_fx[b] ), hStereoDft->res_cod_NRG_M_fx_e[b], &L_tmp2_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, MAX_32, 0, &L_tmp2_e ); + L_tmp1 = BASOP_Util_Divide3232_Scale_cadence( hStereoDft->res_cod_NRG_S_fx[b], L_tmp2, &L_tmp1_e ); + L_tmp1_e = add( L_tmp1_e, sub( hStereoDft->res_cod_NRG_S_fx_e[b], L_tmp2_e ) ); + L_tmp1 = L_shl( L_tmp1, L_tmp1_e ); // Q31 + *res_dmx_ratio = L_max( L_tmp1, *res_dmx_ratio ); + move32(); + } + //*res_dmx_ratio = check_bounds(*res_dmx_ratio, 0, 1); /*should always be satisfied*/ + *res_dmx_ratio = check_bounds_l( *res_dmx_ratio, 0, MAX_32 ); /*should always be satisfied*/ + move32(); + + /*Calculate the total energy of RES and DMX*/ + // dmx_res_all = res_nrg_all_curr + dmx_nrg_all_curr; + dmx_res_all = BASOP_Util_Add_Mant32Exp( res_nrg_all_curr, res_nrg_all_curr_e, dmx_nrg_all_curr, dmx_nrg_all_curr_e, &dmx_res_all_e ); + + /*Calculate the energy ratio of the inter-frame */ + //*frame_nrg_ratio = dmx_res_all / hStereoDft->dmx_res_all_prev; + *frame_nrg_ratio = BASOP_Util_Divide3232_Scale_cadence( dmx_res_all, hStereoDft->dmx_res_all_prev_fx, &L_tmp1_e ); + move32(); + L_tmp1_e = add( L_tmp1_e, sub( dmx_res_all_e, hStereoDft->dmx_res_all_prev_fx_e ) ); + *frame_nrg_ratio = L_shr_r_sat( *frame_nrg_ratio, sub( 3, L_tmp1_e ) ); // Q28 + move32(); + //*frame_nrg_ratio = L_min(5.0f, max(0.2f, *frame_nrg_ratio)); + *frame_nrg_ratio = L_min( ( 5 << 28 ) /*5.0f*/, L_max( 53687091 /*0.2f*/, *frame_nrg_ratio ) ); // Q28 + move32(); + + /* Get fast update flag */ + fast_update_flag = 0; + move16(); + // if ((*frame_nrg_ratio > 3.2f && *res_dmx_ratio < 0.1f) || (*frame_nrg_ratio < 0.21f && *res_dmx_ratio > 0.4f)) + test(); + test(); + test(); + if ( ( GT_32( *frame_nrg_ratio, 858993459 /*3.2f*/ ) && LT_32( *res_dmx_ratio, 214748365 /*0.1f*/ ) ) || ( LT_32( *frame_nrg_ratio, 56371446 /*0.21f */ ) && GT_32( *res_dmx_ratio, 858993459 /*0.4f*/ ) ) ) + { + fast_update_flag = 1; + move16(); + } + + /* Calculate long term energy ratio between residual signal and downmix signal */ + IF( fast_update_flag ) + { + // hStereoDft->res_dmx_ratio_lt = *res_dmx_ratio * 0.2f + hStereoDft->res_dmx_ratio_lt * 0.8f; + hStereoDft->res_dmx_ratio_lt_fx = L_add( Mpy_32_32( *res_dmx_ratio, 429496730 /*0.2f*/ ), Mpy_32_32( hStereoDft->res_dmx_ratio_lt_fx, 1717986918 /*0.8f*/ ) ); + move32(); + } + ELSE + { + // hStereoDft->res_dmx_ratio_lt = *res_dmx_ratio * 0.05f + hStereoDft->res_dmx_ratio_lt * 0.95f; + hStereoDft->res_dmx_ratio_lt_fx = L_add( Mpy_32_32( *res_dmx_ratio, 107374182 /*0.05f*/ ), Mpy_32_32( hStereoDft->res_dmx_ratio_lt_fx, 2040109466 /*0.95f*/ ) ); + move32(); + } + + /*Get the residual signal coding initial flag */ + // if (hStereoDft->res_dmx_ratio_lt > 0.01f) + IF( GT_32( hStereoDft->res_dmx_ratio_lt_fx, 21474836 /*0.01f*/ ) ) + { + res_cod_mode_flag = 1; + move16(); + } + ELSE + { + res_cod_mode_flag = 0; + move16(); + } + + /* Get the residual signal coding flag */ + IF( hStereoDft->first_frm_flag ) + { + prev_res_cod_mode_flag = res_cod_mode_flag; + move16(); + hStereoDft->first_frm_flag = 0; + move16(); + } + ELSE + { + prev_res_cod_mode_flag = hStereoDft->res_cod_mode[STEREO_DFT_OFFSET - 1]; + move16(); + } + IF( NE_16( res_cod_mode_flag, prev_res_cod_mode_flag ) ) + { + IF( EQ_16( prev_res_cod_mode_flag, 1 ) ) + { + test(); + test(); + IF( LT_16( hStereoDft->hangover_cnt0, 5 ) && hStereoDft->last_res_cod_mode_modify_flag == 0 && fast_update_flag == 0 ) + { + res_cod_mode_flag = prev_res_cod_mode_flag; + move16(); + hStereoDft->hangover_cnt0 = add( hStereoDft->hangover_cnt0, 1 ); + move16(); + } + ELSE + { + /* reset hangover */ + hStereoDft->hangover_cnt0 = 0; + move16(); + } + } + ELSE + { + // if (*frame_nrg_ratio > 2.5f || *frame_nrg_ratio < 0.21f) + test(); + IF( GT_32( *frame_nrg_ratio, 671088640 /*2.5f*/ ) || LT_32( *frame_nrg_ratio, 56371446 /*0.21f*/ ) ) + { + /* reset hangover */ + hStereoDft->hangover_cnt1 = 0; + move16(); + } + ELSE + { + IF( LT_16( hStereoDft->hangover_cnt1, 5 ) ) + { + res_cod_mode_flag = prev_res_cod_mode_flag; + move16(); + hStereoDft->hangover_cnt1 = add( hStereoDft->hangover_cnt1, 1 ); + move16(); + } + ELSE + { + /* reset hangover */ + hStereoDft->hangover_cnt1 = 0; + move16(); + } + } + } + } + + /* handle switching frames */ + test(); + IF( NE_16( res_cod_mode_flag, prev_res_cod_mode_flag ) && hStereoDft->last_res_cod_mode_modify_flag == 0 ) + { + hStereoDft->res_cod_sw_flag = 1; + move16(); + + /* Update switch_fade_factor */ + // if (*frame_nrg_ratio > 3.2f && *res_dmx_ratio < 0.1f) + test(); + test(); + IF( GT_32( *frame_nrg_ratio, 858993459 /*3.2f*/ ) && LT_32( *res_dmx_ratio, 214748365 /*0.1f*/ ) ) + { + // hStereoDft->switch_fade_factor = 0.75f; + hStereoDft->switch_fade_factor_fx = 24576; // 0.75f + move16(); + } + // else if (*frame_nrg_ratio < 0.21f && *res_dmx_ratio > 0.4f) + ELSE IF( LT_32( *frame_nrg_ratio, 56371446 /*0.21f*/ ) && GT_32( *res_dmx_ratio, 858993459 /*0.4f*/ ) ) + { + // hStereoDft->switch_fade_factor = 0.25f; + hStereoDft->switch_fade_factor_fx = 8192; // 0.25f + move16(); + } + ELSE + { + // hStereoDft->switch_fade_factor = 0.5f; + hStereoDft->switch_fade_factor_fx = 16384; // 0.5f + move16(); + } + if ( res_cod_mode_flag == 0 ) + { + res_cod_mode_flag = 1; + move16(); + } + } + + /*update previous frame's total energy of RES and DMX */ + hStereoDft->dmx_res_all_prev_fx = dmx_res_all; + move32(); + hStereoDft->dmx_res_all_prev_fx_e = dmx_res_all_e; + move16(); + + /* update residual coding mode */ + hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] = res_cod_mode_flag; + move16(); + IF( !hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + hStereoDft->res_cod_band_max = 0; + move16(); + hStereoDft->res_cod_line_max = 0; + move16(); + } + + /*Update residual signal memory when switching from not coding residual signal to coding it*/ + test(); + IF( prev_res_cod_mode_flag == 0 && EQ_16( res_cod_mode_flag, 1 ) ) + { + set_zero_fx( hStereoDft->output_mem_res_8k_fx, STEREO_DFT_OVL_8k ); + } + + return; +} +#else static void stereo_dft_enc_get_res_cod_mode_flag( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, const float res_nrg_all_curr, @@ -3708,7 +4249,7 @@ static void stereo_dft_enc_get_res_cod_mode_flag( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_res() * @@ -4334,8 +4875,11 @@ static void stereo_dft_enc_compute_prm_fx( move16(); set32_fx( sub_nrg_DMX, 0, STEREO_DFT_BAND_MAX ); + set16_fx( sub_nrg_DMX_e, 0, STEREO_DFT_BAND_MAX ); set32_fx( sub_nrg_L, 0, STEREO_DFT_BAND_MAX ); + set16_fx( sub_nrg_L_e, 0, STEREO_DFT_BAND_MAX ); set32_fx( sub_nrg_R, 0, STEREO_DFT_BAND_MAX ); + set16_fx( sub_nrg_R_e, 0, STEREO_DFT_BAND_MAX ); pSideGain = hStereoDft->side_gain_fx + k_offset * STEREO_DFT_BAND_MAX; // Q31 pgIpd = hStereoDft->gipd_fx + k_offset; // Q13 @@ -4917,6 +5461,8 @@ static void stereo_dft_enc_compute_prm_fx( ELSE { stereo_dft_enc_get_reverb_flag_fx( hStereoDft, pPredGain, sub_nrg_DMX, sub_nrg_DMX_e, sub_nrg_L, sub_nrg_L_e, sub_nrg_R, sub_nrg_R_e, k_offset, bin_nrgL_fx, bin_nrgL_fx_e, bin_nrgR_fx, bin_nrgR_fx_e ); + // printf( "\n%d ", hStereoDft->reverb_flag ); + // printf( "\n%f ", (float)hStereoDft->res_pred_gain_fx[18]/0x7fffffff); } @@ -6546,7 +7092,91 @@ static float stereo_dft_gain_offset( * calculate energy of downmix and left and right channel in the * SHB region for later use in ICBWE * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void stereo_dft_enc_calculate_nrg_for_icbwe_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ + const Word16 *DFT_L_e, + const Word16 *DFT_R_e, + const Word32 *DMX, /* i : DFT Stereo downmix Q(31-DMX_e[]) */ + const Word16 *DMX_e, /* i : DFT Stereo downmix */ + const Word32 input_Fs /* i : input sampling rate */ +) +{ + Word32 *pDFT_L, *pDFT_R, bandResDft; + Word16 bandResDft_e; + Word16 i, shbBins[3]; + Word16 tmp_e; + Word32 tmp; + + // bandResDft = ( (float) input_Fs ) / hStereoDft->NFFT; + bandResDft = BASOP_Util_Divide3232_Scale_cadence( input_Fs, hStereoDft->NFFT, &bandResDft_e ); + // shbBins[0] = (int16_t) ( 6400 / bandResDft ); + shbBins[0] = BASOP_Util_Divide3232_Scale( 6400, bandResDft, &tmp_e ); + move16(); + tmp_e = add( tmp_e, sub( 31, bandResDft_e ) ); + shbBins[0] = shr( shbBins[0], sub( 15, tmp_e ) ); // Q0 + move16(); + + // shbBins[1] = (int16_t) ( 10400 / bandResDft ); + shbBins[1] = BASOP_Util_Divide3232_Scale( 10400, bandResDft, &tmp_e ); + move16(); + tmp_e = add( tmp_e, sub( 31, bandResDft_e ) ); + shbBins[1] = shr( shbBins[1], sub( 15, tmp_e ) ); // Q0 + move16(); + + // shbBins[2] = (int16_t) ( 14400 / bandResDft ); + shbBins[2] = BASOP_Util_Divide3232_Scale( 14400, bandResDft, &tmp_e ); + move16(); + tmp_e = add( tmp_e, sub( 31, bandResDft_e ) ); + shbBins[2] = shr( shbBins[2], sub( 15, tmp_e ) ); // Q0 + move16(); + + assert( shbBins[1] <= hStereoDft->NFFT / 2 ); + + set32_fx( hStereoDft->nrg_L_fx, EPSILON_FX_M, 2 ); + set16_fx( hStereoDft->nrg_L_fx_e, EPSILON_FX_E, 2 ); + set32_fx( hStereoDft->nrg_R_fx, EPSILON_FX_M, 2 ); + set16_fx( hStereoDft->nrg_R_fx_e, EPSILON_FX_E, 2 ); + set32_fx( hStereoDft->nrg_DMX_fx, EPSILON_FX_M, 2 ); + set16_fx( hStereoDft->nrg_DMX_fx_e, EPSILON_FX_E, 2 ); + pDFT_L = hStereoDft->DFT_fx[0]; // Q(31-DFT_L_e[]) + pDFT_R = hStereoDft->DFT_fx[1]; // Q(31-DFT_R_e[]) + + FOR( i = shbBins[0]; i < shbBins[1]; i++ ) + { + // hStereoDft->nrg_L[0] += pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_L[2 * i] ), shl( DFT_L_e[2 * i], 1 ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_L[2 * i + 1] ), shl( DFT_L_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_L_fx[0] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_L_fx[0], hStereoDft->nrg_L_fx_e[0], tmp, tmp_e, &hStereoDft->nrg_L_fx_e[0] ); + move32(); + // hStereoDft->nrg_R[0] += pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R[2 * i], pDFT_R[2 * i] ), shl( DFT_R_e[2 * i], 1 ), Mpy_32_32( pDFT_R[2 * i + 1], pDFT_R[2 * i + 1] ), shl( DFT_R_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_R_fx[0] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_R_fx[0], hStereoDft->nrg_R_fx_e[0], tmp, tmp_e, &hStereoDft->nrg_R_fx_e[0] ); + move32(); + // hStereoDft->nrg_DMX[0] += DMX[2 * i] * DMX[2 * i] + DMX[2 * i + 1] * DMX[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( DMX[2 * i], DMX[2 * i] ), shl( DMX_e[2 * i], 1 ), Mpy_32_32( DMX[2 * i + 1], DMX[2 * i + 1] ), shl( DMX_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_DMX_fx[0] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_DMX_fx[0], hStereoDft->nrg_DMX_fx_e[0], tmp, tmp_e, &hStereoDft->nrg_DMX_fx_e[0] ); + move32(); + } + FOR( ; i < shbBins[2]; i++ ) + { + // hStereoDft->nrg_L[1] += pDFT_L[2 * i] * pDFT_L[2 * i] + pDFT_L[2 * i + 1] * pDFT_L[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_L[2 * i], pDFT_L[2 * i] ), shl( DFT_L_e[2 * i], 1 ), Mpy_32_32( pDFT_L[2 * i + 1], pDFT_L[2 * i + 1] ), shl( DFT_L_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_L_fx[1] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_L_fx[1], hStereoDft->nrg_L_fx_e[1], tmp, tmp_e, &hStereoDft->nrg_L_fx_e[1] ); + move32(); + // hStereoDft->nrg_R[1] += pDFT_R[2 * i] * pDFT_R[2 * i] + pDFT_R[2 * i + 1] * pDFT_R[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( pDFT_R[2 * i], pDFT_R[2 * i] ), shl( DFT_R_e[2 * i], 1 ), Mpy_32_32( pDFT_R[2 * i + 1], pDFT_R[2 * i + 1] ), shl( DFT_R_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_R_fx[1] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_R_fx[1], hStereoDft->nrg_R_fx_e[1], tmp, tmp_e, &hStereoDft->nrg_R_fx_e[1] ); + move32(); + // hStereoDft->nrg_DMX[1] += DMX[2 * i] * DMX[2 * i] + DMX[2 * i + 1] * DMX[2 * i + 1]; + tmp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( DMX[2 * i], DMX[2 * i] ), shl( DMX_e[2 * i], 1 ), Mpy_32_32( DMX[2 * i + 1], DMX[2 * i + 1] ), shl( DMX_e[2 * i + 1], 1 ), &tmp_e ); + hStereoDft->nrg_DMX_fx[1] = BASOP_Util_Add_Mant32Exp( hStereoDft->nrg_DMX_fx[1], hStereoDft->nrg_DMX_fx_e[1], tmp, tmp_e, &hStereoDft->nrg_DMX_fx_e[1] ); + move32(); + } + + return; +} +#else static void stereo_dft_enc_calculate_nrg_for_icbwe( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ const float *DMX, /* i : DFT Stereo downmix */ @@ -6584,3 +7214,4 @@ static void stereo_dft_enc_calculate_nrg_for_icbwe( return; } +#endif diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index b7f2af7f9..2115cc652 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -1698,7 +1698,7 @@ void stereo_dft_enc_compute_itd_fx( hStereoClassif->prev_g_IPD_fx = ONE_IN_Q28; move32(); // hStereoClassif->prev_IPD = 0.0f; - hStereoClassif->prev_IPD = 0; + hStereoClassif->prev_IPD_fx = 0; move16(); } diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 961781180..7b3fb8f5f 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -139,7 +139,7 @@ void stereo_tcx_init_enc_fx( test(); IF( !prev_IsTNSAllowed && st->hTcxCfg->fIsTNSAllowed && EQ_16( st->element_mode, IVAS_CPE_DFT ) ) /* may happen in unified stereo when switching stereo technologies */ { - InitTnsConfigs( st->bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, total_brate, st->element_mode, 0 ); + InitTnsConfigs_ivas_fx( st->bwidth, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, total_brate, st->element_mode, 0 ); SetAllowTnsOnWhite( st->hTcxCfg->tnsConfig, 0 ); } @@ -148,7 +148,7 @@ void stereo_tcx_init_enc_fx( return; } -#endif +#else void stereo_tcx_init_enc( Encoder_State *st /* i/o: encoder state structure */ @@ -216,7 +216,7 @@ void stereo_tcx_init_enc( return; } - +#endif /*-------------------------------------------------------------------* * stereo_tcx_core_enc() @@ -236,7 +236,7 @@ void stereo_tcx_core_enc( const int16_t vad_hover_flag /* i : VAD hangover flag */ ) { -#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word32 pitch_buf_fx[NB_SUBFR16k]; /* 15Q16 */ // Convert gamma to fixed point. @@ -278,14 +278,14 @@ void stereo_tcx_core_enc( /*LPC*/ float lsf_q[M], lsp_q[M], lsf[M]; - Word16 lsp_q_fx[M]; + Word16 lsp_q_fx[M], lsf_fx[M]; float lspmid_q[M]; Word16 lspmid_q_fx[M]; float A_q[M + 1]; Word16 A_q_fx[M + 1]; float gainlpc[2][FDNS_NPTS]; float lsp_tcx_q[M], lsf_tcx_q[M]; - // Word16 lsp_tcx_q_fx[M], lsf_tcx_q_fx[M]; + Word16 lsp_tcx_q_fx[M], lsf_tcx_q_fx[M]; int16_t tcx_lpc_cdk; Word16 A_q_ind[M + 1]; /*for LPC-based AC*/ Word16 lspq_ind[M]; /*for LPC-based AC*/ @@ -366,6 +366,7 @@ void stereo_tcx_core_enc( IF( LT_16( T_op[i], PIT_MIN_SHORTER ) ) { T_op[i] = shl( T_op[i], 1 ); + move16(); } /* convert pitch values to core sampling-rate */ @@ -377,6 +378,7 @@ void stereo_tcx_core_enc( 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); } } @@ -630,7 +632,7 @@ void stereo_tcx_core_enc( *---------------------------------------------------------------*/ #endif - if ( !st->enableTcxLpc ) + IF( !st->enableTcxLpc ) { #ifdef IVAS_FLOAT_FIXED IF( st->envWeighted ) @@ -663,32 +665,31 @@ void stereo_tcx_core_enc( } } -#ifdef IVAS_FLOAT_FIXED last_core_orig = st->last_core; move16(); -#else - last_core_orig = st->last_core; + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // Float to fix + Word16 lsp_new_fx[M], lsp_fx[M]; + st->gamma = float_to_fix16( st->gamma_flt, Q15 ); + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + if ( !st->enableTcxLpc ) + { + floatToFixed_arr( lsp_q, lsp_q_fx, Q15, M ); + floatToFixed_arr( lspmid_q, lspmid_q_fx, Q15, M ); + } #endif - for ( n = 0; n < n_subframes; n++ ) + FOR( n = 0; n < n_subframes; n++ ) { /* Get the envelope */ - if ( st->enableTcxLpc ) + IF( st->enableTcxLpc ) { -#ifdef IVAS_FLOAT_FIXED tcx_lpc_cdk = tcxlpc_get_cdk( st->hTcxCfg->coder_type ); -#else - tcx_lpc_cdk = tcxlpc_get_cdk_float( st->hTcxCfg->coder_type ); -#endif - -#ifdef IVAS_FLOAT_FIXED0 /* High MLD if this is enabled. */ - // Float to fix - for ( int j = 0; j < M; j++ ) - { - lsp_new_fx[j] = float_to_fix16( lsp_new[j], Q15 ); - st->lspold_enc_fx[j] = float_to_fix16( st->lspold_enc[j], Q15 ); - } - st->gamma = float_to_fix16( st->gamma_flt, Q15 ); + /* 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 ); @@ -700,117 +701,51 @@ 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; } -#else - /* Get the envelope corresponding to the current frame */ - E_LPC_int_lpc_tcx_float( st->lspold_enc, lsp_new, A_q ); - - /* Weight the envelope */ - weight_a( A_q, A_q, st->gamma_flt, M ); - - /* Convert to lsp and lsf */ - float lsp[M]; - a2lsp_stab( A_q, lsp, lsp_new ); - lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); #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 - /* Account for consumed bits */ - nbits_lpc[0] = TCXLPC_NUMBITS; - if ( param_lpc[0] ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int j = 0; j < M; j++ ) { - nbits_lpc[0] += TCXLPC_IND_NUMBITS; + lsf_tcx_q_fx[j] = (Word16) ( lsf_tcx_q[j] * 2.56f ); } -#else +#endif + /* Account for consumed bits */ nbits_lpc[0] = TCXLPC_NUMBITS; - if ( param_lpc[0] ) + move16(); + IF( param_lpc[0] ) { - nbits_lpc[0] += TCXLPC_IND_NUMBITS; + nbits_lpc[0] = add( nbits_lpc[0], TCXLPC_IND_NUMBITS ); + move16(); } -#endif -#ifdef IVAS_FLOAT_FIXED0 /* High MLD if this is enabled. */ + /* NOTE: High MLD observed for the below function. */ /* Convert quantized lsf to lsp and A */ - for ( int j = 0; j < M; j++ ) - { - lsf_tcx_q_fx[j] = (Word16) ( lsf_tcx_q[j] * 2.56f ); - } E_LPC_lsf_lsp_conversion( lsf_tcx_q_fx, lsp_tcx_q_fx, M ); - for ( int j = 0; j < M; j++ ) - { - lsp_tcx_q[j] = fix16_to_float( lsp_tcx_q_fx[j], Q15 ); - } E_LPC_f_lsp_a_conversion( lsp_tcx_q_fx, A_q_fx, M ); - for ( int j = 0; j < M + 1; j++ ) - { - A_q[j] = fix16_to_float( A_q_fx[j], Q14 - norm_s( A_q_fx[0] ) ); - } -#else - /* Convert quantized lsf to lsp and A */ - lsf2lsp( lsf_tcx_q, lsp_tcx_q, M, INT_FS_12k8 ); - lsp2a_stab( lsp_tcx_q, A_q, M ); -#endif -#ifdef IVAS_FLOAT_FIXED0 /* High MLD if this is enabled. */ - for ( int j = 0; j < M + 1; j++ ) - { - A_q_fx[j] = (Word16) ( A_q[j] / A_q[0] * ONE_IN_Q12 ); - A_q[j] = (float) A_q_fx[j] / A_q_fx[0]; - } -#endif } - else if ( !st->tcxonly ) + ELSE IF( !st->tcxonly ) { - E_LPC_int_lpc_tcx_float( st->lsp_old, lsp_q, A_q ); - -#ifdef IVAS_FLOAT_FIXED0 /* High MLD if this is enabled. */ - for ( int j = 0; j < M + 1; j++ ) - { - A_q_fx[j] = (Word16) ( A_q[j] / A_q[0] * ONE_IN_Q12 ); - A_q[j] = (float) A_q_fx[j] / A_q_fx[0]; - } -#endif + E_LPC_int_lpc_tcx( st->lsp_old_fx, lsp_q_fx, A_q_fx ); } - else if ( n + 2 == n_subframes ) /* First TCX10/5 subframe */ + ELSE IF( EQ_16( add( n, 2 ), n_subframes ) ) /* First TCX10/5 subframe */ { -#ifdef IVAS_FLOAT_FIXED - for ( int j = 0; j < M; j++ ) - { - lspmid_q_fx[j] = float_to_fix16( lspmid_q[j], Q15 ); - } E_LPC_f_lsp_a_conversion( lspmid_q_fx, A_q_fx, M ); - for ( int j = 0; j < M + 1; j++ ) - { - A_q[j] = fix16_to_float( A_q_fx[j], Q14 - norm_s( A_q_fx[0] ) ); - } -#else - lsp2a_stab( lspmid_q, A_q, M ); -#endif } - else + ELSE { -#ifdef IVAS_FLOAT_FIXED - for ( int j = 0; j < M; j++ ) - { - lsp_q_fx[j] = float_to_fix16( lsp_q[j], Q15 ); - } E_LPC_f_lsp_a_conversion( lsp_q_fx, A_q_fx, M ); - for ( int j = 0; j < M + 1; j++ ) - { - A_q[j] = fix16_to_float( A_q_fx[j], Q14 - norm_s( A_q_fx[0] ) ); - } -#else - lsp2a_stab( lsp_q, A_q, M ); -#endif } -#ifdef IVAS_FLOAT_FIXED IF( hTcxEnc->tcx_lpc_shaped_ari ) { basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); @@ -818,13 +753,63 @@ void stereo_tcx_core_enc( bitsAvailable = sub( bitsAvailable, nbits_lpc[n] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( A_q_fx, A_q, Q14 - norm_s( A_q_fx[0] ), M + 1 ); +#endif + /* Shape spectrum */ /* TODO: integrate this. */ ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); st->last_core = st->core; move16(); + } #else + for ( n = 0; n < n_subframes; n++ ) + { + /* Get the envelope */ + if ( st->enableTcxLpc ) + { + tcx_lpc_cdk = tcxlpc_get_cdk_float( st->hTcxCfg->coder_type ); + + /* Get the envelope corresponding to the current frame */ + E_LPC_int_lpc_tcx_float( st->lspold_enc, lsp_new, A_q ); + + /* Weight the envelope */ + weight_a( A_q, A_q, st->gamma_flt, M ); + + /* Convert to lsp and lsf */ + float lsp[M]; + a2lsp_stab( A_q, lsp, lsp_new ); + lsp2lsf( lsp, lsf, M, INT_FS_12k8 ); + + /* Quantize */ + Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); + + /* Account for consumed bits */ + nbits_lpc[0] = TCXLPC_NUMBITS; + if ( param_lpc[0] ) + { + nbits_lpc[0] += TCXLPC_IND_NUMBITS; + } + + /* Convert quantized lsf to lsp and A */ + lsf2lsp( lsf_tcx_q, lsp_tcx_q, M, INT_FS_12k8 ); + lsp2a_stab( lsp_tcx_q, A_q, M ); + } + else if ( !st->tcxonly ) + { + E_LPC_int_lpc_tcx_float( st->lsp_old, lsp_q, A_q ); + } + else if ( n + 2 == n_subframes ) /* First TCX10/5 subframe */ + { + lsp2a_stab( lspmid_q, A_q, M ); + } + else + { + lsp2a_stab( lsp_q, A_q, M ); + } + if ( hTcxEnc->tcx_lpc_shaped_ari ) { basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); @@ -836,8 +821,8 @@ void stereo_tcx_core_enc( ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); st->last_core = st->core; -#endif } +#endif #ifdef IVAS_FLOAT_FIXED st->last_core = last_core_orig; @@ -934,20 +919,18 @@ void stereo_tcx_core_enc( #ifdef IVAS_FLOAT_FIXED IF( st->enableTcxLpc ) { - // Float to fixed - Word16 lsp_tcx_q_fx[M]; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word16 lsf_q_fx[M]; - for ( int j = 0; j < M; j++ ) - { - lsp_tcx_q_fx[j] = float_to_fix16( lsp_tcx_q[j], Q15 ); - } +#endif E_LPC_lsp_unweight( lsp_tcx_q_fx, lsp_q_fx, lsf_q_fx, st->inv_gamma, M ); /* Update lsf_q for encoderSideLossSimulation() */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Fixed to float for ( int j = 0; j < M; j++ ) { lsp_q[j] = fix16_to_float( lsp_q_fx[j], Q15 ); lsf_q[j] = (float) lsf_q_fx[j] / 2.56f; } +#endif } #else if ( st->enableTcxLpc ) @@ -956,6 +939,13 @@ void stereo_tcx_core_enc( } #endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->enableTcxLpc ) + { + fixedToFloat_arr( lsp_tcx_q_fx, lsp_tcx_q, Q15, M ); + } +#endif + /* Update lsp/lsf memory */ if ( st->enableTcxLpc && st->core != ACELP_CORE ) { @@ -979,7 +969,7 @@ void stereo_tcx_core_enc( } -#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Float to fixed Word16 Q_exc, exp_exc; f2me_buf_16( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, &exp_exc, L_EXC_MEM ); @@ -999,8 +989,6 @@ void stereo_tcx_core_enc( floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); } - Word16 lsp_new_fx_arr[M]; - Word16 *lsp_new_fx = &lsp_new_fx_arr[0]; floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); @@ -1150,7 +1138,7 @@ void stereo_tcx_core_enc( } #endif -#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Fixed to float for ( int j = 0; j < NB_SUBFR16k; j++ ) { diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 37fc691ab..ddac54b52 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -780,7 +780,28 @@ Word16 peak_avrg_ratio_fx( Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ Word16 Q_coeff ); - +#ifdef IVAS_FLOAT_FIXED +Word16 peak_avrg_ratio_ivas_fx( + const Word32 total_brate, + const Word32 *input_hi_fx, /* i : i signal */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ + Word16 Q_coeff ); +void hvq_classifier_ivas_fx( + const Word32 *input, /* i : input signal Q12 */ + Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ + Word16 *prev_peaks, /* i/o: Peak indices memory Q0 */ + Word16 *hqswb_clas, /* i/o: HQ class Q0 */ + Word16 *Npeaks, /* o : Number of peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + const Word32 L_core_brate, /* i : Core bit-rate Q0 */ + const Word16 last_core, /* i : Last core used Q0 */ + Word32 *L_nf_gains, /* o : Noisefloor gains Q12 */ + Word16 *hvq_hangover, /* i/o: Mode-switch hangover Q0 */ + Word32 *L_pe_gains /* o : peak gains Q12 */ +); +#endif void pit16k_Q_enc_fx( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ const Word16 nBits, /* i : # of Q bits */ @@ -868,17 +889,6 @@ void InitTransientDetection_ivas_fx( Word16 nFrameLength, */ void RunTransientDetection_fx( Word16 const *i, Word16 nSamplesAvailable, struct TransientDetection *pTransientDetection ); -#ifdef IVAS_FLOAT_FIXED -/** Get the average temporal flatness measure using subblock energies aligned with the TCX. - * @param pTransientDetection Structure that contains transient detectors to be run. - * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. - A lookeahead can also be use if it exists. - * @param nPrevSubblocks Number of subblocks from the previous frames to use for the calculation. - * @return average temporal flatness measure with exponent AVG_FLAT_E - */ -Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE hTranDet, const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks, Word16 *exp_out ); -#endif - /** Get the average temporal flatness measure using subblock energies aligned with the TCX. * @param pTransientDetection Structure that contains transient detectors to be run. * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. @@ -900,6 +910,12 @@ Word16 GetTCXMaxenergyChange_fx( struct TransientDetection const *pTransientDete const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks ); + +Word16 GetTCXMaxenergyChange_ivas_fx( TRAN_DET_HANDLE hTranDet, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, + const Word16 nPrevSubblocks ); + #ifdef IVAS_FLOAT_FIXED /** Set TCX window length and overlap configuration * @param prevEnergyHF previous HF energy. Exponent must be the same as for currEnergyHF. @@ -1208,6 +1224,25 @@ Word16 DetectTnsFilt_fx( STnsConfig const *pTnsConfig, STnsData *pTnsData, Word16 *predictionGain ); +/** Detect TNS parameters. +* Detects if TNS should be used and fills TNS data in pTnsData. +* @param pTnsConfig TNS configuration. +* @param pSpectrum Spectrum lines. +TNS is tested on the spectrum defined by pSpectrum. +* @param sbCnt Number of active subbands. +* @param pTnsData TNS data is filled with sensible information. +* @return Returns 1 if Tns should be used, otherwise 0. +*/ +Word16 DetectTnsFilt_ivas_fx( STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + Word32 const pSpectrum[], /* i : MDCT spectrum Q=Qx */ + STnsData *pTnsData, /* o : TNS data struct */ + TRAN_DET_HANDLE hTranDet, /* i : transient detection handle */ + Word8 isTCX10, /* i : TCX10 or TCX20? */ + Word16 ltp_gain, /* i : LTP gain Q=15 */ + Word16 *predictionGain /* o : TNS prediction gain Q=7 */ +); + + /** Write TNS data into a stream of integers. * Writes TNS data into a stream of integers. * @param pTnsConfig TNS configuration. @@ -2163,6 +2198,20 @@ void TNSAnalysis_fx( Word8 *pfUseTns, /* o : Flag indicating if TNS is used */ Word16 *predictionGain ); +void TNSAnalysis_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 L_frame, /* i : frame length */ + Word16 L_spec, /* i : length of the spectrum */ + Word16 transform_type, /* i : transform type for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */ + Word8 isAfterACELP, /* i : Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */ + Word32 spectrum[], /* i : MDCT spectrum Q=Qx*/ + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + Word16 ltp_gain, /* i : ltp gain Q=15*/ + STnsData *pTnsData, /* o : Tns data */ + Word8 *pfUseTns, /* o : Flag indicating if TNS is used */ + Word16 *predictionGain /* o : TNS prediction gain Q=7 */ +); + void HBAutocorrelation_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 left_overlap_mode, /* i : overlap mode of left window half */ @@ -3071,7 +3120,19 @@ Word16 hq_classifier_enc_fx( /* o : Consumed bits Word32 *nf_gains, /* o : Noise-fill gains Q12 */ Word16 *hqswb_clas /* o : HQ class Q0 */ ); - +#ifdef IVAS_FLOAT_FIXED +Word16 hq_classifier_enc_ivas_fx( /* o : Consumed bits Q0 */ + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +); +#endif void diff_envelope_coding_fx( const Word16 is_transient, /* i : transient indicator Q0 */ const Word16 num_env_bands, /* i : number of envelope bands to code Q0 */ diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 7e269230f..43921ea1a 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -158,13 +158,9 @@ typedef struct including block i-1 and without block i. */ Word32 accSubblockNrg[NSUBBLOCKS + MAX_TD_DELAY + 1]; float subblockNrgChange_flt[NSUBBLOCKS + MAX_TD_DELAY]; /* subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ - Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; -#ifdef IVAS_FLOAT_FIXED - Word32 subblockNrgChange_32[NSUBBLOCKS + MAX_TD_DELAY]; /* subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ - Word16 q_subblockNrgChange; -#endif - int16_t nDelay; /* Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ - int16_t nPartialDelay; /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ + Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; /* Q(15 - SUBBLOCK_NRG_CHANGE_E) */ + int16_t nDelay; /* Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ + int16_t nPartialDelay; /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ /* Decay factor for the recursive accumulation */ float facAccSubblockNrg_flt; @@ -1137,7 +1133,10 @@ typedef struct hq_enc_structure int16_t hq_generic_speech_class; float crest_lp; /* Low-pass filtered crest of high band */ float crest_mod_lp; /* Low-pass filtered noise band detection */ - + Word32 crest_lp_fx; + Word16 crest_lp_q; + Word32 crest_mod_lp_fx; + Word16 crest_mod_lp_q; /* SWB BWE LR classification */ int16_t prev_frm_index[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; int16_t prev_frm_hfe2; @@ -2923,5 +2922,4 @@ typedef struct context_rc_mem_struct } RC_CONTEXT_MEM, *HANDLE_RC_CONTEXT_MEM; - #endif diff --git a/lib_enc/tns_base_enc_fx.c b/lib_enc/tns_base_enc_fx.c index 546326cb6..9798a1eaa 100644 --- a/lib_enc/tns_base_enc_fx.c +++ b/lib_enc/tns_base_enc_fx.c @@ -311,6 +311,294 @@ Word16 DetectTnsFilt_fx( STnsConfig const *pTnsConfig, return ( pTnsData->nFilters > 0 ); } + +Word16 DetectTnsFilt_ivas_fx( STnsConfig const *pTnsConfig, /* i : TNS Configuration struct */ + Word32 const pSpectrum[], /* i : MDCT spectrum Q=Qx */ + STnsData *pTnsData, /* o : TNS data struct */ + TRAN_DET_HANDLE hTranDet, /* i : transient detection handle */ + Word8 isTCX10, /* i : TCX10 or TCX20? */ + Word16 ltp_gain, /* i : LTP gain Q=15 */ + Word16 *predictionGain /* o : TNS prediction gain Q=7 */ +) +{ + 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(); + ResetTnsData( pTnsData ); + + IF( pTnsConfig->maxOrder <= 0 ) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ ) + { + Word16 idx0; + Word16 idx1; + Word16 nSubdivisions; + Word16 iSubdivisions; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter + 1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS ); + + FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ ) + { + Word16 iStartLine; + Word16 iEndLine; + Word16 tmp, headroom, shift; + Word32 L_tmp, tmp32; + + /* 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 ); + + tmp = sub( 1, shl( tmp, 1 ) ); /* exponent of autocorrelation */ +#ifdef BASOP_NOGLOB + 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 */ +#else + L_tmp = L_shl( 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( L_tmp ) ); /* L_tmp is >= 0x2000000 */ +#endif + } + } + } + /* 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 idx0; + Word16 idx1; + Word16 spectrumLength; + STnsFilter *pFilter; + Word16 nSubdivisions; + Word16 iSubdivisions; + Word16 tmpbuf[325]; + + set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 ); + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter + 1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + spectrumLength = sub( idx1, idx0 ); + pFilter = pTnsData->filter + iFilter; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ ) + { + Word16 iStartLine, n, i; + Word16 iEndLine; + const Word16 *pWindow; + Word16 lag, shift; + Word32 L_tmp; + + 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( L_shl( 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; + } + + /* We check the filter's decisions in the opposite direction */ + FOR( iFilter = sub( pTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- ) + { + STnsFilter *pFilter; + struct TnsParameters const *pTnsParameters; + Word16 maxEnergyChange; + move16(); + move16(); + pFilter = pTnsData->filter + iFilter; + pTnsParameters = pTnsConfig->pTnsParameters + iFilter; + + IF( s_or( (Word16) GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ), + sub( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) > 0 ) ) + { + move16(); + // pTnsData->nFilters > 0 || isTCX10 || ltp_gain < 0.6f || hTranDet == NULL + // .6f = 19660, Q=15 + test(); + test(); + test(); + IF( pTnsData->nFilters > 0 || isTCX10 || LT_16( ltp_gain, 19660 ) || hTranDet == NULL ) + { + pTnsData->nFilters = add( pTnsData->nFilters, 1 ); + move16(); + } + ELSE + { + maxEnergyChange = GetTCXMaxenergyChange_ivas_fx( hTranDet, isTCX10, NSUBBLOCKS, 3 ); + IF( sub( maxEnergyChange, pTnsParameters->minEnergyChange ) >= 0 ) + { + + pTnsData->nFilters = add( pTnsData->nFilters, 1 ); + move16(); + } + ELSE + { + ClearTnsFilterCoefficients( pFilter ); + } + } + } + ELSE IF( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */ + { + /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */ + ClearTnsFilterCoefficients( pFilter ); + move16(); + move16(); + pFilter->order = 1; + pTnsData->nFilters = add( pTnsData->nFilters, 1 ); + } + ELSE + { + ClearTnsFilterCoefficients( pFilter ); + } + } + + return ( pTnsData->nFilters > 0 ); +} + Word16 EncodeTnsData_fx( STnsConfig const *pTnsConfig, STnsData const *pTnsData, Word16 *stream, Word16 *pnSize, Word16 *pnBits ) { diff --git a/lib_enc/transient_detection_fx.c b/lib_enc/transient_detection_fx.c index 49be6db41..6fd743a99 100644 --- a/lib_enc/transient_detection_fx.c +++ b/lib_enc/transient_detection_fx.c @@ -303,6 +303,82 @@ Word16 GetTCXMaxenergyChange_fx( struct TransientDetection const *pTransientDete return i; } + +Word16 GetTCXMaxenergyChange_ivas_fx( TRAN_DET_HANDLE hTranDet, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, + const Word16 nPrevSubblocks ) +{ + Word16 i; + TransientDetector const *pTransientDetector; + SubblockEnergies const *pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const *pSubblockNrgChange; + Word16 maxEnergyChange; + Word16 nTotBlocks; + + + pTransientDetector = &hTranDet->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + move16(); + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub( pSubblockEnergies->nDelay, nDelay ); + pSubblockNrgChange = NULL; + nTotBlocks = add( nCurrentSubblocks, nPrevSubblocks ); + + assert( nTotBlocks > 0 ); + maxEnergyChange = 0 /*0.0f Q7*/; + move16(); + assert( ( nPrevSubblocks <= nRelativeDelay ) && ( nCurrentSubblocks <= NSUBBLOCKS + nDelay ) ); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nRelativeDelay - nPrevSubblocks]; + + IF( s_or( pTransientDetector->bIsAttackPresent, isTCX10 ) ) /* frame is TCX-10 */ + { + Word32 const *pSubblockNrg = &pSubblockEnergies->subblockNrg[sub( nRelativeDelay, nPrevSubblocks )]; + Word32 nrgMin, nrgMax; + Word16 idxMax = 0; + move16(); + + nrgMax = L_add( pSubblockNrg[0], 0 ); + + /* find subblock with maximum energy */ + FOR( i = 1; i < nTotBlocks; i++ ) + { + if ( LT_32( nrgMax, pSubblockNrg[i] ) ) + { + idxMax = i; + move16(); + } + nrgMax = L_max( nrgMax, pSubblockNrg[i] ); + } + + nrgMin = nrgMax; + move32(); + /* find minimum energy after maximum */ + FOR( i = idxMax + 1; i < nTotBlocks; i++ ) + { + nrgMin = L_min( nrgMin, pSubblockNrg[i] ); + } + /* lower maxEnergyChange if energy doesn't decrease much after energy peak */ + /* if (nrgMin > 0.375f * nrgMax) */ + if ( LT_32( Mpy_32_16_1( nrgMax, 12288 /*0.375f Q15*/ ), nrgMin ) ) + { + nTotBlocks = sub( idxMax, 3 ); + } + } + + FOR( i = 0; i < nTotBlocks; i++ ) + { + maxEnergyChange = s_max( maxEnergyChange, pSubblockNrgChange[i] ); + } + + move16(); + i = maxEnergyChange; + + return i; +} + void RunTransientDetection_fx( Word16 const *input, Word16 nSamplesAvailable, TransientDetection *pTransientDetection ) { Word16 filteredInput[L_FRAME48k]; @@ -334,56 +410,6 @@ void RunTransientDetection_fx( Word16 const *input, Word16 nSamplesAvailable, Tr } -#ifdef IVAS_FLOAT_FIXED -/*-------------------------------------------------------------------* - * GetTCXAvgTemporalFlatnessMeasure_ivas_fx() - * - * - *-------------------------------------------------------------------*/ - -Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( - TRAN_DET_HANDLE hTranDet, - const Word16 nCurrentSubblocks, - const Word16 nPrevSubblocks, - Word16 *exp_out ) -{ - Word16 i; - TransientDetector *pTransientDetector = &hTranDet->transientDetector; - const SubblockEnergies *pSubblockEnergies = pTransientDetector->pSubblockEnergies; - const Word16 nDelay = pTransientDetector->nDelay; - const Word16 nRelativeDelay = sub( pSubblockEnergies->nDelay, nDelay ); - const Word32 *pSubblockNrgChange = NULL; - Word32 sumTempFlatness; - Word64 sumTempFlatness_64; - Word16 q_tmp; - const Word16 nTotBlocks = add( nCurrentSubblocks, nPrevSubblocks ); - Word16 exp_diff; - move16(); - - /* Initialization */ - assert( nTotBlocks > 0 ); - sumTempFlatness_64 = 0; - move64(); - - assert( ( nPrevSubblocks <= nRelativeDelay ) && ( nCurrentSubblocks <= NSUBBLOCKS + nDelay ) ); - pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange_32[nRelativeDelay - nPrevSubblocks]; - FOR( i = 0; i < nTotBlocks; i++ ) - { - sumTempFlatness_64 = W_add( sumTempFlatness_64, W_deposit32_l( pSubblockNrgChange[i] ) ); - } - q_tmp = W_norm( sumTempFlatness_64 ); - sumTempFlatness = W_extract_l( W_shl( sumTempFlatness_64, sub( q_tmp, 32 ) ) ); - q_tmp = add( pSubblockEnergies->q_subblockNrgChange, sub( q_tmp, 32 ) ); - - i = BASOP_Util_Divide3216_Scale( sumTempFlatness, nTotBlocks, &exp_diff ); - *exp_out = sub( add( exp_diff, sub( Q31, q_tmp ) ), Q15 ); - move16(); - - return i; -} -#endif - - #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * isLongTermTransient_fx() @@ -426,7 +452,7 @@ void SetTCXModeInfo_ivas_fx( ) { TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; - Word16 tmp, exp_diff, exp_out; + Word16 tmp, exp_diff; test(); test(); @@ -512,8 +538,8 @@ void SetTCXModeInfo_ivas_fx( move16(); } } - tmp = BASOP_Util_Divide3216_Scale( ONE_IN_Q31, GetTCXAvgTemporalFlatnessMeasure_ivas_fx( hTranDet, NSUBBLOCKS, 0, &exp_out ), &exp_diff ); - tmp = shl( tmp, sub( exp_diff, exp_out ) ); // Q15 + tmp = BASOP_Util_Divide3216_Scale( ONE_IN_Q31, GetTCXAvgTemporalFlatnessMeasure_fx( (const TransientDetection *) hTranDet, NSUBBLOCKS, 0 ), &exp_diff ); + tmp = shl( tmp, sub( exp_diff, AVG_FLAT_E ) ); // Q15 test(); IF( isLongTermTransient_fx( L_deposit_h( tmp ), &hTcxEnc->tfm_mem_fx ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) { @@ -542,8 +568,8 @@ void SetTCXModeInfo_ivas_fx( *tcxModeOverlap = ALDO_WINDOW; move16(); } - tmp = BASOP_Util_Divide3216_Scale( ONE_IN_Q31, GetTCXAvgTemporalFlatnessMeasure_ivas_fx( hTranDet, NSUBBLOCKS, 0, &exp_out ), &exp_diff ); - tmp = shl( tmp, sub( exp_diff, exp_out ) ); // Q15 + tmp = BASOP_Util_Divide3216_Scale( ONE_IN_Q31, GetTCXAvgTemporalFlatnessMeasure_fx( (const TransientDetection *) hTranDet, NSUBBLOCKS, 0 ), &exp_diff ); + tmp = shl( tmp, sub( exp_diff, AVG_FLAT_E ) ); // Q15 test(); IF( isLongTermTransient_fx( L_deposit_h( tmp ), &hTcxEnc->tfm_mem_fx ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) { -- GitLab