diff --git a/lib_com/core_com_config.c b/lib_com/core_com_config.c index eb705127fad07d9c51026c2ed02df352c34f0f3b..2073ed00213b6eae7e02324df0adffb20fc0b2ca 100644 --- a/lib_com/core_com_config.c +++ b/lib_com/core_com_config.c @@ -42,6 +42,7 @@ #include "wmc_auto.h" #include "ivas_prot.h" #include "prot_fx.h" +#include "ivas_prot_fx.h" #define FSCALE_DENOM_BY_12800_Q15 1311 /*-------------------------------------------------------------------* @@ -229,6 +230,78 @@ int16_t getTcxonly_ivas( return tcxonly; } + +#ifdef IVAS_FLOAT_FIXED +Word16 getTcxonly_ivas_fx( + const Word16 element_mode, /* i : IVAS element mode */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const Word16 is_ism_format /* i : flag indicating ISM format */ +) +{ + Word16 tcxonly = 0; + move16(); + Word32 temp_flag; + if ( MCT_flag ) + { + temp_flag = IVAS_32k; + move32(); + } + else + { + temp_flag = IVAS_48k; + move32(); + } + + SWITCH( element_mode ) + { + case EVS_MONO: + if ( GT_32( total_brate, ACELP_32k ) ) + { + tcxonly = 1; + move16(); + } + BREAK; + case IVAS_SCE: + if ( is_ism_format ) + { + if ( GT_32( total_brate, MAX_ACELP_BRATE_ISM ) ) + { + tcxonly = 1; + move16(); + } + } + else + { + if ( GT_32( total_brate, MAX_ACELP_BRATE ) ) + { + tcxonly = 1; + move16(); + } + } + BREAK; + + case IVAS_CPE_DFT: + case IVAS_CPE_TD: + if ( GT_32( total_brate, MAX_ACELP_BRATE ) ) + { + tcxonly = 1; + move16(); + } + BREAK; + case IVAS_CPE_MDCT: + if ( GE_32( total_brate, temp_flag ) ) + { + tcxonly = 1; + move16(); + } + BREAK; + } + + return tcxonly; +} +#endif + Word16 getTcxonly( #ifdef IVAS_CODE_SWITCHING const Word16 element_mode, /* i : IVAS element mode */ @@ -706,7 +779,7 @@ Word16 getTcxBandwidth( tcxBandwidth = 16384 /*0.5f Q15*/; move16(); - if ( bwidth == NB ) + if ( EQ_16( bwidth, NB ) ) { tcxBandwidth = 10240 /*0.3125f Q15*/; move16(); @@ -1411,6 +1484,157 @@ void init_tcx_cfg( return; } + +#ifdef IVAS_FLOAT_FIXED +void init_tcx_cfg_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, + const Word32 total_brate, + const Word32 sr_core, + const Word32 input_Fs, + const Word16 L_frame, + const Word16 bwidth, + const Word16 L_frameTCX, + const Word16 fscale, + const Word16 preemph_fac, + const Word16 tcxonly, + const Word16 rf_mode, + const Word16 igf, + const Word16 infoIGFStopFreq, + const Word16 element_mode, + const Word16 ini_frame, + const Word16 MCT_flag ) +{ + Word16 i; + Word16 mdctWindowLength; + Word16 mdctWindowLengthFB; + Word16 na_scale_bwidth; + + hTcxCfg->preemph_fac = preemph_fac; + move16(); + + hTcxCfg->tcx5Size = shr( L_frame, 2 ); /* Always 5 ms */ + hTcxCfg->tcx5SizeFB = shr( L_frameTCX, 2 ); /* Always 5 ms */ + move16(); + move16(); + + hTcxCfg->tcx_mdct_window_length_old = hTcxCfg->tcx_mdct_window_length; + move16(); + mdctWindowLength = getMdctWindowLength_fx( fscale ); + mdctWindowLengthFB = (Word16) ( mdctWindowLength * input_Fs / sr_core ); + + init_tcx_window_cfg_fx( hTcxCfg, sr_core, input_Fs, L_frame, L_frameTCX, mdctWindowLength, mdctWindowLengthFB, element_mode ); + /* SQ deadzone & memory quantization*/ + hTcxCfg->sq_rounding = 12288 /*0.375f Q15*/; /*deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/ + move16(); + + /* TCX rate loop */ + hTcxCfg->tcxRateLoopOpt = 0; + move16(); + + if ( tcxonly != 0 ) + { + hTcxCfg->tcxRateLoopOpt = 2; + move16(); + } + if ( EQ_16( element_mode, IVAS_CPE_MDCT ) ) + { + hTcxCfg->tcxRateLoopOpt = 3; + move16(); + } + hTcxCfg->bandwidth = getTcxBandwidth( bwidth ); + move16(); + + /* set number of coded lines */ + hTcxCfg->tcx_coded_lines = getNumTcxCodedLines( bwidth ); + move16(); + + /* TNS in TCX */ + hTcxCfg->pCurrentTnsConfig = NULL; + hTcxCfg->fIsTNSAllowed = getTnsAllowed( total_brate, igf, element_mode ); + move16(); + + IF( hTcxCfg->fIsTNSAllowed ) + { + InitTnsConfigs_ivas_fx( bwidth, hTcxCfg->tcx_coded_lines, hTcxCfg->tnsConfig, infoIGFStopFreq, total_brate, element_mode, MCT_flag ); + + SetAllowTnsOnWhite( hTcxCfg->tnsConfig, (Word8) EQ_16( element_mode, IVAS_CPE_MDCT ) ); + } + + IF( ini_frame == 0 ) + { + hTcxCfg->tcx_curr_overlap_mode = hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW; + hTcxCfg->last_aldo = 1; + move16(); + move16(); + move16(); + } + + /* Context HM*/ + hTcxCfg->ctx_hm = getCtxHm( element_mode, total_brate, rf_mode ); + move16(); + + /* Residual Coding*/ + hTcxCfg->resq = getResq( total_brate ); + move16(); + test(); + if ( hTcxCfg->resq && !tcxonly ) + { + hTcxCfg->tcxRateLoopOpt = 1; + move16(); + } + + /*Set bandwidth scale*/ + IF( EQ_16( bwidth, NB ) ) + { + na_scale_bwidth = NB; + } + ELSE IF( LE_32( sr_core, INT_FS_16k ) ) + { + na_scale_bwidth = WB; + } + ELSE + { + na_scale_bwidth = SWB; + } + move16(); + hTcxCfg->na_scale = 32767 /*1.0f Q15*/; + move16(); + + test(); + IF( LT_16( na_scale_bwidth, SWB ) && !tcxonly ) + { + FOR( i = 0; i < SIZE_SCALE_TABLE_TCX; i++ ) + { + test(); + test(); + IF( ( EQ_16( na_scale_bwidth, scaleTcxTable[i].bwmode ) ) && + ( GE_32( total_brate, scaleTcxTable[i].bitrateFrom ) ) && + ( LT_32( total_brate, scaleTcxTable[i].bitrateTo ) ) ) + { + if ( rf_mode ) + { + i = sub( i, 1 ); + } + hTcxCfg->na_scale = scaleTcxTable[i].scale; + move16(); + BREAK; + } + } + } + + IF( tcxonly ) + { + InitPsychLPC_fx( sr_core, L_frame, hTcxCfg ); + } + ELSE + { + hTcxCfg->psychParamsCurrent = NULL; + } + + return; +} +#endif + #ifdef IVAS_FLOAT_FIXED void init_tcx_window_cfg_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i/o: TCX Config handle */ @@ -1529,7 +1753,7 @@ void init_tcx_cfg_fx( const Word16 bwidth, const Word16 L_frameTCX, const Word16 fscale, - const Word16 preemph_fac, + const Word16 preemph_fac, /*Q15*/ const Word16 tcxonly, const Word16 rf_mode, const Word16 igf, diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index c753e4d039440095b676440f543d00f7e0155b28..e64cacf4c9d938c83ccb60b678faf854210755ed 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3034,7 +3034,21 @@ void QuantizeTCXSpectrum( float *gain_tcx, /* o : global gain */ int16_t prm[] /* o : tcx parameters */ ); - +#ifdef IVAS_FLOAT_FIXED +void EstimateStereoTCXNoiseLevel_fx( + Encoder_State **sts, /* i : state handle */ + Word32 *q_spectrum[CPE_CHANNELS][NB_DIV], /* i : quantized MDCT spectrum */ + Word16 gain_tcx[][NB_DIV], /* i : global gain */ + Word16 gain_tcx_e, /* i : global gain exponent */ + Word16 L_frame[][NB_DIV], /* i : frame length */ + Word16 noiseFillingBorder[][NB_DIV], /* i : noise filling border */ + Word16 hm_active[][NB_DIV], /* i : flag indicating if the harmonic model is active */ + const Word16 ignore_chan[], /* i : flag indicating whether the channel should be ignored */ + Word16 fac_ns[][NB_DIV], /* o : noise filling level */ + Word16 param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); +#endif void EstimateStereoTCXNoiseLevel( Encoder_State **sts, /* i : state handle */ float *q_spectrum[CPE_CHANNELS][NB_DIV], /* i : quantized MDCT spectrum */ @@ -4081,6 +4095,14 @@ void ivas_mdct_quant_coder( const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); +void ivas_mdct_quant_coder_fx( + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); + void apply_MCT_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 68175df0257ed1b6fbd42eced8be4def6630f3b5..7eaeb92e0b3a477092ca7fd6f8a3cc1212a6d97a 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -2613,7 +2613,6 @@ void apply_MCT_enc_fx( Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ const Word16 nchan /* i : number of channels */ ); -#endif void ivas_spar_config_fx( Word32 ivas_total_brate, /* i : codec total bitrate */ @@ -2700,4 +2699,34 @@ void stereo_dft_enc_process_fx( const Word16 vad_hover_flag[], /* i : VAD hangover flags */ const Word16 input_frame /* i : input frame length */ ); + +void spectral_balancer_fx16( + Word16 *signal, /* i/o : signal Qx */ + Word16 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +); + +void stereo_icBWE_preproc_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 shb_speech_nonref[], /* o : SHB speech non-ref channel */ + Word16 q_shb_speech_nonref /* i : Q SHB speech non-ref channel */ +); + +#endif + +void QuantizeSpectrum_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const float A[], /* i : quantized coefficients NxAz_q[M+1] */ + const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ + float gainlpc[], /* i : MDCT gains of the previous frame */ + float synth[], /* o : synthesis buffer */ + const int16_t nb_bits, /* i : bit budget */ + const int16_t tnsSize, /* i : number of tns parameters put into prm */ + int16_t prm[], /* o : tcx parameters */ + const int16_t frame_cnt, /* i : frame counter in the super_frame */ + CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +); #endif diff --git a/lib_com/prot.h b/lib_com/prot.h index df837c21f38acea83410e4bb488316923234f0ed..e882813532680a1a1b24c0476441a410b7722d75 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -6859,11 +6859,24 @@ void init_coder_ace_plus( const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0)*/ ); +#ifdef IVAS_FLOAT_FIXED +void init_coder_ace_plus_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + const Word32 last_total_brate, /* i : last total bitrate */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); +#endif + void core_coder_reconfig( Encoder_State *st, /* i/o: encoder state structure */ const int32_t last_total_brate /* i : last total bitrate */ ); +#ifdef IVAS_FLOAT_FIXED +void core_coder_reconfig_ivas_fx( + Encoder_State *st ); +#endif + void core_coder_mode_switch( Encoder_State *st, /* i/o: encoder state structure */ const int32_t last_total_brate, /* i : last bitrate */ @@ -9926,6 +9939,15 @@ int16_t getTcxonly_ivas( const int16_t is_ism_format /* i : flag indicating ISM format */ ); +#ifdef IVAS_FLOAT_FIXED +Word16 getTcxonly_ivas_fx( + const Word16 element_mode, /* i : IVAS element mode */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/ + const Word16 is_ism_format /* i : flag indicating ISM format */ +); +#endif + int16_t getTnsAllowed( const int32_t total_brate, /* i : total bitrate */ const int16_t igf, /* i : flag indicating IGF activity*/ @@ -10071,6 +10093,16 @@ void IGFEncSetMode( const int16_t rf_mode /* i : flag to signal the RF mode */ ); +#ifdef IVAS_FLOAT_FIXED +void IGFEncSetMode_ivas_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word32 total_brate, /* i : encoder total bitrate */ + const Word16 bwidth, /* i : encoder audio bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +); +#endif + /*! r: number of bits written per frame */ int16_t IGFEncWriteBitstream( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ @@ -10286,4 +10318,24 @@ void init_tcx_cfg( const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); +#ifdef IVAS_FLOAT_FIXED +void init_tcx_cfg_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, + const Word32 total_brate, + const Word32 sr_core, + const Word32 input_Fs, + const Word16 L_frame, + const Word16 bwidth, + const Word16 L_frameTCX, + const Word16 fscale, + const Word16 preemph_fac, + const Word16 tcxonly, + const Word16 rf_mode, + const Word16 igf, + const Word16 infoIGFStopFreq, + const Word16 element_mode, + const Word16 ini_frame, + const Word16 MCT_flag ); +#endif + #endif diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 0dedd638c574381de1d08225e71164d361467612..caf9ba2c3c8916dfeeca5959eeea183fa08c5155 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -3319,6 +3319,7 @@ void InitTnsConfiguration( const Word16 element_mode, const Word16 is_mct ); +#ifdef IVAS_FLOAT_FIXED void InitTnsConfiguration_ivas_fx( const Word16 bwidth, const Word16 frameLength, @@ -3327,6 +3328,7 @@ void InitTnsConfiguration_ivas_fx( const Word32 total_brate, const Word16 element_mode, const Word16 is_mct ); +#endif /** Modify spectrum using TNS filter. * Modifies spectrum unsing TNS filter defined by pTnsData. @@ -4028,6 +4030,7 @@ void InitTnsConfigs( const Word16 element_mode, const Word16 is_mct ); +#ifdef IVAS_FLOAT_FIXED void InitTnsConfigs_ivas_fx( const Word16 bwidth, const Word16 L_frame, @@ -4036,6 +4039,7 @@ void InitTnsConfigs_ivas_fx( const Word32 total_brate, const Word16 element_mode, const Word16 is_mct ); +#endif #define IVAS_CODE_TCX_UTIL #ifdef IVAS_CODE_TCX_UTIL @@ -6345,7 +6349,7 @@ void init_tcx_cfg_fx( const Word16 bwidth, const Word16 L_frameTCX, const Word16 fscale, - const Word16 preemph_fac, + const Word16 preemph_fac, /*Q15*/ const Word16 tcxonly, const Word16 rf_mode, const Word16 igf, diff --git a/lib_com/tcx_utils_fx.c b/lib_com/tcx_utils_fx.c index 6de09ab9016bf635987458ed005166a89b6018b2..19082fe248dfe07482fe38c342437d8e17495920 100644 --- a/lib_com/tcx_utils_fx.c +++ b/lib_com/tcx_utils_fx.c @@ -2056,6 +2056,7 @@ void InitTnsConfigs( InitTnsConfiguration( bwidth, add( L_frame, shr( L_frame, 2 ) ), &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag ); } +#ifdef IVAS_FLOAT_FIXED void InitTnsConfigs_ivas_fx( const Word16 bwidth, const Word16 L_frame, @@ -2072,6 +2073,7 @@ void InitTnsConfigs_ivas_fx( 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 ); } +#endif void SetTnsConfig( diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index 99a4e67630105c65436fc9d36ce840f33c8d8b30..6ec06b3aaba578b770cc3f48f14cb705504cddd0 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -172,7 +172,6 @@ void InitTnsConfiguration( { IF( EQ_32( nSampleRate, L_mult0( 100, frameLength ) ) ) /* sub-frame length is <= 10 ms */ { - move16(); move16(); pTnsConfig->nMaxFilters = sizeof( tnsParameters16kHz_grouped ) / sizeof( tnsParameters16kHz_grouped[0] ); pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped; @@ -219,6 +218,7 @@ void InitTnsConfiguration( return; /*TNS_NO_ERROR;*/ } +#ifdef IVAS_FLOAT_FIXED void InitTnsConfiguration_ivas_fx( const Word16 bwidth, const Word16 frameLength, @@ -330,6 +330,7 @@ void InitTnsConfiguration_ivas_fx( FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ ) { assert( pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f * nSampleRate ); + assert( nSampleRate <= 96000 ); move16(); startLineFilter[iFilter] = divide3232( L_mult0( frameLength, pTnsConfig->pTnsParameters[iFilter].startLineFrequency ), L_shl( nSampleRate, 14 ) ); } @@ -355,6 +356,10 @@ void InitTnsConfiguration_ivas_fx( return; /*TNS_NO_ERROR;*/ } + +#endif + + /*-------------------------------------------------------------------* * ApplyTnsFilter() * diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index b42da35ad2636294312fe1d575ef9cca5b627617..212183213f564146772e06d2862e5f9c7b8c914d 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -1744,17 +1744,17 @@ typedef struct td_bwe_dec_structure #ifndef IVAS_FLOAT_FIXED float prev_lsf_diff[LPC_SHB_ORDER - 2]; #endif - Word16 prev_lsf_diff_fx[LPC_SHB_ORDER - 2]; + Word16 prev_lsf_diff_fx[LPC_SHB_ORDER - 2]; /*Q15*/ #ifndef IVAS_FLOAT_FIXED float prev_tilt_para; #endif - Word16 prev_tilt_para_fx; + Word16 prev_tilt_para_fx; /*Q10*/ #ifndef IVAS_FLOAT_FIXED float cur_sub_Aq[M + 1]; #endif - Word16 cur_sub_Aq_fx[M + 1]; + Word16 cur_sub_Aq_fx[M + 1]; /*Q12*/ /* quantized data */ diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c index 4af1da2cd57a07268a5eb13ae42e322f242d2ecd..edffd41358c27812810e82788e935a62e50f4ecc 100644 --- a/lib_enc/cod_tcx.c +++ b/lib_enc/cod_tcx.c @@ -43,9 +43,11 @@ #include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_com.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_rom_com_fx.h" #include "prot_fx_enc.h" #include "prot_fx.h" - +#endif /*-------------------------------------------------------------------* * HBAutocorrelation() * diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index 3aeaa3a6d453632b3e0fd9328abfe99b3734694b..531467d1aaf724219f6435a118a06d0db5218697 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -14,6 +14,11 @@ #include "stl.h" //#include "basop_mpy.h" #include "prot_fx_enc.h" +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#include "ivas_prot.h" +#include "ivas_prot_fx.h" +#include "ivas_rom_com_fx.h" +#endif /* Up to the Autocorrelation it is the same code as in GetMDCT, with the difference in the parameters in the call to tcx_windowing_analysis */ @@ -1186,6 +1191,368 @@ static int16_t DecideTonalSideInfo( } #endif +#ifdef IVAS_FLOAT_FIXED +/*-------------------------------------------------------------------* + * GetTransWidth() + * + * + *-------------------------------------------------------------------*/ + +static Word16 GetTransWidth_ivas_fx( + const Word16 tcxonly, + const Word16 tcx10, + const Word16 tcxltp_gain, // Q15 + const Word16 hm_active ) +{ + Word16 noiseTransWidth = MIN_NOISE_FILLING_HOLE; + move16(); + + IF( tcxonly ) + { + IF( hm_active ) + { + noiseTransWidth = HOLE_SIZE_FROM_LTP( s_max( tcxltp_gain, 10240 /*0.3125f Q15*/ ) ); + } + ELSE + { + noiseTransWidth = HOLE_SIZE_FROM_LTP( s_max( tcxltp_gain, 0 ) ); + } + + if ( tcx10 ) + { + noiseTransWidth = 3; /* minimum transition for noise filling in TCX-10 */ + move16(); + } + } + + return noiseTransWidth; +} + +/*-----------------------------------------------------------* + * EstimateTCXNoiseLevel() + * + * Estimate and quantize noise factor * + *-----------------------------------------------------------*/ + +static void EstimateTCXNoiseLevel_ivas_fx( + Encoder_State *st, /* i : encoder state handle */ + Word32 x_orig[], /* i : shaped MDCT spectrum */ + Word16 x_orig_e, /* i : shaped MDCT spectrum exponent */ + Word32 spectrum[], /* i/o: quantized MDCT spectrum */ + const Word16 gain_tcx, /* i : global gain */ + const Word16 gain_tcx_e, /* i : global gain exponent */ + const Word16 L_frame, /* i : frame length */ + const Word16 noiseFillingBorder, /* i : noise filling border */ + const Word16 hm_active, /* i : flag indicating if the harmonic model is active */ + Word16 *fac_ns, /* o : noise filling level, Q15 */ + Word16 *fac_ns_q /* o : quantized noise filling level, Q0 */ +) +{ + Word16 maxNfCalcBw, iStart, noiseTransWidth; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + maxNfCalcBw = s_min( noiseFillingBorder, round_fx( L_shl( L_mult( hTcxEnc->measuredBwRatio, L_frame ), 1 ) ) ); + + IF( GE_32( st->total_brate, HQ_96k ) ) + { + *fac_ns = 0; + *fac_ns_q = 0; + move16(); + move16(); + } + ELSE + { + Word16 minLevel; + minLevel = 1; + move16(); + test(); + if ( hTcxEnc->tcx_lpc_shaped_ari && GT_16( st->element_mode, IVAS_SCE ) ) + { + minLevel = 0; + move16(); + } + + /* noise filling start bin */ + iStart = shr( L_frame, 3 ); + test(); + IF( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 ) + { + iStart = idiv1616U( L_frame, 6 ); + } + + noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame, shr( st->L_frame, 1 ) ), st->hTcxEnc->tcxltp_gain, ( st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active ) ); + + tcx_noise_factor_ivas_fx( x_orig, x_orig_e, spectrum, iStart, maxNfCalcBw, noiseTransWidth, L_frame, gain_tcx, gain_tcx_e, hTcxEnc->noiseTiltFactor, fac_ns, fac_ns_q, st->element_mode ); + + /* hysteresis for very tonal passages (more stationary noise filling level) */ + IF( EQ_16( *fac_ns_q, minLevel ) ) + { + hTcxEnc->noiseLevelMemory_cnt = s_min( INT16_MAX, add( 1, abs_s( hTcxEnc->noiseLevelMemory_cnt ) ) ); /* update counter */ + move16(); + } + ELSE + { + test(); + IF( EQ_16( *fac_ns_q, add( minLevel, 1 ) ) && GT_16( abs_s( hTcxEnc->noiseLevelMemory_cnt ), 5 ) ) + { + *fac_ns_q = minLevel; /* reduce noise filling level by one step */ + *fac_ns = 0; + move16(); + move16(); + IF( minLevel != 0 ) + { + *fac_ns = shr( 0x6000, NBITS_NOISE_FILL_LEVEL ); + move16(); + } + /* signal that noise level is changed by inverting sign of level memory */ + IF( hTcxEnc->noiseLevelMemory_cnt < 0 ) + { + hTcxEnc->noiseLevelMemory_cnt = 5; + move16(); + } + ELSE + { + hTcxEnc->noiseLevelMemory_cnt = negate( add( 1, hTcxEnc->noiseLevelMemory_cnt ) ); + move16(); + } + } + ELSE + { + hTcxEnc->noiseLevelMemory_cnt = 0; /* reset memory since level is too different */ + move16(); + } + } + } /* bitrate */ + + return; +} + + +/*-------------------------------------------------------------------* + * QuantizeSpectrum() + * + * + *-------------------------------------------------------------------*/ + +void QuantizeSpectrum_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const float A[], /* i : quantized coefficients NxAz_q[M+1] */ + const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */ + float gainlpc[], /* i : MDCT gains of the previous frame */ + float synth[], /* o : synthesis buffer */ + const int16_t nb_bits, /* i : bit budget */ + const int16_t tnsSize, /* i : number of tns parameters put into prm */ + int16_t prm[], /* o : tcx parameters */ + const int16_t frame_cnt, /* i : frame counter in the super_frame */ + CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +) +{ + int16_t L_frameTCX; /* full frame length */ + int16_t L_frame; /* frame length */ + int16_t L_spec; /* length of the coded spectrum */ + int16_t tcx_offset; /* folding point offset relative to the end of the previous frame */ + int16_t noiseFillingBorder; /* noise filling border */ + float quantized_spectrum[N_MAX]; /* quantized MDCT spectrum */ + Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */ + float lf_deemph_fact[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ + int16_t hm_active; /* flag indicating if the harmonic model is active */ + float fac_ns; /* noise filling level */ + Word16 fac_ns_fx; /* noise filling level, Q15 */ + int16_t nf_seed; /* noise filling random seed */ + float ener; /* energy of the quantized spectrum */ + float gain_tcx; /* global gain */ + Word16 gain_tcx_fx; /* global gain */ + Word16 gain_tcx_e; /* global gain */ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + /*-----------------------------------------------------------* + * Quantize the MDCT spectrum * + *-----------------------------------------------------------*/ + + QuantizeTCXSpectrum( st, frame_cnt, hTcxEnc->spectrum[frame_cnt], gainlpc, Aqind, tnsSize, nb_bits, vad_hover_flag, + &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum, hm_cfg, &hm_active, lf_deemph_fact, &nf_seed, &ener, &gain_tcx, prm ); + + /*-----------------------------------------------------------* + * Estimate and quantize noise factor * + *-----------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->tcxltp_gain = float_to_fix16( st->hTcxEnc->tcxltp_gain_flt, Q15 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); + st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); + floatToFixed_arrL( quantized_spectrum, quantized_spectrum_fx, 31 - st->hTcxEnc->spectrum_e[0], L_frame ); + gain_tcx_e = 15 - ( Q_factor( gain_tcx ) ); + gain_tcx_fx = float_to_fix16( gain_tcx, 15 - gain_tcx_e ); +#endif + + EstimateTCXNoiseLevel_ivas_fx( st, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, &fac_ns_fx, &prm[1] ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fac_ns = fix16_to_float( fac_ns_fx, Q15 ); +#endif + /*-----------------------------------------------------------* + * Internal decoder * + *-----------------------------------------------------------*/ + + InternalTCXDecoder( st, frame_cnt, L_frameTCX, L_frame, L_spec, tcx_offset, noiseFillingBorder, quantized_spectrum, ener, lf_deemph_fact, fac_ns, nf_seed, A, gainlpc, hm_active, gain_tcx, hTcxEnc->spectrum[frame_cnt], synth, &prm[0] ); + + /* Update L_frame_past */ + st->L_frame_past = L_frame; + + /* Update overlap */ + if ( ( ( ( L_frameTCX == hTcxEnc->L_frameTCX >> 1 ) && frame_cnt > 0 ) || ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) + { + st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + } + + + return; +} +#endif // IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED +void EstimateStereoTCXNoiseLevel_fx( + Encoder_State **sts, /* i : state handle */ + Word32 *q_spectrum[CPE_CHANNELS][NB_DIV], /* i : quantized MDCT spectrum */ + Word16 gain_tcx[][NB_DIV], /* i : global gain */ + Word16 gain_tcx_e, /* i : global gain exponent */ + Word16 L_frame[][NB_DIV], /* i : frame length */ + Word16 noiseFillingBorder[][NB_DIV], /* i : noise filling border */ + Word16 hm_active[][NB_DIV], /* i : flag indicating if the harmonic model is active */ + const Word16 ignore_chan[], /* i : flag indicating whether the channel should be ignored */ + Word16 fac_ns[][NB_DIV], /* o : noise filling level Q15 */ + Word16 param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) +{ + Word16 ch, n, i; + Word16 nSubframes, maxNfCalcBw, iStart, noiseTransWidth; + Word16 smooth_gain; + Word32 combined_q_spectrum[N_MAX]; + Word16 *fac_ns_q; + Word32 total_brate; + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + Encoder_State *st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + } + + if ( ignore_chan[ch] ) + { + continue; + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && !MCT_flag ) + { + total_brate = st->element_brate; + move32(); + } + ELSE + { + total_brate = st->total_brate; + move32(); + } + + FOR( n = 0; n < nSubframes; n++ ) + { + fac_ns_q = param_core[ch] + add( i_mult( n, NPRM_DIV ), 1 ); + + maxNfCalcBw = s_min( noiseFillingBorder[ch][n], round_fx( L_shl( L_mult( hTcxEnc->measuredBwRatio, L_frame[ch][n] ), 1 ) ) ); + + test(); + test(); + test(); + IF( ( GE_32( total_brate, HQ_96k ) && ( LE_16( st->element_mode, IVAS_SCE ) || LT_16( st->bwidth, SWB ) ) ) || GT_32( total_brate, IVAS_192k ) ) + { + fac_ns[ch][n] = 0; + move16(); + *fac_ns_q = 0; + move16(); + } + ELSE + { + test(); + IF( GE_32( total_brate, ACELP_13k20 ) && !st->rf_mode ) + { + iStart = idiv1616( L_frame[ch][n], 6 ); + } + ELSE + { + iStart = shr( L_frame[ch][n], 3 ); + } + + IF( n == 0 ) + { + Copy( hTcxEnc->ltpGainMemory_fx, &hTcxEnc->ltpGainMemory_fx[1], N_LTP_GAIN_MEMS - 1 ); + hTcxEnc->ltpGainMemory_fx[0] = st->hTcxEnc->tcxltp_gain; + move16(); + } + + Word32 temp = L_mult0( hTcxEnc->ltpGainMemory_fx[0], nf_tw_smoothing_coeffs_fx[0] ); + + FOR( i = 1; i < N_LTP_GAIN_MEMS; i++ ) + { + temp = L_mac0( temp, hTcxEnc->ltpGainMemory_fx[i], nf_tw_smoothing_coeffs_fx[i] ); + } + smooth_gain = round_fx( L_shl( temp, 1 ) ); + noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame[ch][n], shr( st->L_frame, 1 ) ), smooth_gain, ( st->hTcxCfg->ctx_hm && NE_16( st->last_core, ACELP_CORE ) && hm_active[ch][n] ) ); + + Copy32( q_spectrum[ch][n], combined_q_spectrum, L_frame[ch][n] ); + tcx_noise_factor_ivas_fx( hTcxEnc->spectrum_fx[n], hTcxEnc->spectrum_e[n], combined_q_spectrum, iStart, maxNfCalcBw, noiseTransWidth, L_frame[ch][n], gain_tcx[ch][n], gain_tcx_e, hTcxEnc->noiseTiltFactor, &fac_ns[ch][n], fac_ns_q, st->element_mode ); + + /* hysteresis for very tonal passages (more stationary noise filling level) */ + IF( EQ_16( *fac_ns_q, 1 ) ) + { + hTcxEnc->noiseLevelMemory_cnt = s_min( INT16_MAX, 1 + abs_s( hTcxEnc->noiseLevelMemory_cnt ) ); /* update counter */ + move16(); + } + ELSE + { + test(); + IF( EQ_16( *fac_ns_q, 2 ) && GT_16( abs_s( hTcxEnc->noiseLevelMemory_cnt ), 5 ) ) + { + *fac_ns_q = 1; /* reduce noise filling level by one step */ + fac_ns[ch][n] = 3072; /* 0.75f / ( 1 << NBITS_NOISE_FILL_LEVEL ) in Q15*/ + move16(); + move16(); + /* signal that noise level is changed by inverting sign of level memory */ + IF( ( hTcxEnc->noiseLevelMemory_cnt < 0 ) ) + { + hTcxEnc->noiseLevelMemory_cnt = 5; + move16(); + } + ELSE + { + hTcxEnc->noiseLevelMemory_cnt = sub( -1, hTcxEnc->noiseLevelMemory_cnt ); + } + } + ELSE + { + hTcxEnc->noiseLevelMemory_cnt = 0; /* reset memory since level is too different */ + move16(); + } + } + } /* bitrate */ + } + } + + return; +} +#endif + void QuantizeSpectrum_fx( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index 855ff8e89badccf2c5f5505c71770ff6019cc745..98483e7f8cbcd5eefbc0a99cbae586932614fc0a 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -41,6 +41,8 @@ #include "ivas_prot.h" #include "rom_com.h" #include "wmc_auto.h" +#include "prot_fx.h" +#include "prot_fx_enc.h" /*-----------------------------------------------------------------------* * Local function prototypes @@ -51,12 +53,358 @@ static void init_sig_buffers( Encoder_State *st, const int16_t L_frame_old, cons static void init_core_sig_ana( Encoder_State *st ); static void init_acelp( Encoder_State *st, const int16_t L_frame_old, const int32_t total_brate, const int32_t last_total_brate ); static void init_modes( Encoder_State *st, const int32_t last_total_brate ); - +#ifdef IVAS_FLOAT_FIXED +static void init_tcx_ivas_fx( Encoder_State *st, const Word16 L_frame_old, const Word32 total_brate, const Word32 last_total_brate, const Word16 MCT_flag ); +static void init_core_sig_ana_ivas_fx( Encoder_State *st ); +static void init_modes_ivas_fx( Encoder_State *st, const int32_t last_total_brate ); +static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_old, const Word16 L_subfr ); +static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 shift ); +#endif /*-----------------------------------------------------------------------* * init_coder_ace_plus() * * Initialization of state variables *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void init_coder_ace_plus_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + const Word32 last_total_brate, /* i : last total bitrate */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 L_frame_old; /*keep old frame size for switching */ + Word16 L_subfr; + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( hTcxEnc != NULL ) + { + hTcxEnc->L_frameTCX = extract_l( Mult_32_16( st->input_Fs, 0x0290 ) ); /* 0x0290 is 1/FRAMES_PER_SEC in Q15*/ + move16(); + + IF( st->ini_frame == 0 ) + { + set_zero( hTcxEnc->Txnq_flt, L_FRAME32k / 2 + 64 ); + hTcxEnc->acelp_zir_flt = hTcxEnc->Txnq_flt + L_FRAME / 2; + hTcxEnc->tcx_target_bits_fac_flt = 1.0f; + } + } + + IF( st->ini_frame == 0 ) + { + st->prevTempFlatness = 1.0f; + } + + IF( st->hBWE_TD != NULL ) + { + set_f( st->hBWE_TD->prev_lsf_diff, 0.5f, LPC_SHB_ORDER - 2 ); + st->hBWE_TD->prev_tilt_para = 0.0f; + set_zero( st->hBWE_TD->cur_sub_Aq, M + 1 ); + } + + st->currEnergyHF = 0; + + IF( ( NE_16( st->last_L_frame, st->L_frame ) ) || ( EQ_16( st->last_core, AMR_WB_CORE ) ) || ( EQ_16( st->last_core, HQ_CORE ) ) ) + { + set_f( st->mem_MA, 0.0f, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + /* Initialize TCX */ + IF( hTcxEnc != NULL ) + { + st->preemph_fac = (Word16) floatToFixed( st->preemph_fac_flt, Q15 ); + } + + /* Initialize Signal Buffers */ + f2me_buf_16( st->buf_speech_enc_flt, st->buf_speech_enc, &st->exp_buf_speech_enc, st->L_frame ); + f2me_buf_16( st->old_wsp, st->old_wsp_fx, &st->exp_old_wsp, L_WSP_MEM ); + f2me_buf_16( st->old_inp_12k8, st->old_inp_12k8_fx, &st->exp_old_inp_12k8, L_INP_MEM ); + f2me_buf_16( st->old_inp_16k, st->old_inp_16k_fx, &st->exp_old_inp_16k, L_INP_MEM ); + f2me_buf_16( st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, &st->exp_old_inp_16k, L_WSP_MEM ); + + /* Initialize ACELP */ + if ( st->lspold_enc != NULL ) + { + floatToFixed_arr16( st->lspold_enc, &st->lspold_enc_fx[0], Q15, M ); + } + if ( st->lsp_old1 != NULL ) + { + floatToFixed_arr16( st->lsp_old1, &st->lsp_old1_fx[0], Q15, M ); + } + if ( st->lsp_old != NULL ) + { + floatToFixed_arr16( st->lsp_old, &st->lsp_old_fx[0], Q15, M ); + } + + /* Adaptive BPF */ + set_zero( st->mem_bpf, 2 * L_FILT16k ); + set_zero( st->mem_error_bpf, 2 * L_FILT16k ); +#endif + + /* Bitrate */ + st->tcxonly = getTcxonly_ivas_fx( st->element_mode, st->total_brate, MCT_flag, st->is_ism_format ); + move16(); + + /* Core Sampling Rate */ + st->sr_core = getCoreSamplerateMode2( st->element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, st->is_ism_format ); + st->fscale = sr2fscale_fx( st->sr_core ); + move32(); + move16(); + + /* Narrowband? */ + IF( EQ_16( st->bwidth, NB ) ) + { + st->narrowBand = 1; + move16(); + } + ELSE + { + st->narrowBand = 0; + move16(); + } + + /* Core Framing */ + L_frame_old = st->last_L_frame; + move16(); + st->L_frame = extract_l( Mult_32_16( st->sr_core, 0x0290 ) ); /* 0x0290 is 1/FRAMES_PER_SEC in Q15*/ + move16(); + st->L_frame_past = -1; + move16(); + + IF( hTcxEnc != NULL ) + { + hTcxEnc->L_frameTCX = extract_l( Mult_32_16( st->input_Fs, 0x0290 ) ); /* 0x0290 is 1/FRAMES_PER_SEC in Q15*/ + move16(); + + IF( st->ini_frame == 0 ) + { + set16_fx( hTcxEnc->Txnq, 0, L_FRAME32k / 2 + 64 ); + hTcxEnc->acelp_zir = hTcxEnc->Txnq + L_FRAME / 2; + hTcxEnc->tcx_target_bits_fac = ONE_IN_Q14; + move16(); + } + } + + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( st->element_mode, EVS_MONO ) && EQ_32( st->L_frame, L_FRAME16k ) && LE_32( st->total_brate, ACELP_32k ) ) || ( GT_16( st->element_mode, EVS_MONO ) && EQ_32( st->L_frame, L_FRAME16k ) && LE_32( st->total_brate, MAX_ACELP_BRATE ) ) ) + { + st->nb_subfr = NB_SUBFR16k; + move16(); + } + ELSE + { + st->nb_subfr = NB_SUBFR; + move16(); + } + L_subfr = idiv1616( st->L_frame, st->nb_subfr ); + + /* Core Lookahead */ + st->encoderLookahead_enc = NS2SA_FX2( st->sr_core, ACELP_LOOK_NS ); + st->encoderLookahead_FB = NS2SA_FX2( st->input_Fs, ACELP_LOOK_NS ); + move16(); + move16(); + + IF( st->ini_frame == 0 ) + { + st->acelpFramesCount = 0; + move16(); + st->prevTempFlatness_fx = 128 /*1.0f Q7*/; + move16(); + } + + /* Initialize TBE */ + IF( st->hBWE_TD != NULL ) + { + st->hBWE_TD->prev_coder_type = GENERIC; + move16(); + set16_fx( st->hBWE_TD->prev_lsf_diff_fx, 16384, LPC_SHB_ORDER - 2 ); + st->hBWE_TD->prev_tilt_para_fx = 0; + move16(); + set16_fx( st->hBWE_TD->cur_sub_Aq_fx, 0, M + 1 ); + } + + st->currEnergyHF_fx = 0; + move32(); + + test(); + /* Initialize LPC analysis/quantization */ + IF( LE_32( st->sr_core, INT_FS_16k ) && st->tcxonly == 0 ) + { + st->lpcQuantization = 1; + move16(); + } + ELSE + { + st->lpcQuantization = 0; + move16(); + } + + st->next_force_safety_net = 0; + move16(); + test(); + test(); + IF( ( NE_16( st->last_L_frame, st->L_frame ) ) || ( EQ_16( st->last_core, AMR_WB_CORE ) ) || ( EQ_16( st->last_core, HQ_CORE ) ) ) + { + set16_fx( st->mem_MA_fx, 0, M ); + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); + } + + /* Initialize IGF */ + if ( st->hIGFEnc != NULL ) + { + st->hIGFEnc->infoStopFrequency = -1; + move16(); + } + + test(); + IF( st->igf && st->hIGFEnc != NULL ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGFEncSetMode( st->hIGFEnc, st->total_brate, st->bwidth, st->element_mode, st->rf_mode ); +#endif + IGFEncSetMode_ivas_fx( st->hIGFEnc, st->total_brate, st->bwidth, st->element_mode, st->rf_mode ); + } + ELSE IF( st->hIGFEnc != NULL ) + { + st->hIGFEnc->infoTotalBitsWritten = 0; + move16(); + st->hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + } + + /* Initialize Core Signal Analysis Module */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_core_sig_ana( st ); +#endif + init_core_sig_ana_ivas_fx( st ); + + /* Initialize TCX */ + IF( hTcxEnc != NULL ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_tcx( st, L_frame_old, st->total_brate, last_total_brate, MCT_flag ); +#endif + init_tcx_ivas_fx( st, L_frame_old, st->total_brate, last_total_brate, MCT_flag ); + } + + /* Initialize Signal Buffers */ + init_sig_buffers_ivas_fx( st, L_frame_old, L_subfr ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_sig_buffers( st, L_frame_old, L_subfr, st->total_brate, last_total_brate ); +#endif + /* Initialize ACELP */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_acelp( st, L_frame_old, st->total_brate, last_total_brate ); +#endif + + init_acelp_ivas_fx( st, L_frame_old, 0 ); + + IF( st->ini_frame == 0 ) + { + st->tec_tfa = 0; + move16(); + } + + IF( st->hTECEnc != NULL ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + resetTecEnc( st->hTECEnc, st->tec_tfa ); +#endif + resetTecEnc_Fx( st->hTECEnc, st->tec_tfa ); + } + + test(); + test(); + test(); + IF( EQ_16( st->bwidth, SWB ) && ( EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && EQ_16( st->element_mode, EVS_MONO ) ) + { + st->tec_tfa = 1; + move16(); + } + ELSE + { + st->tec_tfa = 0; + move16(); + } + + st->tec_flag = 0; + move16(); + st->tfa_flag = 0; + move16(); + + test(); + test(); + test(); + IF( ( EQ_32( st->total_brate, ACELP_9k60 ) || EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && EQ_16( st->element_mode, EVS_MONO ) ) + { + st->glr = 1; + move16(); + } + ELSE + { + st->glr = 0; + move16(); + } + + st->glr_reset = 0; + move16(); + + /* Initialize ACELP/TCX Modes */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_modes( st, last_total_brate ); +#endif + init_modes_ivas_fx( st, last_total_brate ); + + /* Adaptive BPF */ + set32_fx( st->mem_bpf_fx1, 0, 2 * L_FILT16k ); + set32_fx( st->mem_error_bpf_fx, 0, 2 * L_FILT16k ); + + IF( GE_32( st->total_brate, HQ_48k ) ) + { + st->enablePlcWaveadjust = 1; + move16(); + } + ELSE + { + st->enablePlcWaveadjust = 0; + move16(); + } + + IF( st->hPlcExt ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + init_PLC_enc( st->hPlcExt, st->sr_core ); +#endif + init_PLC_enc_fx( st->hPlcExt, st->sr_core ); + } + + st->glr_idx[0] = 0; + move16(); + st->glr_idx[1] = 0; + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->mean_gc_flt[0] = 0.0f; + st->mean_gc_flt[1] = 0.0f; + st->prev_lsf4_mean_flt = 0.0f; + st->last_stab_fac_flt = 0.0f; +#endif + st->mean_gc[0] = 0; + move16(); + st->mean_gc[1] = 0; + move16(); + st->prev_lsf4_mean = 0; + move16(); + st->last_stab_fac = 0; + move16(); + + return; +} +#endif void init_coder_ace_plus( Encoder_State *st, /* i : Encoder state */ @@ -152,6 +500,9 @@ void init_coder_ace_plus( if ( st->igf && st->hIGFEnc != NULL ) { IGFEncSetMode( st->hIGFEnc, st->total_brate, st->bwidth, st->element_mode, st->rf_mode ); +#ifdef IVAS_FLOAT_FIXED + IGFEncSetMode_ivas_fx( st->hIGFEnc, st->total_brate, st->bwidth, st->element_mode, st->rf_mode ); +#endif } else if ( st->hIGFEnc != NULL ) { @@ -161,18 +512,43 @@ void init_coder_ace_plus( /* Initialize Core Signal Analysis Module */ init_core_sig_ana( st ); +#ifdef IVAS_FLOAT_FIXED + init_core_sig_ana_ivas_fx( st ); +#endif /* Initialize TCX */ if ( hTcxEnc != NULL ) { init_tcx( st, L_frame_old, st->total_brate, last_total_brate, MCT_flag ); +#ifdef IVAS_FLOAT_FIXED + init_tcx_ivas_fx( st, L_frame_old, st->total_brate, last_total_brate, MCT_flag ); +#endif } /* Initialize Signal Buffers */ +#ifdef IVAS_FLOAT_FIXED + init_sig_buffers_ivas_fx( st, L_frame_old, L_subfr ); +#endif init_sig_buffers( st, L_frame_old, L_subfr, st->total_brate, last_total_brate ); /* Initialize ACELP */ init_acelp( st, L_frame_old, st->total_brate, last_total_brate ); +#ifdef IVAS_FLOAT_FIXED + if ( st->lspold_enc != NULL ) + { + floatToFixed_arr16( st->lspold_enc, &st->lspold_enc_fx[0], Q15, M ); + } + if ( st->lsp_old1 != NULL ) + { + floatToFixed_arr16( st->lsp_old1, &st->lsp_old1_fx[0], Q15, M ); + } + if ( st->lsp_old != NULL ) + { + floatToFixed_arr16( st->lsp_old, &st->lsp_old_fx[0], Q15, M ); + } + + init_acelp_ivas_fx( st, L_frame_old, 0 ); +#endif if ( st->ini_frame == 0 ) { @@ -182,6 +558,9 @@ void init_coder_ace_plus( if ( st->hTECEnc != NULL ) { resetTecEnc( st->hTECEnc, st->tec_tfa ); +#ifdef IVAS_FLOAT_FIXED + resetTecEnc_Fx( st->hTECEnc, st->tec_tfa ); +#endif } if ( st->bwidth == SWB && ( st->total_brate == ACELP_16k40 || st->total_brate == ACELP_24k40 ) && st->element_mode == EVS_MONO ) @@ -210,7 +589,9 @@ void init_coder_ace_plus( /* Initialize ACELP/TCX Modes */ init_modes( st, last_total_brate ); - +#ifdef IVAS_FLOAT_FIXED + init_modes_ivas_fx( st, last_total_brate ); +#endif /* Adaptive BPF */ set_zero( st->mem_bpf, 2 * L_FILT16k ); set_zero( st->mem_error_bpf, 2 * L_FILT16k ); @@ -224,9 +605,28 @@ void init_coder_ace_plus( st->enablePlcWaveadjust = 0; } +#ifdef IVAS_FLOAT_FIXED + set32_fx( st->mem_bpf_fx1, 0, 2 * L_FILT16k ); + set32_fx( st->mem_error_bpf_fx, 0, 2 * L_FILT16k ); + + IF( st->total_brate >= HQ_48k ) + { + st->enablePlcWaveadjust = 1; + move16(); + } + ELSE + { + st->enablePlcWaveadjust = 0; + move16(); + } +#endif + if ( st->hPlcExt ) { init_PLC_enc( st->hPlcExt, st->sr_core ); +#ifdef IVAS_FLOAT_FIXED + init_PLC_enc_fx( st->hPlcExt, st->sr_core ); +#endif } st->glr_idx[0] = 0; @@ -235,6 +635,12 @@ void init_coder_ace_plus( st->mean_gc_flt[1] = 0.0f; st->prev_lsf4_mean_flt = 0.0f; st->last_stab_fac_flt = 0.0f; +#ifdef IVAS_FLOAT_FIXED + st->mean_gc[0] = 0; + st->mean_gc[1] = 0; + st->prev_lsf4_mean = 0; + st->last_stab_fac = 0; +#endif return; } @@ -245,6 +651,119 @@ void init_coder_ace_plus( * Initialization of TCX *-----------------------------------------------------------------------*/ + +#ifdef IVAS_FLOAT_FIXED +static void init_tcx_ivas_fx( + Encoder_State *st, + const Word16 L_frame_old, + const Word32 total_brate, + const Word32 last_total_brate, + const Word16 MCT_flag ) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ + hTcxEnc->spectrum_fx[0] = hTcxEnc->spectrum_long_fx; + hTcxEnc->spectrum_fx[1] = hTcxEnc->spectrum_long_fx + N_TCX10_MAX; + + init_tcx_cfg_ivas_fx( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, + st->fscale, st->preemph_fac, st->tcxonly, st->rf_mode, st->igf, + st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, MCT_flag ); + + /* Init TCX target bits correction factor */ + hTcxEnc->tcx_target_bits_fac = 0x4000; /*1.0f in 1Q14*/ + move16(); + hTcxEnc->measuredBwRatio = 0x4000; /*1.0f in 1Q14*/ + move16(); + hTcxEnc->noiseTiltFactor = 9216; /*0.5625f in 1Q14*/ + move16(); + hTcxEnc->noiseLevelMemory_cnt = 0; + move16(); + + set16_fx( hTcxEnc->ltpGainMemory_fx, 0, N_LTP_GAIN_MEMS ); + set_c( hTcxEnc->memQuantZeros, 0, L_FRAME_PLUS ); + + /* TCX-LTP */ + hTcxEnc->tcxltp = getTcxLtp( st->sr_core ); + move16(); + + test(); + test(); + test(); + test(); + IF( st->ini_frame == 0 ) + { + hTcxEnc->tcxltp_pitch_int_past = st->L_frame; + hTcxEnc->tcxltp_pitch_fr_past = 0; + hTcxEnc->tcxltp_gain_past = 0; + hTcxEnc->tcxltp_norm_corr_past = 0; + hTcxEnc->tcxltp_norm_corr_mem = 0; + hTcxEnc->kernel_switch_corr_past = 0; + hTcxEnc->kernel_symmetry_past = 0; /* MDCT_IV & 1 */ + hTcxEnc->enc_ste_pre_corr_past = 0; + hTcxEnc->tfm_mem_fx = 12288 /*0.75 in Q14*/; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hTcxEnc->tfm_mem = 0.75f; +#endif + hTcxEnc->tcxltp_on_mem = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE IF( NE_16( st->L_frame, L_frame_old ) && !( ( GE_32( total_brate, ACELP_16k40 ) && LE_32( total_brate, ACELP_24k40 ) ) && + ( EQ_32( total_brate, last_total_brate ) ) && ( EQ_16( st->last_bwidth, st->bwidth ) ) ) ) + { + Word16 pitres, pitres_old; + Word16 pit, pit_old; + + pitres_old = 4; + move16(); + if ( EQ_16( 160, shr( L_frame_old, sub( 7, norm_s( L_frame_old ) ) ) ) ) /*if ( L_frame_old%160==0 )*/ + { + pitres_old = 6; + move16(); + } + + /*pit_old = (float)st->tcxltp_pitch_int_past + (float)st->tcxltp_pitch_fr_past/(float)pitres_old;*/ + pit_old = add( hTcxEnc->tcxltp_pitch_int_past, mult_r( hTcxEnc->tcxltp_pitch_fr_past, div_s( 1, pitres_old ) ) ); + + pitres = 4; + move16(); + if ( EQ_16( 160, shr( st->L_frame, sub( 7, norm_s( st->L_frame ) ) ) ) ) /*if ( st->L_frame%160==0 )*/ + { + pitres = 6; + move16(); + } + +#ifdef BASOP_NOGLOB + /*pit = pit_old * (float)st->L_frame/(float)L_frame_old;*/ + pit = shl_sat( mult_r( pit_old, div_s( st->L_frame, shl( L_frame_old, 2 ) ) ), 2 ); + /* Note : the saturation here that can happens when FS == 32kHz*/ +#else + pit = shl( mult_r( pit_old, div_s( st->L_frame, shl( L_frame_old, 2 ) ) ), 2 ); +#endif + /* assert(pit <= st->L_frame);*/ + + hTcxEnc->tcxltp_pitch_int_past = pit; + move16(); + hTcxEnc->tcxltp_pitch_fr_past = i_mult2( sub( pit, hTcxEnc->tcxltp_pitch_int_past ), pitres ); + move16(); + } + + hTcxEnc->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->total_brate, st->rf_mode, st->element_mode ); + move16(); + + return; +} +#endif + static void init_tcx( Encoder_State *st, const int16_t L_frame_old, @@ -267,7 +786,17 @@ static void init_tcx( hTcxEnc->spectrum_fx[1] = hTcxEnc->spectrum_long_fx + N_TCX10_MAX; #endif - init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, st->fscale, st->encoderLookahead_enc, st->encoderLookahead_FB, st->preemph_fac_flt, st->tcxonly, st->rf_mode, st->igf, st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, MCT_flag ); + init_tcx_cfg( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, + st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, st->fscale, st->encoderLookahead_enc, + st->encoderLookahead_FB, st->preemph_fac_flt, st->tcxonly, st->rf_mode, st->igf, + st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, MCT_flag ); + +#ifdef IVAS_FLOAT_FIXED + st->preemph_fac = (Word16) floatToFixed( st->preemph_fac_flt, Q15 ); + init_tcx_cfg_ivas_fx( st->hTcxCfg, total_brate, st->sr_core, st->input_Fs, st->L_frame, st->bwidth, hTcxEnc->L_frameTCX, + st->fscale, st->preemph_fac, st->tcxonly, st->rf_mode, st->igf, + st->hIGFEnc != NULL ? st->hIGFEnc->infoStopFrequency : 0, st->element_mode, st->ini_frame, MCT_flag ); +#endif /* Init TCX target bits correction factor */ hTcxEnc->tcx_target_bits_fac_flt = 1.0f; @@ -375,66 +904,196 @@ static void init_sig_buffers( } else if ( st->L_frame == L_FRAME16k && !st->tcxonly ) { - lerp_flt( st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); - mvr2r( st->old_inp_16k, st->buf_speech_enc_pe_flt + st->L_frame - L_INP_MEM, L_INP_MEM ); + lerp_flt( st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); + mvr2r( st->old_inp_16k, st->buf_speech_enc_pe_flt + st->L_frame - L_INP_MEM, L_INP_MEM ); + } + + st->mem_preemph_enc_flt = st->buf_speech_enc_flt[st->L_frame - 1]; + st->mem_wsp_enc_flt = st->buf_wspeech_enc_flt[st->L_frame + L_SUBFR - 1]; + } + else if ( !st->tcxonly && last_total_brate > ACELP_32k ) /* coming from TCXonly modes */ + { + mvr2r( st->old_wsp, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM ); + + /*Resamp buffers needed only for ACELP*/ + if ( st->L_frame == L_FRAME16k ) + { + lerp_flt( st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); + } + st->hLPDmem->mem_w0_flt = 0; + st->mem_wsp_enc_flt = st->buf_wspeech_enc_flt[st->L_frame + L_SUBFR - 1]; + } + + st->new_speech_enc_flt = st->buf_speech_enc_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; + st->new_speech_enc_pe_flt = st->buf_speech_enc_pe_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; + + if ( hTcxEnc != NULL ) + { + hTcxEnc->new_speech_ltp_flt = hTcxEnc->buf_speech_ltp_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; + } + + if ( st->hTcxEnc != NULL ) + { + st->hTcxEnc->new_speech_TCX_flt = st->input_buff + st->input_Fs / FRAMES_PER_SEC; /* note: in EVS st->new_speech_TCX == st->input - 0.9375ms; in IVAS st->new_speech_TCX == st->input */ + st->hTcxEnc->speech_TCX_flt = st->hTcxEnc->new_speech_TCX_flt - st->encoderLookahead_FB; + } + + st->speech_enc_flt = st->buf_speech_enc_flt + st->encoderPastSamples_enc; + st->speech_enc_pe_flt = st->buf_speech_enc_pe_flt + st->encoderPastSamples_enc; + + if ( hTcxEnc != NULL ) + { + hTcxEnc->speech_ltp_flt = hTcxEnc->buf_speech_ltp_flt + st->encoderPastSamples_enc; + } + + if ( st->element_mode > EVS_MONO ) + { + st->wspeech_enc_flt = st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR; + } + else + { + st->wspeech_enc_flt = st->buf_wspeech_enc_flt + st->L_frame + L_subfr; + } + + if ( st->ini_frame == 0 || st->L_frame != L_frame_old || st->last_codec_mode == MODE1 ) + { + set_zero( st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + } + st->synth_flt = st->buf_synth_flt + st->L_frame + L_subfr; + + return; +} + +#ifdef IVAS_FLOAT_FIXED +/*copy of evs function since it was static */ +static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_old, const Word16 L_subfr ) +{ + + LPD_state_HANDLE hLPDmem = st->hLPDmem; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + /* Encoder Past Samples at encoder-sampling-rate */ + st->encoderPastSamples_enc = shr( imult1616( st->L_frame, 9 ), 4 ); + move16(); + + /* Initialize Signal Buffers and Pointers at encoder-sampling-rate */ + IF( st->ini_frame == 0 ) + { + set16_fx( st->buf_speech_enc, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + set16_fx( st->buf_speech_enc_pe, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + if ( hTcxEnc != NULL ) + { + set16_fx( hTcxEnc->buf_speech_ltp, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); } - - st->mem_preemph_enc_flt = st->buf_speech_enc_flt[st->L_frame - 1]; - st->mem_wsp_enc_flt = st->buf_wspeech_enc_flt[st->L_frame + L_SUBFR - 1]; + set16_fx( st->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); } - else if ( !st->tcxonly && last_total_brate > ACELP_32k ) /* coming from TCXonly modes */ + ELSE { - mvr2r( st->old_wsp, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM ); + test(); + test(); + test(); + test(); + test(); + IF( NE_16( st->L_frame, L_frame_old ) && !( ( EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && ( EQ_32( st->total_brate, st->last_total_brate ) ) && ( EQ_16( st->last_bwidth, st->bwidth ) ) ) ) + { + lerp( st->buf_speech_enc, st->buf_speech_enc, st->L_frame, L_frame_old ); + test(); + IF( NE_16( st->last_core, TCX_20_CORE ) && NE_16( st->last_core, TCX_10_CORE ) ) /* condition should be checked again */ + { + Copy( st->buf_speech_enc, hTcxEnc->buf_speech_ltp, st->L_frame ); + hTcxEnc->exp_buf_speech_ltp = st->exp_buf_speech_enc; + move16(); + } - /*Resamp buffers needed only for ACELP*/ - if ( st->L_frame == L_FRAME16k ) + // Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM, sub( st->prev_Q_new, st->prev_Q_old ) ); + Copy( st->old_wsp_fx, st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM ); + st->exp_buf_wspeech_enc = st->exp_old_wsp; + move16(); + + /*Resamp buffers needed only for ACELP*/ + test(); + test(); + IF( EQ_16( st->L_frame, L_FRAME ) && !st->tcxonly ) + { + // Copy_Scale_sig( st->old_inp_12k8_fx, st->buf_speech_enc_pe + st->L_frame - L_INP_MEM, L_INP_MEM, sub( st->prev_Q_new, st->prev_Q_old ) ); + Copy( st->old_inp_12k8_fx, st->buf_speech_enc_pe + st->L_frame - L_INP_MEM, L_INP_MEM ); + st->exp_buf_speech_enc_pe = st->exp_old_inp_12k8; + move16(); + } + ELSE IF( EQ_16( st->L_frame, L_FRAME16k ) && !st->tcxonly ) + { + lerp( st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); + Copy( st->old_inp_16k_fx, st->buf_speech_enc_pe + st->L_frame - L_INP_MEM, L_INP_MEM ); + st->exp_buf_speech_enc_pe = st->exp_old_inp_16k; + move16(); + } + + st->mem_preemph_enc = st->buf_speech_enc[st->encoderPastSamples_enc + st->encoderLookahead_enc - 1]; + move16(); + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame + L_SUBFR - 1]; + move16(); + } + /*coming from TCXonly modes*/ + ELSE IF( !st->tcxonly && GE_32( st->last_total_brate, ACELP_32k ) ) { - lerp_flt( st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); + + Copy( st->old_wsp_fx, st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM ); + // Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, L_WSP_MEM, sub( st->prev_Q_new, st->prev_Q_old ) ); + + /*Resamp buffers needed only for ACELP*/ + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + lerp( st->buf_wspeech_enc + st->L_frame + L_SUBFR - L_WSP_MEM, st->buf_wspeech_enc + st->L_frame + L_SUBFR - 310, 310, L_WSP_MEM ); + } + hLPDmem->mem_w0 = 0; + move16(); + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame + L_SUBFR - 1]; + move16(); } - st->hLPDmem->mem_w0_flt = 0; - st->mem_wsp_enc_flt = st->buf_wspeech_enc_flt[st->L_frame + L_SUBFR - 1]; } - st->new_speech_enc_flt = st->buf_speech_enc_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; - st->new_speech_enc_pe_flt = st->buf_speech_enc_pe_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; - + st->new_speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc + st->encoderLookahead_enc; + st->new_speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc + st->encoderLookahead_enc; if ( hTcxEnc != NULL ) { - hTcxEnc->new_speech_ltp_flt = hTcxEnc->buf_speech_ltp_flt + st->encoderPastSamples_enc + st->encoderLookahead_enc; + hTcxEnc->new_speech_ltp = hTcxEnc->buf_speech_ltp + st->encoderPastSamples_enc + st->encoderLookahead_enc; } if ( st->hTcxEnc != NULL ) { - st->hTcxEnc->new_speech_TCX_flt = st->input_buff + st->input_Fs / FRAMES_PER_SEC; /* note: in EVS st->new_speech_TCX == st->input - 0.9375ms; in IVAS st->new_speech_TCX == st->input */ - st->hTcxEnc->speech_TCX_flt = st->hTcxEnc->new_speech_TCX_flt - st->encoderLookahead_FB; + hTcxEnc->new_speech_TCX = st->input_buff_fx + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) - NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ); + hTcxEnc->speech_TCX = hTcxEnc->new_speech_TCX - st->encoderLookahead_FB; } - - st->speech_enc_flt = st->buf_speech_enc_flt + st->encoderPastSamples_enc; - st->speech_enc_pe_flt = st->buf_speech_enc_pe_flt + st->encoderPastSamples_enc; + st->speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc; + st->speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc; if ( hTcxEnc != NULL ) { - hTcxEnc->speech_ltp_flt = hTcxEnc->buf_speech_ltp_flt + st->encoderPastSamples_enc; + hTcxEnc->speech_ltp = hTcxEnc->buf_speech_ltp + st->encoderPastSamples_enc; } - if ( st->element_mode > EVS_MONO ) + IF( GT_16( st->element_mode, EVS_MONO ) ) { - st->wspeech_enc_flt = st->buf_wspeech_enc_flt + st->L_frame + L_SUBFR; + st->wspeech_enc = st->buf_wspeech_enc + st->L_frame + L_SUBFR; } - else + ELSE { - st->wspeech_enc_flt = st->buf_wspeech_enc_flt + st->L_frame + L_subfr; + st->wspeech_enc = st->buf_wspeech_enc + st->L_frame + L_subfr; } - if ( st->ini_frame == 0 || st->L_frame != L_frame_old || st->last_codec_mode == MODE1 ) + test(); + test(); + IF( st->ini_frame == 0 || NE_16( st->L_frame, L_frame_old ) || EQ_16( st->last_codec_mode, MODE1 ) ) { - set_zero( st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + set16_fx( st->buf_synth, 0, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); } - st->synth_flt = st->buf_synth_flt + st->L_frame + L_subfr; + + st->synth = st->buf_synth + st->L_frame + L_subfr; + return; } - +#endif /*-----------------------------------------------------------------------* * init_core_sig_ana() @@ -482,7 +1141,51 @@ static void init_core_sig_ana( return; } +#ifdef IVAS_FLOAT_FIXED +static void init_core_sig_ana_ivas_fx( Encoder_State *st ) +{ + + /* Pre-emphasis factor and memory */ + + st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ + move16(); + IF( LT_16( st->fscale, ( 16000 * FSCALE_DENOM ) / 12800 ) ) + { + st->preemph_fac = PREEMPH_FAC; /*WB*/ + move16(); + } + ELSE IF( LT_16( st->fscale, ( 24000 * FSCALE_DENOM ) / 12800 ) ) + { + st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ + move16(); + } + + st->gamma = GAMMA1; + move16(); + IF( EQ_32( st->sr_core, 16000 ) ) + { + st->gamma = GAMMA16k; + move16(); + } + + + st->min_band = 1; + move16(); + st->max_band = 16; + move16(); + + IF( st->narrowBand == 0 ) + { + st->min_band = 0; + move16(); + st->max_band = 19; + move16(); + } + + return; +} +#endif /*-----------------------------------------------------------------------* * init_acelp() * @@ -706,6 +1409,291 @@ static void init_acelp( return; } +#ifdef IVAS_FLOAT_FIXED +static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 shift ) +{ + Word16 mem_syn_r_size_old; + Word16 mem_syn_r_size_new; + LPD_state_HANDLE hLPDmem = st->hLPDmem; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + /* Init pitch lag */ + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* TCX LTP ana always runs @12.8kHz */ + st->pit_res_max = initPitchLagParameters( 12800, &st->pit_min, &st->pit_fr1, &st->pit_fr1b, &st->pit_fr2, &st->pit_max ); + move16(); + } + ELSE + { + st->pit_res_max = initPitchLagParameters( st->sr_core, &st->pit_min, &st->pit_fr1, &st->pit_fr1b, &st->pit_fr2, &st->pit_max ); + move16(); + } + + /* Init LPDmem */ + IF( st->ini_frame == 0 ) + { + IF( hLPDmem != NULL ) + { + set16_fx( hLPDmem->syn, 0, 1 + M ); + set16_fx( hLPDmem->mem_syn_r, 0, L_SYN_MEM ); + } + + IF( st->hTcxEnc != NULL ) + { + set16_fx( st->hTcxEnc->Txnq, 0, L_FRAME32k / 2 + 64 ); + st->hTcxEnc->acelp_zir = st->hTcxEnc->Txnq + shr( st->L_frame, 1 ); + } + } + ELSE /*Rate switching*/ + { + IF( EQ_16( st->last_core, ACELP_CORE ) ) + { + lerp( hTcxEnc->Txnq, hTcxEnc->Txnq, shr( st->L_frame, 1 ), shr( L_frame_old, 1 ) ); + } + ELSE + { + lerp( hTcxEnc->Txnq, hTcxEnc->Txnq, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_length_old ); + } + hTcxEnc->acelp_zir = hTcxEnc->Txnq + shr( st->L_frame, 1 ); + + /* Rate switching */ + IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->element_mode, EVS_MONO ) ) + { + IF( hLPDmem != NULL ) + { + Copy( hLPDmem->mem_syn1_fx, hLPDmem->mem_syn2, M ); + set16_fx( hLPDmem->syn, 0, M ); + } + IF( st->hTcxEnc != NULL ) + { + set16_fx( hTcxEnc->Txnq, 0, L_FRAME32k / 2 + 64 ); + } + } + + /*AMR-WBIO->MODE2*/ + IF( EQ_16( st->last_core, AMR_WB_CORE ) ) + { + st->next_force_safety_net_fx = 1; + move16(); + st->last_core = ACELP_CORE; + move16(); + } + /*HQ-CORE->MODE2*/ + test(); + IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->last_core, HQ_CORE ) ) + { + /*Reset of ACELP memories*/ + st->next_force_safety_net_fx = 1; + move16(); + st->rate_switching_reset = 1; + move16(); + IF( hLPDmem != NULL ) + { + hLPDmem->tilt_code = TILT_CODE; + move16(); + set16_fx( hLPDmem->old_exc, 0, L_EXC_MEM ); + set16_fx( hLPDmem->syn, 0, 1 + M ); + hLPDmem->mem_w0 = 0; + move16(); + set16_fx( hLPDmem->mem_syn, 0, M ); + set16_fx( hLPDmem->mem_syn2, 0, M ); + } + + /* unquantized LPC*/ + test(); + test(); + test(); + IF( !( ( EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && ( EQ_32( st->total_brate, st->last_total_brate ) ) && ( EQ_16( st->last_bwidth, st->bwidth ) ) ) ) + { + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/ + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame, 0 ); + } + } + Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/ + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + st->last_core = TCX_20_CORE; + move16(); + + st->hTcxCfg->last_aldo = 1; /*It was previously ALDO*/ + st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + move16(); + /*ALDO overlap windowed past: also used in MODE1 but for other MDCT-FB*/ + set16_fx( hTcxEnc->old_out_fx, 0, st->L_frame ); + } + ELSE + { + test(); + test(); + test(); + test(); + IF( ( NE_16( st->L_frame, L_frame_old ) ) && ( LE_16( st->L_frame, L_FRAME16k ) ) && ( LE_16( L_frame_old, L_FRAME16k ) ) ) + { + /* convert quantized LSP vector */ + st->rate_switching_reset = lsp_convert_poly_fx( st->lsp_old_fx, st->L_frame, 0 ); + move16(); + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + Copy( st->lsp_old_fx, st->lspold_enc_fx, M ); + } + ELSE + { + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + + + /*Mem of deemphasis stay unchanged : hLPDmem->syn*/ + IF( hLPDmem != NULL ) + { + synth_mem_updt2( st->L_frame, st->last_L_frame, hLPDmem->old_exc, hLPDmem->mem_syn_r, hLPDmem->mem_syn2, hLPDmem->mem_syn, ENC ); + Word16 tmp, A[M + 1], Ap[M + 1], tmp_buf[M + 1]; + /* Update wsyn */ + /* lsp2a_stab( st->lsp_old, A, M ); */ + E_LPC_f_lsp_a_conversion( st->lsp_old_fx, A, M ); + weight_a_fx( A, Ap, GAMMA1, M ); + tmp = 0; + move16(); + tmp_buf[0] = 0; + move16(); + Copy( hLPDmem->mem_syn2, tmp_buf + 1, M ); + deemph_fx( tmp_buf + 1, st->preemph_fac, M, &tmp ); + Residu3_fx( Ap, tmp_buf + M, &tmp, 1, 1 ); +#ifdef BASOP_NOGLOB + hLPDmem->mem_w0 = sub_sat( shr_sat( st->wspeech_enc[-1], shift ), tmp ); + move16(); +#else + hLPDmem->mem_w0 = sub( shr( st->wspeech_enc[-1], shift ), tmp ); +#endif + } + } + ELSE IF( ( NE_16( st->L_frame, L_frame_old ) ) ) + { + /*Partial reset of ACELP memories*/ + st->next_force_safety_net_fx = 1; + move16(); + st->rate_switching_reset = 1; + move16(); + + /*reset partly some memories*/ + IF( hLPDmem != NULL ) + { + hLPDmem->tilt_code = TILT_CODE; + move16(); + set16_fx( hLPDmem->old_exc, 0, L_EXC_MEM ); + move16(); + + /*Resamp others memories*/ + /*Size of LPC syn memory*/ + /* 1.25/20.0 = 1.0/16.0 -> shift 4 to the right. */ + mem_syn_r_size_old = shr( L_frame_old, 4 ); + mem_syn_r_size_new = shr( st->L_frame, 4 ); + + lerp( hLPDmem->mem_syn_r + L_SYN_MEM - mem_syn_r_size_old, hLPDmem->mem_syn_r + L_SYN_MEM - mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + Copy( hLPDmem->mem_syn_r + L_SYN_MEM - M, hLPDmem->mem_syn, M ); + Copy( hLPDmem->mem_syn, hLPDmem->mem_syn2, M ); + + /*Untouched memories : hLPDmem->syn & hLPDmem->mem_w0*/ + hLPDmem->mem_w0 = 0; + move16(); + } + /* unquantized LPC*/ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/ + IF( EQ_16( st->L_frame, L_FRAME16k ) ) + { + lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame, 0 ); + } + Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/ + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + } + ELSE IF( !st->tcxonly && EQ_16( st->L_frame, L_FRAME16k ) && GT_32( st->last_total_brate, ACELP_32k ) ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + } + } + + test(); + test(); + if ( EQ_16( st->last_bwidth, NB ) && NE_16( st->bwidth, NB ) && st->ini_frame != 0 ) + { + st->rate_switching_reset = 1; + move16(); + } + + /* Post-processing */ + /*EVS specific*/ + /* hLPDmem->dm_fx.prev_gain_code = L_deposit_l( 0 ); + set16_fx( hLPDmem->dm_fx.prev_gain_pit, 0, 6 ); + hLPDmem->dm_fx.prev_state = 0;*/ + /*------------*/ + + if ( hLPDmem != NULL ) + { + set32_fx( hLPDmem->dispMem, 0, 8 ); + hLPDmem->gc_threshold = 0; + move16(); + } + + /* Pulse Search configuration */ + st->acelp_autocorr = 1; + move16(); + + /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/ + test(); + test(); + if ( ( LE_32( st->total_brate, ACELP_9k60 ) || st->rf_mode != 0 ) && ( EQ_32( st->sr_core, 12800 ) ) ) + { + st->acelp_autocorr = 0; + move16(); + } + + + /*BPF parameters for adjusting gain in function of background noise*/ + IF( EQ_16( st->codec_mode, MODE2 ) ) + { + /*EVS specific*/ + // st->mem_bpf_fx.lp_error_ener = L_deposit_l( 0 ); + /*------------*/ + st->pst_lp_ener_fx = 0; + move16(); + if ( EQ_16( st->last_codec_mode, MODE1 ) ) + { + /*EVS specific*/ + // st->mem_bpf_fx.lp_error = L_deposit_l( 0 ); + /*------------*/ + st->pst_mem_deemp_err_fx = 0; + move16(); + } + } + + return; +} +#endif /*-----------------------------------------------------------------------* * init_modes() * @@ -773,3 +1761,110 @@ static void init_modes( return; } + +#ifdef IVAS_FLOAT_FIXED +static void init_modes_ivas_fx( + Encoder_State *st, + const Word32 last_total_brate ) +{ + Word8 n; + Word32 tmp32; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + (void) last_total_brate; + + + /* Restrict ACE/TCX20/TCX10 mode */ + move16(); + st->restrictedMode = getRestrictedMode( st->element_mode, st->total_brate, st->Opt_AMR_WB ); + move16(); + st->acelpEnabled = 0; + move16(); + st->tcx20Enabled = 0; + move16(); + st->tcx10Enabled = 0; + + if ( EQ_16( s_and( st->restrictedMode, 1 ), 1 ) ) + { + st->acelpEnabled = 1; + move16(); + } + if ( EQ_16( s_and( st->restrictedMode, 2 ), 2 ) ) + { + st->tcx20Enabled = 1; + move16(); + } + if ( EQ_16( s_and( st->restrictedMode, 4 ), 4 ) ) + { + st->tcx10Enabled = 1; + move16(); + } + + + /* TCX mode (TCX20 TCX10_10 or NO_TCX) */ + if ( st->hTcxEnc != NULL ) + { + hTcxEnc->tcxMode = NO_TCX; + move16(); + } + + /* Bits Budget */ + /*st->bits_frame_nominal = (int)( (float)st->L_frame * (float)FSCALE_DENOM * (float)st->bitrate / ( (float)st->fscale * 12800.0f ) );*/ + /*st->bits_frame_nominal = (int)( (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f );*/ + /*328 = 0.010009765625 in 0Q15*/ + /* st->bits_frame_nominal = extract_h(L_add(L_mult(div_l(L_mult(shl(st->L_frame,2),st->bitrate),st->fscale),328),16056)); */ + + /* st->bits_frame_nominal = (int)( (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f ); */ + tmp32 = L_shl( st->total_brate, 1 ); /* (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate */ + st->bits_frame_nominal = extract_l( L_shr( Mpy_32_16_1( tmp32, 20972 ), 6 ) ); /* 20972 = 0.01 * 64 * 32768 */ + move16(); + + IF( st->Opt_AMR_WB ) + { + st->bits_frame = st->bits_frame_nominal; + move16(); + st->bits_frame_core = st->bits_frame_nominal; + move16(); + st->frame_size_index = 0; + move16(); + } + ELSE + { + FOR( n = 0; n < FRAME_SIZE_NB; n++ ) + { + IF( LT_32( n, FRAME_SIZE_NB - 1 ) ) + { + test(); + IF( FrameSizeConfig[n].frame_bits <= st->bits_frame_nominal && FrameSizeConfig[n + 1].frame_bits > st->bits_frame_nominal ) + { + st->frame_size_index = n; + move16(); + st->bits_frame = st->bits_frame_nominal; + move16(); + st->bits_frame_core = st->bits_frame_nominal - FrameSizeConfig[n].transmission_bits - FrameSizeConfig[n].bandwidth_bits - FrameSizeConfig[n].reserved_bits; + move16(); + BREAK; + } + } + ELSE + { + IF( FrameSizeConfig[n].frame_bits <= st->bits_frame_nominal ) + { + st->frame_size_index = n; + move16(); + st->bits_frame = st->bits_frame_nominal; + move16(); + st->bits_frame_core = st->bits_frame_nominal - FrameSizeConfig[n].transmission_bits - FrameSizeConfig[n].bandwidth_bits - FrameSizeConfig[n].reserved_bits; + move16(); + BREAK; + } + } + } + } + + /* Reconfigure core */ + core_coder_reconfig_ivas_fx( st ); + + + return; +} +#endif diff --git a/lib_enc/core_enc_reconf.c b/lib_enc/core_enc_reconf.c index 67238f036306394659e80ce7c6c311ca3e89117b..31ad5d4a0b4e06baa9fa0bde26ffc3647f394985 100644 --- a/lib_enc/core_enc_reconf.c +++ b/lib_enc/core_enc_reconf.c @@ -40,6 +40,7 @@ #include "rom_com.h" #include "rom_enc.h" #include "wmc_auto.h" +#include "prot_fx.h" /*-----------------------------------------------------------------* * Funtion core_coder_reconfig * @@ -236,3 +237,300 @@ void core_coder_reconfig( return; } + +#ifdef IVAS_FLOAT_FIXED +void core_coder_reconfig_ivas_fx( + Encoder_State *st ) +{ + Word16 i, bwidth, index; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + /*Configuration of ACELP*/ + BITS_ALLOC_init_config_acelp( st->total_brate, st->narrowBand, st->nb_subfr, &( st->acelp_cfg ) ); + + /*Configuration of partial copy*/ + IF( st->Opt_RF_ON ) + { + st->hRF->acelp_cfg_rf.mode_index = 1; + st->hRF->acelp_cfg_rf.midLpc = 0; + st->hRF->acelp_cfg_rf.midLpc_enable = 0; + st->hRF->acelp_cfg_rf.pre_emphasis = 0; + st->hRF->acelp_cfg_rf.formant_enh = 1; + st->hRF->acelp_cfg_rf.formant_tilt = 1; + st->hRF->acelp_cfg_rf.voice_tilt = 1; + st->hRF->acelp_cfg_rf.formant_enh_num = FORMANT_SHARPENING_G1; + st->hRF->acelp_cfg_rf.formant_enh_den = FORMANT_SHARPENING_G2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + st->nb_bits_header_tcx = 2; /* signal class */ + move16(); + } + ELSE IF( st->tcxonly ) + { + st->nb_bits_header_tcx = 1 + 1; /*TCX20/TCX10 + last_core*/ + st->nb_bits_header_tcx = add( st->nb_bits_header_tcx, 2 ); /* Siganl class*/ + move16(); + move16(); + } + ELSE + { + st->nb_bits_header_ace = 1 + 2 + 1; /*TCX/ACELP+coder_type + last_core*/ + st->nb_bits_header_tcx = st->nb_bits_header_ace; + move16(); + move16(); + + IF( st->hTcxCfg != NULL ) + { + IF( st->hTcxCfg->lfacNext <= 0 ) + { + st->nb_bits_header_ace = sub( st->nb_bits_header_ace, 1 ); /*No last_core*/ + move16(); + } + } + } + + + /*Switch off TCX or ACELP?*/ + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->acelpEnabled = (Word16) EQ_16( ( s_and( st->restrictedMode, 1 ) ), 1 ); + st->tcx20Enabled = (Word16) EQ_16( ( s_and( st->restrictedMode, 2 ) ), 2 ); + move16(); + move16(); + } + st->prevEnergyHF_fx = st->currEnergyHF_fx = 1073725440l /*65535.0f Q14*/; /* prevent block switch */ + st->currEnergyHF_e_fx = 17; + move32(); + move16(); + + /*Sanity check : don't need to be instrumented*/ + IF( st->tcxonly == 0 ) + { + assert( st->acelpEnabled || st->tcx20Enabled || st->frame_size_index == 0 ); + } + ELSE + { + assert( st->tcx10Enabled || st->tcx20Enabled || st->frame_size_index == 0 ); + } + + /* TCX-LTP */ + IF( st->hTcxEnc != NULL ) + { + hTcxEnc->tcxltp = getTcxLtp( st->sr_core ); + move16(); + } + + /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/ + + st->acelp_autocorr = 1; + move16(); + + test(); + if ( ( LE_32( st->total_brate, ACELP_9k60 ) ) && ( EQ_32( st->sr_core, INT_FS_12k8 ) ) ) + { + st->acelp_autocorr = 0; + move16(); + } + + /*Get bandwidth mode*/ + IF( st->narrowBand ) + { + move16(); + bwidth = NB; + } + ELSE IF( LE_32( st->sr_core, INT_FS_16k ) ) + { + move16(); + bwidth = WB; + } + ELSE + { + move16(); + bwidth = SWB; + } + + /*Scale TCX for non-active frames to adjust loudness with ACELP*/ + IF( st->hTcxCfg != NULL ) + { + st->hTcxCfg->na_scale = 32767 /*1.0f Q15*/; + move16(); + + test(); + IF( LT_16( bwidth, 2 ) && ( st->tcxonly == 0 ) ) + { + /*const Word16 scaleTableSize = sizeof(scaleTcxTable) / sizeof(scaleTcxTable[0]);*/ + + FOR( i = 0; i < SIZE_SCALE_TABLE_TCX; i++ ) + { + + test(); + test(); + IF( EQ_16( bwidth, scaleTcxTable[i].bwmode ) && + GE_32( st->total_brate, scaleTcxTable[i].bitrateFrom ) && + LT_32( st->total_brate, scaleTcxTable[i].bitrateTo ) ) + { + if ( st->rf_mode ) + { + i = sub( i, 1 ); + } + move16(); + st->hTcxCfg->na_scale = scaleTcxTable[i].scale; + BREAK; + } + } + } + } + st->enableTcxLpc = 0; + move16(); + IF( GT_16( st->element_mode, IVAS_SCE ) ) + { + test(); + test(); + st->enableTcxLpc = ( EQ_16( st->lpcQuantization, 1 ) && ( LE_32( st->total_brate, LOWRATE_TCXLPC_MAX_BR_CPE ) || st->rf_mode ) ); + move16(); + } + ELSE + { + test(); + test(); + if ( EQ_16( st->lpcQuantization, 1 ) && ( LE_32( st->total_brate, LOWRATE_TCXLPC_MAX_BR ) || st->rf_mode != 0 ) ) + { + st->enableTcxLpc = 1; + move16(); + } + } + test(); + IF( st->ini_frame == 0 || EQ_16( st->last_codec_mode, MODE1 ) ) + { + st->envWeighted = 0; + move16(); + } + + test(); + test(); + test(); + IF( EQ_16( st->bwidth, SWB ) && + ( EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && st->element_mode == EVS_MONO ) + { + IF( st->tec_tfa == 0 ) + { + FOR( i = 0; i < MAX_TEC_SMOOTHING_DEG; i++ ) + { + st->hTECEnc->loBuffer[i] = 0; + move16(); + } + } + st->tec_tfa = 1; + move16(); + } + ELSE + { + st->tec_tfa = 0; + move16(); + } + + st->enablePlcWaveadjust = 0; + move16(); + if ( GE_32( st->total_brate, HQ_48k ) ) + { + st->enablePlcWaveadjust = 1; + move16(); + } + + + move16(); + st->glr = 0; + test(); + test(); + test(); + if ( ( EQ_32( st->total_brate, ACELP_9k60 ) || EQ_32( st->total_brate, ACELP_16k40 ) || EQ_32( st->total_brate, ACELP_24k40 ) ) && EQ_16( st->element_mode, EVS_MONO ) ) + { + move16(); + st->glr = 1; + } + + IF( st->glr ) + { + move16(); + st->nb_bits_header_ace = add( st->nb_bits_header_ace, G_LPC_RECOVERY_BITS ); + } + IF( hTcxEnc != NULL ) + { + test(); + IF( EQ_16( st->bwidth, NB ) || EQ_16( st->bwidth, WB ) ) + { + IF( st->rf_mode == 0 ) + { + index = s_min( N_TCX_STARTLINE_NOISE_WB - 1, s_max( 3, st->frame_size_index ) ); + } + ELSE + { + index = s_min( N_TCX_STARTLINE_NOISE_WB - 1, s_max( 3, st->frame_size_index - 1 ) ); + } + hTcxEnc->nmStartLine = startLineWB[index]; + move16(); + } + ELSE /* (st->bwidth == SWB || st->bwidth == FB) */ + { + IF( st->rf_mode == 0 ) + { + index = s_min( N_TCX_STARTLINE_NOISE_SWB - 1, sub( s_max( 3, st->frame_size_index ), 3 ) ); + } + ELSE + { + index = s_min( N_TCX_STARTLINE_NOISE_SWB - 1, sub( s_max( 3, st->frame_size_index - 1 ), 3 ) ); + } + test(); + test(); + if ( GE_32( st->total_brate, IVAS_96k ) && LE_32( st->total_brate, IVAS_192k ) && GT_16( st->element_mode, IVAS_SCE ) ) + { + index = sub( index, 1 ); + } + hTcxEnc->nmStartLine = startLineSWB[index]; + move16(); + test(); + test(); + if ( EQ_32( st->total_brate, IVAS_48k ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) && LT_16( add( hTcxEnc->nmStartLine, shl( hTcxEnc->nmStartLine, 2 ) ), shl( st->L_frame, 2 ) ) ) + { + hTcxEnc->nmStartLine = shr( add( hTcxEnc->nmStartLine, shl( hTcxEnc->nmStartLine, 2 ) ), 2 ); /* low-rate stereo is more efficient than dual-mono due to stereo processing */ + move16(); + } + } + } + + IF( hTcxEnc != NULL ) + { + test(); + test(); + test(); + test(); + test(); + IF( ( LT_32( st->total_brate, ACELP_24k40 ) ) && ( ( GT_32( st->total_brate, st->last_total_brate ) ) || ( EQ_16( st->last_codec_mode, MODE1 ) ) ) ) + { + /* low-freq memQuantZeros_fx must be reset partially if bitrate increased */ + FOR( i = 0; i < hTcxEnc->nmStartLine; i++ ) + { + hTcxEnc->memQuantZeros[i] = 0; + move16(); + } + } + ELSE IF( ( GE_32( st->total_brate, ACELP_24k40 ) ) && ( LE_32( st->total_brate, ACELP_32k ) ) && ( GE_32( st->last_total_brate, ACELP_13k20 ) ) && ( LT_32( st->last_total_brate, ACELP_24k40 ) ) ) + { + FOR( i = 0; i < st->L_frame; i++ ) /* memQuantZeros_fx won't be updated */ + { + hTcxEnc->memQuantZeros[i] = 0; + move16(); + } + } + } +} +#endif diff --git a/lib_enc/core_enc_reconf_fx.c b/lib_enc/core_enc_reconf_fx.c index c4e4b16cd6a9694998664d9b34fa9cd1802c6f00..c11dd9959af47ec89ff3c687936dd24f2926d496 100644 --- a/lib_enc/core_enc_reconf_fx.c +++ b/lib_enc/core_enc_reconf_fx.c @@ -50,6 +50,7 @@ void core_coder_reconfig_fx( move16(); move16(); move16(); + move16(); } st->nb_bits_header_tcx = 2; /*Mode(1) + Last_mode(1)*/ move16(); diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c index 93aca7e0d6a79cdf17053993660509a7ac3cc3cc..e13e3e4d7f6e2ec9925b2db8954bf184c7405d0b 100644 --- a/lib_enc/core_enc_switch.c +++ b/lib_enc/core_enc_switch.c @@ -149,7 +149,11 @@ void core_coder_mode_switch( else { st->igf = getIgfPresent( st->element_mode, st->total_brate, st->bwidth, st->rf_mode ); +#ifdef IVAS_FLOAT_FIXED + init_coder_ace_plus_ivas_fx( st, last_total_brate, MCT_flag ); +#else init_coder_ace_plus( st, last_total_brate, MCT_flag ); +#endif } if ( st->igf && st->hBWE_TD != NULL ) diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 0315a8c5cfdadcb093ad29703b57aad3e050d526..7fa5ed9f0ef5920d63325eafa41637cc80ac2b7f 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -3243,6 +3243,98 @@ void IGFEncSetMode( return; } +#ifdef IVAS_FLOAT_FIXED +void IGFEncSetMode_ivas_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word32 total_brate, /* i : encoder total bitrate */ + const Word16 bwidth, /* i : encoder audio bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Word16 i; + + hPrivateData = &hIGFEnc->igfData; + hPrivateData->igfBitstreamBits = 0; + move16(); + set16_fx( hPrivateData->igfScfQuantized, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES ); + set16_fx( hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES ); + set16_fx( hPrivateData->igfWhiteningHangoverCnt, 0, IGF_MAX_TILES ); + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + set16_fx( hPrivateData->igfPastSFM_fx[i], -( ONE_IN_Q13 ), IGF_PAST_SFM_LEN ); + } + + hPrivateData->igfPastSFM_pos = 0; + move16(); + + FOR( i = 0; i < IGF_BITBUFSIZE / 8; i++ ) + { + hPrivateData->igfBitstream[i] = 0; + move16(); + } + hPrivateData->wasTransient = 0; + move16(); + set32_fx( hPrivateData->prevSFM_FIR, 0, IGF_MAX_TILES ); + set16_fx( hPrivateData->prevSFM_IIR, 0, IGF_MAX_TILES ); + set16_fx( hPrivateData->dampingFactorSmoothing, 2, IGF_MAX_SFB ); + set16_fx( hPrivateData->prevSFM_FIR_SFB_SB_fx, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->prevSFM_IIR_SFB_SB_fx, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->prevSFM_FIR_SFB_TB_fx, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->prevSFM_IIR_SFB_TB_fx, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->prevDampingFactor_IIR_fx, -( ONE_IN_Q15 ), IGF_MAX_SFB ); + set16_fx( hPrivateData->logSpec, 0, L_FRAME_PLUS ); + set16_fx( hPrivateData->SFM_sb_fx, 0, IGF_MAX_SFB ); + set16_fx( hPrivateData->SFM_tb_fx, 0, IGF_MAX_SFB ); + + IF( IGFCommonFuncsIGFConfiguration_ivas_fx( total_brate, bwidth, element_mode, &hPrivateData->igfInfo, rf_mode ) != 0 ) + { + IGFSCFEncoderOpen_fx( &hPrivateData->hIGFSCFArithEnc, &hPrivateData->igfInfo, total_brate, bwidth, element_mode, rf_mode ); + + hIGFEnc->infoSamplingRate = hPrivateData->igfInfo.sampleRate; + move32(); + hIGFEnc->infoStartFrequency = hPrivateData->igfInfo.grid[0].startFrequency; + move16(); + hIGFEnc->infoStopFrequency = hPrivateData->igfInfo.grid[0].stopFrequency; + move16(); + hIGFEnc->infoStartLine = hPrivateData->igfInfo.grid[0].startLine; + move16(); + hIGFEnc->infoStopLine = hPrivateData->igfInfo.grid[0].stopLine; + move16(); + } + ELSE + { + /* IGF configuration failed -> error! */ + hIGFEnc->infoSamplingRate = 0; + move32(); + hIGFEnc->infoStartFrequency = -1; + move16(); + hIGFEnc->infoStopFrequency = -1; + move16(); + hIGFEnc->infoStartLine = -1; + move16(); + hIGFEnc->infoStopLine = -1; + move16(); + fprintf( stderr, "IGFEncSetMode_fx: initialization error!\n" ); + } + + /* reset remaining variables */ + hIGFEnc->infoTotalBitsWritten = 0; + move16(); + hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + hIGFEnc->flatteningTrigger = 0; + move16(); + hIGFEnc->spec_be_igf_e = 0; + move16(); + hIGFEnc->tns_predictionGain = 0; + move16(); + set32_fx( hIGFEnc->spec_be_igf, 0, N_MAX_TCX - IGF_START_MN ); + return; +} +#endif /*-------------------------------------------------------------------* * pack_bit_ivas() diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 3c16f3924cb7d8965fc4ffe881a28ce16159f425..2e9c14ee27a655728468de749624ef69006e1bee 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -427,7 +427,62 @@ ivas_error ivas_core_enc( if ( n == 0 && input_Fs >= 32000 && hStereoICBWE != NULL ) { +#ifdef IVAS_FLOAT_FIXED + Word16 inp0_fx[L_FRAME48k], inp1_fx[L_FRAME48k]; + Word16 new_swb_speech_buffer_fx16[L_FRAME48k + STEREO_DFT_OVL_MAX]; + Word16 q_new_swb_speech_buffer = Q_factor_arr( new_swb_speech_buffer, input_frame ); + floatToFixed_arr16( new_swb_speech_buffer, new_swb_speech_buffer_fx16, q_new_swb_speech_buffer, input_frame ); + + hCPE->hStereoICBWE->dataChan_fx[0] = inp0_fx; + hCPE->hStereoICBWE->dataChan_fx[1] = inp1_fx; + hCPE->hStereoTCA->targetGain_fx = floatToFixed( hCPE->hStereoTCA->targetGain, Q29 ); + + Word16 scale_factor = Q_factor_arr( hCPE->hStereoICBWE->dataChan[0], input_frame ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->dataChan[1], input_frame ) ); + scale_factor = min( scale_factor, Q_factor_arr( &hCPE->hStereoICBWE->memHPF[0], 4 ) ); + scale_factor = min( scale_factor, Q_factor_arr( &hCPE->hStereoICBWE->memHPF[4], 4 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->dec_2over3_mem, 12 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->dec_2over3_mem_lp, 3 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->memModifyFs_icbwe[0], 60 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->memModifyFs_icbwe[1], 60 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->icbwe_inp_mem[0], 270 ) ); + scale_factor = min( scale_factor, Q_factor_arr( hCPE->hStereoICBWE->icbwe_inp_mem[1], 270 ) ); + hCPE->hStereoICBWE->q_dataChan_fx = scale_factor; + floatToFixed_arr16( hCPE->hStereoICBWE->dataChan[0], inp0_fx, scale_factor, input_frame ); + floatToFixed_arr16( hCPE->hStereoICBWE->dataChan[1], inp1_fx, scale_factor, input_frame ); + floatToFixed_arr16( &hCPE->hStereoICBWE->memHPF[0], &hCPE->hStereoICBWE->memHPF_fx[0], scale_factor, 4 ); + floatToFixed_arr16( &hCPE->hStereoICBWE->memHPF[4], &hCPE->hStereoICBWE->memHPF_fx[4], scale_factor, 4 ); + floatToFixed_arr16( hCPE->hStereoICBWE->dec_2over3_mem, hCPE->hStereoICBWE->dec_2over3_mem_fx, scale_factor, 12 ); + floatToFixed_arr16( hCPE->hStereoICBWE->dec_2over3_mem_lp, hCPE->hStereoICBWE->dec_2over3_mem_lp_fx, scale_factor, 3 ); + floatToFixed_arr16( hCPE->hStereoICBWE->memModifyFs_icbwe[0], hCPE->hStereoICBWE->memModifyFs_icbwe_fx[0], scale_factor, 60 ); + floatToFixed_arr16( hCPE->hStereoICBWE->memModifyFs_icbwe[1], hCPE->hStereoICBWE->memModifyFs_icbwe_fx[1], scale_factor, 60 ); + floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[0], hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], scale_factor, 270 ); + floatToFixed_arr16( hCPE->hStereoICBWE->icbwe_inp_mem[1], hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], scale_factor, 270 ); + + floatToFixed_arr16( hCPE->hStereoICBWE->mem_decim_shb_ch0, hCPE->hStereoICBWE->mem_decim_shb_ch0_fx, 0, 90 ); + + + stereo_icBWE_preproc_fx( hCPE, input_frame, new_swb_speech_buffer_fx16 /*tmp buffer*/, q_new_swb_speech_buffer ); + + + fixedToFloat_arr( new_swb_speech_buffer_fx16, new_swb_speech_buffer, q_new_swb_speech_buffer, input_frame ); + + fixedToFloat_arr( inp0_fx, hCPE->hStereoICBWE->dataChan[0], scale_factor, input_frame ); + fixedToFloat_arr( inp1_fx, hCPE->hStereoICBWE->dataChan[1], scale_factor, input_frame ); + fixedToFloat_arr( &hCPE->hStereoICBWE->memHPF_fx[0], &hCPE->hStereoICBWE->memHPF[0], scale_factor, 4 ); + fixedToFloat_arr( &hCPE->hStereoICBWE->memHPF_fx[4], &hCPE->hStereoICBWE->memHPF[4], scale_factor, 4 ); + fixedToFloat_arr( hCPE->hStereoICBWE->dec_2over3_mem_fx, hCPE->hStereoICBWE->dec_2over3_mem, scale_factor, 12 ); + fixedToFloat_arr( hCPE->hStereoICBWE->dec_2over3_mem_lp_fx, hCPE->hStereoICBWE->dec_2over3_mem_lp, scale_factor, 3 ); + fixedToFloat_arr( hCPE->hStereoICBWE->memModifyFs_icbwe_fx[0], hCPE->hStereoICBWE->memModifyFs_icbwe[0], scale_factor, 60 ); + fixedToFloat_arr( hCPE->hStereoICBWE->memModifyFs_icbwe_fx[1], hCPE->hStereoICBWE->memModifyFs_icbwe[1], scale_factor, 60 ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], hCPE->hStereoICBWE->icbwe_inp_mem[0], scale_factor, 270 ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], hCPE->hStereoICBWE->icbwe_inp_mem[1], scale_factor, 270 ); + + fixedToFloat_arr( hCPE->hStereoICBWE->mem_decim_shb_ch0_fx, hCPE->hStereoICBWE->mem_decim_shb_ch0, 0, 90 ); + +#else stereo_icBWE_preproc( hCPE, input_frame, new_swb_speech_buffer /*tmp buffer*/ ); +#endif // IVAS_FLOAT_FIXED stereo_icBWE_enc( hCPE, shb_speech, new_swb_speech_buffer, voice_factors[0] ); } diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index e2757647a14c224fbc9f01bad11a10862555d83c..484abca22ffb48cbe788b4f647b26239a1e1308f 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -484,7 +484,7 @@ ivas_error ivas_mct_enc( hCPE->hCoreCoder[0]->hBstr->ind_list = st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->ind_list + st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->nb_ind_tot; } - ivas_mdct_quant_coder( hCPE, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); + ivas_mdct_quant_coder_fx( hCPE, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); /* update input samples buffer (as done in ivas_cpe_enc() for other than MCT coding) */ FOR( n = 0; n < CPE_CHANNELS; n++ ) diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index e291f7e04a7c0eaa0d910fedf3006289a16e079e..ba641ef8618eef4e669e8a957320bf1618c5d658 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -527,7 +527,35 @@ static uint16_t enc_ste_pre_mdct( * * write igf parameters to bitstream *---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void enc_prm_igf_mdct( + Encoder_State *st, /* i : Encoder state handle */ + BSTR_ENC_HANDLE hBstr /* i/o: Bitstream handle */ +) +{ + Word16 nbits_start, total_nbbits; + nbits_start = hBstr->nb_bits_tot; + move16(); + + IF( EQ_16( st->core, TCX_20_CORE ) ) + { + st->hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + + IGFEncWriteBitstream_ivas_fx( st->hIGFEnc, hBstr, &st->hIGFEnc->infoTotalBitsPerFrameWritten, ( st->last_core == ACELP_CORE ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM, 1 ); + } + ELSE + { + IGFEncWriteConcatenatedBitstream_ivas_fx( st->hIGFEnc, hBstr ); + } + + total_nbbits = sub( hBstr->nb_bits_tot, nbits_start ); + st->side_bits_frame_channel = add( st->side_bits_frame_channel, total_nbbits ); + + return; +} +#else void enc_prm_igf_mdct( Encoder_State *st, /* i : Encoder state handle */ BSTR_ENC_HANDLE hBstr /* i/o: Bitstream handle */ @@ -553,7 +581,7 @@ void enc_prm_igf_mdct( return; } - +#endif /*-------------------------------------------------------------------* * ivas_mdct_core_whitening_enc() @@ -677,6 +705,7 @@ void ivas_mdct_core_whitening_enc( IF( st->hTcxEnc ) { st->hTcxEnc->tfm_mem_fx = floatToFixed_32( st->hTcxEnc->tfm_mem, Q31 ); + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); } #endif SetTCXModeInfo_ivas_fx( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); @@ -1303,6 +1332,7 @@ void ivas_mdct_quant_coder( push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { set_f( fac_ns[ch], 0.0f, NB_DIV ); @@ -1316,7 +1346,6 @@ void ivas_mdct_quant_coder( { quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; - st = sts[ch]; if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) @@ -1425,7 +1454,214 @@ void ivas_mdct_quant_coder( pop_wmops(); return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_mdct_quant_coder_fx( + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) +{ + Encoder_State *st, **sts; + int16_t bitsAvailable, target_bits, nSubframes, ch, n; + int16_t L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ + int16_t L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ + int16_t L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ + int16_t tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ + int16_t noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + float fac_ns[CPE_CHANNELS][NB_DIV]; /* noise filling level */ + int16_t nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ + int16_t hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ + float ener[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ + float gain_tcx[CPE_CHANNELS][NB_DIV]; /* global gain */ + float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ + float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; + int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; + int16_t ignore_chan[CPE_CHANNELS]; + int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; + int16_t nbits_start, total_nbbits; +#ifdef IVAS_FLOAT_FIXED + Word16 fac_ns_fx[CPE_CHANNELS][NB_DIV]; /* noise filling level */ + Word16 ener_fx[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ + Word16 gain_tcx_fx[CPE_CHANNELS][NB_DIV]; /* global gain */ + Word16 gain_tcx_e; + Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ + Word32 *quantized_spectrum_fx[CPE_CHANNELS][NB_DIV]; +#endif + push_wmops( "mdct_core_Q" ); + sts = hCPE->hCoreCoder; + +#ifdef IVAS_FLOAT_FIXED + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + set16_fx( fac_ns_fx[ch], 0, NB_DIV ); + set16_fx( nf_seed[ch], 0, NB_DIV ); + set16_fx( hm_active[ch], 0, NB_DIV ); + set16_fx( ener_fx[ch], 0, NB_DIV ); + set16_fx( gain_tcx_fx[ch], 0, NB_DIV ); + set16_fx( L_frame[ch], 0, NB_DIV ); + } +#endif + + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + set_f( fac_ns[ch], 0.0f, NB_DIV ); + set_s( nf_seed[ch], 0, NB_DIV ); + set_s( hm_active[ch], 0, NB_DIV ); + set_f( ener[ch], 0.0f, NB_DIV ); + set_f( gain_tcx[ch], 0.0f, NB_DIV ); + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; + quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; +#ifdef IVAS_FLOAT_FIXED + quantized_spectrum_fx[ch][0] = quantized_spectrum_long_fx[ch]; + quantized_spectrum_fx[ch][1] = quantized_spectrum_long_fx[ch] + N_TCX10_MAX; +#endif + st = sts[ch]; + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + ignore_chan[ch] = 1; + continue; + } + + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + ignore_chan[ch] = 0; + + bitsAvailable = st->bits_frame_channel + nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ) + tnsBits[ch][0] + tnsBits[ch][1]; + + /* calculate TCX10 target bits before to assure minimum amount is distributed between subframes */ + if ( st->hTcxEnc->tcxMode == TCX_10 ) + { + int16_t nTnsBitsTCX10Tmp[2]; + nTnsBitsTCX10Tmp[0] = tnsBits[ch][0]; + nTnsBitsTCX10Tmp[1] = tnsBits[ch][1]; + + ivas_mdct_tcx10_bit_distribution( target_bitsTCX10[ch], bitsAvailable, nTnsBitsTCX10Tmp ); + } + for ( n = 0; n < nSubframes; n++ ) + { + if ( nSubframes == 2 ) + { + target_bits = target_bitsTCX10[ch][n]; + } + else + { + target_bits = bitsAvailable / nSubframes - tnsBits[ch][n]; + } + + assert( target_bits >= NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL + SMDCT_MINIMUM_ARITH_BITS ); + + /*-----------------------------------------------------------* + * Quantize the MDCT spectrum * + *-----------------------------------------------------------*/ + + QuantizeTCXSpectrum( st, n, st->hTcxEnc->spectrum[n], NULL, NULL, tnsSize[ch][n], target_bits, 0, &L_frameTCX[ch][n], + &L_frame[ch][n], &L_spec[ch][n], &tcx_offset[ch][n], &noiseFillingBorder[ch][n], quantized_spectrum[ch][n], NULL, + &hm_active[ch][n], NULL, &nf_seed[ch][n], &ener[ch][n], &gain_tcx[ch][n], param_core[ch] + n * NPRM_DIV ); + } + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); + st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], L_frame[ch][0] ) - 4 ); + st->hTcxEnc->spectrum_e[1] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[1], L_frame[ch][1] ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); + floatToFixed_arrL( st->hTcxEnc->spectrum[1], st->hTcxEnc->spectrum_fx[1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); + + floatToFixed_arrL( quantized_spectrum[ch][0], quantized_spectrum_fx[ch][0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); + floatToFixed_arrL( quantized_spectrum[ch][1], quantized_spectrum_fx[ch][1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); + } + gain_tcx_e = Q_factor_arr( gain_tcx[0], NB_DIV ); + gain_tcx_e = 15 - min( gain_tcx_e, Q_factor_arr( gain_tcx[1], NB_DIV ) ); + floatToFixed_arr( gain_tcx[0], gain_tcx_fx[0], 15 - gain_tcx_e, NB_DIV ); + floatToFixed_arr( gain_tcx[1], gain_tcx_fx[1], 15 - gain_tcx_e, NB_DIV ); +#endif + + EstimateStereoTCXNoiseLevel_fx( sts, quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns_fx, param_core, MCT_flag ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( fac_ns[0], fac_ns_fx[0], Q15, NB_DIV ); + floatToFixed_arr( fac_ns[1], fac_ns_fx[1], Q15, NB_DIV ); +#endif +#else + EstimateStereoTCXNoiseLevel( sts, quantized_spectrum, gain_tcx, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns, param_core, MCT_flag ); +#endif + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + /* update the pointer to the buffer of indices of the second channel */ + if ( ch > 0 ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + /*Enable appropriate upadte of tcx_curr_overlap_mode even for uncoded channel index 1*/ + L_frameTCX[ch][0] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; + L_frameTCX[ch][1] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; + + L_frame[ch][0] = st->L_frame; + L_frame[ch][1] = st->L_frame; + } + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + /* Update L_frame_past */ + st->L_frame_past = L_frame[ch][n]; + + /* Update overlap */ + if ( ( ( ( L_frameTCX[ch][n] == st->hTcxEnc->L_frameTCX >> 1 ) && n > 0 ) || ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) + { + st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + } + } + + /*--------------------------------------------------------------* + * Generate Bitstream + *---------------------------------------------------------------*/ + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + nbits_start = st->hBstr->nb_bits_tot; + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); +#endif + + writeTCXparam_fx( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); +#else + writeTCXparam( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); +#endif + + total_nbbits = st->hBstr->nb_bits_tot - nbits_start - nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); + + assert( st->bits_frame_channel == total_nbbits ); + } + + pop_wmops(); + return; +} +#endif /*--------------------------------------------------------------* * init_tcx_enc_info() diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 8fb7d711478807ec48c700269649fe253ab05915..d843afc7078ab19786ed7ad26cb4ebaf44952bd3 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -551,9 +551,9 @@ typedef struct stereo_tca_enc_data_structure float prevTargetGain; /* gain norm applied on target (or right) channel in previous frame */ float corrStatsSmoothFac; /* gD/corrStats smoothing based on corrStats */ - Word16 targetGain_fx; /* gain norm applied on target (or right) channel in current frame //Q15*/ - Word16 instTargetGain_fx; /* instantaneous gain norm applied on target (or right) channel in current frame //Q15*/ - Word16 prevTargetGain_fx; /* gain norm applied on target (or right) channel in previous frame //Q15*/ + Word32 targetGain_fx; /* gain norm applied on target (or right) channel in current frame //Q29 take from decoder*/ + Word32 instTargetGain_fx; /* instantaneous gain norm applied on target (or right) channel in current frame //Q29*/ + Word32 prevTargetGain_fx; /* gain norm applied on target (or right) channel in previous frame //Q29 taken from decoder*/ Word16 corrStatsSmoothFac_fx; /* gD/corrStats smoothing based on corrStats //Q15*/ Word16 lMemRecalc; @@ -647,8 +647,8 @@ typedef struct stereo_icbwe_enc_data_structure float mixExc16k[L_FRAME16k]; float lpSHBRef[LPC_SHB_ORDER + 1]; - Word32 memHPF_fx[8]; - Word32 mem_decim_shb_ch0_fx[2 * L_FILT_MAX]; + Word16 memHPF_fx[8]; // Q -> q_dataChan_fx + Word16 mem_decim_shb_ch0_fx[2 * L_FILT_MAX]; // Q0 Word32 mem_shb_speech_ref_fx[L_LOOK_16k]; Word32 mem_shb_speech_nonref_fx[L_LOOK_16k]; Word32 mem_lpc_shbsynth_nonref_fx[LPC_SHB_ORDER]; @@ -656,14 +656,15 @@ typedef struct stereo_icbwe_enc_data_structure Word32 memShbSpecMapping_fx; Word32 memShbSpecXcorr_fx[6]; Word32 prevgsMapping_fx; - Word32 prevRefEner_fx; // Q31 - Word32 prevNonRefEner_fx; // Q31 - Word32 memGsEnerMap_fx[2]; // Q31 - Word32 dec_2over3_mem_fx[L_FILT_2OVER3]; - Word32 dec_2over3_mem_lp_fx[L_FILT_2OVER3_LP]; - Word32 icbwe_inp_mem_fx[CPE_CHANNELS][NS2SA( 48000, L_MEM_RECALC_TBE_NS )]; - Word32 *dataChan_fx[CPE_CHANNELS]; - Word32 memModifyFs_icbwe_fx[CPE_CHANNELS][2 * L_FILT32k]; + Word32 prevRefEner_fx; // Q31 + Word32 prevNonRefEner_fx; // Q31 + Word32 memGsEnerMap_fx[2]; // Q31 + Word16 dec_2over3_mem_fx[L_FILT_2OVER3]; // Q -> q_dataChan_fx + Word16 dec_2over3_mem_lp_fx[L_FILT_2OVER3_LP]; // Q -> q_dataChan_fx + Word16 icbwe_inp_mem_fx[CPE_CHANNELS][NS2SA( 48000, L_MEM_RECALC_TBE_NS )]; // Q -> q_dataChan_fx + Word16 *dataChan_fx[CPE_CHANNELS]; + Word16 q_dataChan_fx; + Word16 memModifyFs_icbwe_fx[CPE_CHANNELS][2 * L_FILT32k]; // Q -> q_dataChan_fx Word32 mem_nrg_L_fx[CPE_CHANNELS]; Word32 mem_nrg_R_fx[CPE_CHANNELS]; Word32 mem_nrg_DMX_fx[CPE_CHANNELS]; diff --git a/lib_enc/ivas_stereo_ica_enc.c b/lib_enc/ivas_stereo_ica_enc.c index 596f8642ddf10dac7c715fcdaff66b99eb8b85ee..4ea6055b25e54c6325125228a4455d86e58610e6 100644 --- a/lib_enc/ivas_stereo_ica_enc.c +++ b/lib_enc/ivas_stereo_ica_enc.c @@ -43,6 +43,10 @@ #include "ivas_rom_com.h" #include "prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif + /*--------------------------------------------------------------- * Local function prototypes * ---------------------------------------------------------------*/ @@ -135,6 +139,100 @@ static void tcaTargetCh_LA( * Spectral-balancer to take care of the low-freq rumble and * compensate for the pre-emphasis. * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void spectral_balancer_fx16( + Word16 *signal, /* i/o : signal Qx */ + Word16 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +) +{ + Word16 i; + Word16 x0, x1, x2, y0, y1, y2; + Word32 a1, a2, b0, b1, b2; + + y1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + move16(); + move16(); + move16(); + move16(); + + /* hp filter 60Hz at 3dB for 8000KHz sampling rate + 1. [b,a] = butter(1, 60.0/8000.0, 'high'); + 2. spectral_balancing_filter + < maybe not needed>> + b =[1, -1] [1, -0.6] + a =[1, -0.95395255590776329] [1, 0.5] */ + IF( coeff_set == 0 ) + { + // a1 = 0.747789178258504f; + // a2 = -0.272214937925007f; + // b0 = 0.505001029045878f; + // b1 = -1.01000205809176f; + // b2 = 0.505001029045878f; + a1 = 401466258; // Q29 + move32(); + a2 = -146144282; // Q29 + move32(); + b0 = 271120363; // Q29 + move32(); + b1 = -542240726; // Q29 + move32(); + b2 = 271120363; // Q29 + move32(); + } + ELSE + { + // a1 = -0.13456126833218354f; + // a2 = -0.38813694706072926f; + // b0 = 1.0f; + // b1 = -1.9980666374183167f; + // b2 = 1.0f; + a1 = -72242031; // Q29 + move32(); + a2 = -208379437; // Q29 + move32(); + b0 = 536870912; // Q29 + move32(); + b1 = -1072703858; // Q29 + move32(); + b2 = 536870912; // Q29 + move32(); + } + + FOR( i = 0; i < lg; i++ ) + { + x2 = x1; + move16(); + x1 = x0; + move16(); + x0 = signal[i]; + move16(); + // y0 = (y1 * a1) + (y2 * a2) + (x0 * b0) + (x1 * b1) + (x2 * b2); + y0 = extract_l( W_extract_l( W_shr( W_mac_32_16( W_mac_32_16( W_mac_32_16( W_mac_32_16( W_mult_32_16( a1, y1 ), a2, y2 ), b0, x0 ), b1, x1 ), b2, x2 ), 30 ) ) ); // Qx + signal[i] = y0; + move16(); + y2 = y1; + move16(); + y1 = y0; + move16(); + } + + mem[0] = y1; + mem[1] = y2; + mem[2] = x0; + mem[3] = x1; + move16(); + move16(); + move16(); + move16(); + + return; +} +#endif // IVAS_FLOAT_FIXED void spectral_balancer( float *signal, @@ -1582,20 +1680,30 @@ void stereo_tca_init_enc_fx( { Word16 div1; Word16 div_e; - hStereoTCA->lMemRecalc = NS2SA( input_Fs, L_MEM_RECALC_NS ); + hStereoTCA->lMemRecalc = NS2SA_FX2( input_Fs, L_MEM_RECALC_NS ); + move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_12k8 ), input_Fs, &div_e ); hStereoTCA->lMemRecalc_12k8 = shr( div1, sub( 15, div_e ) ); + move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_16k ), input_Fs, &div_e ); hStereoTCA->lMemRecalc_16k = shr( div1, sub( 15, div_e ) ); + move16(); hStereoTCA->refChanIndx = L_CH_INDX; hStereoTCA->prevRefChanIndx = L_CH_INDX; + move16(); + move16(); + + hStereoTCA->targetGain_fx = ONE_IN_Q29; // Q29 + hStereoTCA->prevTargetGain_fx = ONE_IN_Q29; // Q29 + hStereoTCA->instTargetGain_fx = ONE_IN_Q29; // Q29 + move32(); + move32(); + move32(); - hStereoTCA->targetGain = MAX16B; // Q15 - hStereoTCA->prevTargetGain_fx = MAX16B; // Q15 - hStereoTCA->instTargetGain_fx = MAX16B; // Q15 hStereoTCA->corrStatsSmoothFac_fx = 22937; // Q15 + move16(); set16_fx( hStereoTCA->corrLagStats, 0, 3 ); set16_fx( hStereoTCA->prevCorrLagStats, 0, 3 ); @@ -1605,6 +1713,7 @@ void stereo_tca_init_enc_fx( set32_fx( hStereoTCA->memChanL_DS_fx, 0, ADDED_MEM_DS ); set32_fx( hStereoTCA->memChanR_DS_fx, 0, ADDED_MEM_DS ); hStereoTCA->mem_tempF_fx = 0; + move32(); set32_fx( hStereoTCA->corrEstPrev_fx[0], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[1], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[2], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); @@ -1612,13 +1721,18 @@ void stereo_tca_init_enc_fx( set32_fx( hStereoTCA->corrEstLT_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->memdecim_fx, 0, 12 ); hStereoTCA->ica_envVarLT_fx = 2097152000; // 2000 in Q20 + move32(); set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); hStereoTCA->E1_mem_fx = 0; hStereoTCA->E2_mem_fx = 0; + move32(); + move32(); set32_fx( hStereoTCA->delay_0_mem_fx, 0, MAX_DELAYREGLEN ); hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX16B; // Q15 hStereoTCA->LRTD_G_ATT_cnt = 1; + move16(); + move16(); return; } diff --git a/lib_enc/ivas_stereo_icbwe_enc.c b/lib_enc/ivas_stereo_icbwe_enc.c index f1f8371506d04da2ce573676af2d2340965030e5..1c5d7de02fa669284184558949c022899eca97af 100644 --- a/lib_enc/ivas_stereo_icbwe_enc.c +++ b/lib_enc/ivas_stereo_icbwe_enc.c @@ -42,6 +42,10 @@ #include "ivas_rom_com.h" #include "prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif + /*-------------------------------------------------------------------* * ic_bwe_enc_reset() * @@ -610,6 +614,11 @@ void stereo_icBWE_init_enc( set_f( hStereoICBWE->memModifyFs_icbwe[0], 0, 2 * L_FILT32k ); set_f( hStereoICBWE->memModifyFs_icbwe[1], 0, 2 * L_FILT32k ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Required for float to fixed conversion can be removed once float to fix of this buffer is removed. + set_f( hStereoICBWE->icbwe_inp_mem[0], 0, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); + set_f( hStereoICBWE->icbwe_inp_mem[1], 0, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); +#endif + set_f( hStereoICBWE->mem_nrg_L, 0, 2 ); set_f( hStereoICBWE->mem_nrg_R, 0, 2 ); set_f( hStereoICBWE->mem_nrg_DMX, 0, 2 ); @@ -626,7 +635,7 @@ void stereo_icBWE_init_enc_fx( ) { /* SHB speech resampler memory */ - set32_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, shl( L_FILT_MAX, 1 ) ); + set16_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, shl( L_FILT_MAX, 1 ) ); /* SHB ref channel */ set32_fx( hStereoICBWE->mem_shb_speech_ref_fx, 0, L_LOOK_16k ); @@ -640,32 +649,41 @@ void stereo_icBWE_init_enc_fx( /* inter-channel BWE spectral shape adj. */ hStereoICBWE->prevSpecMapping_fx = 0; hStereoICBWE->prevgsMapping_fx = MAX_32; // Q31 + move32(); + move32(); set32_fx( &( hStereoICBWE->memShbSpecMapping_fx ), 0, 1 ); set32_fx( hStereoICBWE->memShbSpecXcorr_fx, 0, 6 ); hStereoICBWE->prevNonRefEner_fx = MAX_32; // Q31 hStereoICBWE->prevRefEner_fx = MAX_32; // Q31 + move32(); + move32(); set32_fx( hStereoICBWE->memGsEnerMap_fx, MAX_32, 2 ); // Q31 - set32_fx( hStereoICBWE->dec_2over3_mem_fx, 0, L_FILT_2OVER3 ); - set32_fx( hStereoICBWE->dec_2over3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); - set32_fx( hStereoICBWE->memHPF_fx, 0, 8 ); + set16_fx( hStereoICBWE->dec_2over3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( hStereoICBWE->dec_2over3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); + set16_fx( hStereoICBWE->memHPF_fx, 0, 8 ); /* BWE ref channel */ hStereoICBWE->refChanIndx_bwe = L_CH_INDX; hStereoICBWE->prev_refChanIndx_bwe = L_CH_INDX; + move16(); + move16(); - set32_fx( hStereoICBWE->memModifyFs_icbwe_fx[0], 0, shl( L_FILT32k, 1 ) ); - set32_fx( hStereoICBWE->memModifyFs_icbwe_fx[1], 0, shl( L_FILT32k, 1 ) ); + set16_fx( hStereoICBWE->memModifyFs_icbwe_fx[0], 0, shl( L_FILT32k, 1 ) ); + set16_fx( hStereoICBWE->memModifyFs_icbwe_fx[1], 0, shl( L_FILT32k, 1 ) ); set32_fx( hStereoICBWE->mem_nrg_L_fx, 0, 2 ); set32_fx( hStereoICBWE->mem_nrg_R_fx, 0, 2 ); set32_fx( hStereoICBWE->mem_nrg_DMX_fx, 0, 2 ); hStereoICBWE->gDes_pastFrame_fx = MAX_32; // Q31 hStereoICBWE->icbweRefEner_fx = 0; + move32(); + move32(); hStereoICBWE->MSFlag = 0; + move16(); return; } @@ -674,7 +692,42 @@ void stereo_icBWE_init_enc_fx( * * Inter-channel BWE pre-proc of the non-ref channel *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void findRefChanBWE_fx( + const Word16 *input0_fx, /* i/o : input 0 Qx */ + const Word16 *input1_fx, /* i/o : input 1 Qx */ + Word16 *refChanIndx_bwe, /* o : Ref Channel Index bwe */ + const Word16 input_frame, /* i : input 0 & 1 frame length */ + Word16 *mem0_fx, /* i/o : mem 0 for input 0 Qx */ + Word16 *mem1_fx /* i/o : mem 1 for input 1 Qx */ +) +{ + Word16 inp0_fx[L_FRAME48k], inp1_fx[L_FRAME48k]; + Word32 tempF_fx, tempF1_fx; + + Copy( input0_fx, inp0_fx, input_frame ); + Copy( input1_fx, inp1_fx, input_frame ); + + spectral_balancer_fx16( inp0_fx, mem0_fx, input_frame, 1 ); + spectral_balancer_fx16( inp1_fx, mem1_fx, input_frame, 1 ); + + tempF_fx = sum2_f_16_gb_fx( inp0_fx, input_frame, find_guarded_bits_fx( input_frame ) ); // Q(2x-find_guarded_bits_fx( input_frame )) + tempF1_fx = sum2_f_16_gb_fx( inp1_fx, input_frame, find_guarded_bits_fx( input_frame ) ); // Q(2x-find_guarded_bits_fx( input_frame )) + + IF( LT_32( tempF1_fx, Mpy_32_32( 1374389535 /* 0.64f Q31 */, tempF_fx ) ) ) + { + *refChanIndx_bwe = L_CH_INDX; + move16(); + } + ELSE IF( LT_32( tempF_fx, Mpy_32_32( 1374389535 /* 0.64f Q31 */, tempF1_fx ) ) ) + { + *refChanIndx_bwe = R_CH_INDX; + move16(); + } + return; +} +#else static void findRefChanBWE( const float *input0, const float *input1, @@ -706,6 +759,7 @@ static void findRefChanBWE( return; } +#endif // IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* @@ -713,6 +767,191 @@ static void findRefChanBWE( * * Inter-channel BWE pre-proc of the non-ref channel *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_icBWE_preproc_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 shb_speech_nonref_fx[], /* o : SHB speech non-ref channel */ + Word16 q_shb_speech_nonref_fx /* i : Q SHB speech non-ref channel */ +) +{ + Word16 i, refChanIndx_bwe; + STEREO_TCA_ENC_HANDLE hStereoTCA; + STEREO_ICBWE_ENC_HANDLE hStereoICBWE; + Encoder_State *st; + Word16 temp_inp_fx[L_FRAME48k]; + Word16 tempSHB_fx[L_FRAME16k]; + Word16 temp_in_fx[L_FRAME48k]; + Word16 /*nonRefOffset,*/ nonRefMemLen; + Word32 gD_fx; + Word32 input_Fs; + + /* initialization */ + hStereoTCA = hCPE->hStereoTCA; /* Stereo TCA encoder handle */ + hStereoICBWE = hCPE->hStereoICBWE; /* Stereo IC BWE encoder handle */ + st = hCPE->hCoreCoder[0]; + input_Fs = st->input_Fs; + move32(); + + /*nonRefOffset = NS2SA(st_ivas->input_Fs, ACELP_LOOK_NS - L_MEM_RECALC_TBE_NS);*/ + nonRefMemLen = NS2SA_FX2( input_Fs, L_MEM_RECALC_TBE_NS ); + + test(); + test(); + test(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) || NE_16( st->core, ACELP_CORE ) || EQ_16( st->extl, -1 ) || LT_32( input_Fs, 32000 ) ) + { + set16_fx( hStereoICBWE->dec_2over3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( hStereoICBWE->dec_2over3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); + set16_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, ( 2 * L_FILT_MAX ) ); + set16_fx( shb_speech_nonref_fx, 0, L_FRAME16k ); + set16_fx( hStereoICBWE->memHPF_fx, 0, 8 ); + hStereoICBWE->refChanIndx_bwe = hStereoICBWE->prev_refChanIndx_bwe = L_CH_INDX; + move16(); + move16(); + + test(); + IF( GE_16( hCPE->element_mode, IVAS_CPE_DFT ) && GE_32( input_Fs, 32000 ) ) + { + set16_fx( temp_inp_fx, 0, L_FRAME48k ); + Copy( hStereoICBWE->dataChan_fx[0], temp_inp_fx + nonRefMemLen, sub( input_frame, nonRefMemLen ) ); + + IF( EQ_32( input_Fs, 48000 ) ) + { + Copy( temp_inp_fx, temp_in_fx, L_FRAME48k ); + set16_fx( temp_inp_fx, 0, L_FRAME48k ); + i = 2 * L_FILT48k + L_FILT_2OVER3; + move16(); + + decimate_2_over_3_allpass_fx( temp_in_fx + sub( input_frame, i ), i, temp_inp_fx + mult( sub( input_frame, i ), 21845 /* 2/3 Q15*/ ), hStereoICBWE->dec_2over3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hStereoICBWE->dec_2over3_mem_lp_fx ); + } + /* flip the spectrum */ + FOR( i = 0; i < L_FRAME32k; i += 2 ) + { + temp_inp_fx[i] = negate( temp_inp_fx[i] ); + move16(); + } + Copy( temp_inp_fx + L_FRAME32k - 2 * L_FILT32k, hStereoICBWE->memModifyFs_icbwe_fx[0], 2 * L_FILT32k ); + + set16_fx( temp_inp_fx, 0, L_FRAME48k ); + Copy( hStereoICBWE->dataChan_fx[1], temp_inp_fx + nonRefMemLen, sub( input_frame, nonRefMemLen ) ); + + IF( EQ_32( input_Fs, 48000 ) ) + { + Copy( temp_inp_fx, temp_in_fx, L_FRAME48k ); + set16_fx( temp_inp_fx, 0, L_FRAME48k ); + i = 2 * L_FILT48k + L_FILT_2OVER3; + move16(); + + /* IVAS-219: the same filter memories are used for both channels; the continuity is thus lost; shouldn't the memories be separated? */ + decimate_2_over_3_allpass_fx( temp_in_fx + sub( input_frame, i ), i, temp_inp_fx + mult( sub( input_frame, i ), 21845 /* 2/3 Q15*/ ), hStereoICBWE->dec_2over3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hStereoICBWE->dec_2over3_mem_lp_fx ); + } + /* flip the spectrum */ + FOR( i = 0; i < input_frame; i += 2 ) + { + temp_inp_fx[i] = negate( temp_inp_fx[i] ); + move16(); + } + Copy( temp_inp_fx + L_FRAME32k - 2 * L_FILT32k, hStereoICBWE->memModifyFs_icbwe_fx[1], 2 * L_FILT32k ); + } + + return; + } + + IF( NE_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + /* initial estimate of refChanIndx_bwe */ + gD_fx = hStereoTCA->targetGain_fx; + move32(); + + refChanIndx_bwe = hStereoTCA->refChanIndx; + move16(); + test(); + test(); + test(); + IF( ( GT_32( gD_fx, ONE_IN_Q29 ) && EQ_16( refChanIndx_bwe, R_CH_INDX ) ) || ( LT_32( gD_fx, ONE_IN_Q29 ) && EQ_16( refChanIndx_bwe, L_CH_INDX ) ) ) + { + refChanIndx_bwe = !( hStereoTCA->refChanIndx ); + move16(); + } + hStereoICBWE->refChanIndx_bwe = refChanIndx_bwe; + move16(); + + set16_fx( hStereoICBWE->dec_2over3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( hStereoICBWE->dec_2over3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); + set16_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, ( 2 * L_FILT_MAX ) ); + set16_fx( shb_speech_nonref_fx, 0, L_FRAME16k ); + set16_fx( hStereoICBWE->memHPF_fx, 0, 8 ); + + return; + } + + gD_fx = hStereoTCA->targetGain_fx; + move32(); + + refChanIndx_bwe = hStereoTCA->refChanIndx; + move16(); + test(); + test(); + test(); + IF( ( GT_32( gD_fx, ONE_IN_Q29 ) && EQ_16( refChanIndx_bwe, R_CH_INDX ) ) || ( LT_32( gD_fx, ONE_IN_Q29 ) && EQ_16( refChanIndx_bwe, L_CH_INDX ) ) ) + { + refChanIndx_bwe = !( hStereoTCA->refChanIndx ); + move16(); + } + + findRefChanBWE_fx( hStereoICBWE->dataChan_fx[0], hStereoICBWE->dataChan_fx[1], &refChanIndx_bwe, input_frame, &hStereoICBWE->memHPF_fx[0], &hStereoICBWE->memHPF_fx[4] ); + + hStereoICBWE->refChanIndx_bwe = refChanIndx_bwe; + move16(); + + IF( EQ_16( refChanIndx_bwe, R_CH_INDX ) ) + { + Copy( hStereoICBWE->icbwe_inp_mem_fx[0], temp_inp_fx, nonRefMemLen ); + Copy( hStereoICBWE->dataChan_fx[0], temp_inp_fx + nonRefMemLen, sub( input_frame, nonRefMemLen ) ); + } + ELSE + { + Copy( hStereoICBWE->icbwe_inp_mem_fx[1], temp_inp_fx, nonRefMemLen ); + Copy( hStereoICBWE->dataChan_fx[1], temp_inp_fx + nonRefMemLen, sub( input_frame, nonRefMemLen ) ); + } + + IF( EQ_32( input_Fs, 48000 ) ) + { + /*printf("\n Non-ref target HB generation for 48 kHz sample rate needs alignment verification \n");*/ + Copy( temp_inp_fx, temp_in_fx, L_FRAME48k ); + set16_fx( temp_inp_fx, 0, L_FRAME48k ); + + decimate_2_over_3_allpass_fx( temp_in_fx, L_FRAME48k, temp_inp_fx, hStereoICBWE->dec_2over3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hStereoICBWE->dec_2over3_mem_lp_fx ); + } + + /* flip the spectrum */ + FOR( i = 0; i < input_frame; i += 2 ) + { + temp_inp_fx[i] = negate( temp_inp_fx[i] ); + move16(); + } + + test(); + test(); + test(); + IF( GE_16( hCPE->element_mode, IVAS_CPE_DFT ) && GE_32( input_Fs, 32000 ) && ( NE_16( st->last_core, ACELP_CORE ) || EQ_16( st->last_extl, -1 ) ) ) + { + Copy_Scale_sig( hStereoICBWE->memModifyFs_icbwe_fx[!refChanIndx_bwe], hStereoICBWE->mem_decim_shb_ch0_fx, 2 * L_FILT32k, sub( 0, hStereoICBWE->q_dataChan_fx ) ); + } + + Word16 Q_new_inp, mem_decim_size; + Scale_sig( temp_inp_fx, L_FRAME48k, sub( 0, hStereoICBWE->q_dataChan_fx ) ); + + /* IVAS-219: Re-wire the shb nonref estimation through a lite CLDFB */ + modify_Fs_fx( temp_inp_fx, L_FRAME32k, 32000, tempSHB_fx, 16000, hStereoICBWE->mem_decim_shb_ch0_fx, 0, &Q_new_inp, &mem_decim_size ); + + Copy_Scale_sig( tempSHB_fx, shb_speech_nonref_fx, L_FRAME16k, sub( q_shb_speech_nonref_fx, Q_new_inp ) ); + + return; +} + +#else void stereo_icBWE_preproc( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ @@ -860,3 +1099,4 @@ void stereo_icBWE_preproc( return; } +#endif diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index a5b82fdd7efe8fa51acb88b857d7b1c4d37b6df0..96108be8b1c354f82ceb9a6d40bbb4dd9601563e 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -42,6 +42,7 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "prot_fx_enc.h" #endif /*-------------------------------------------------------------------* @@ -50,7 +51,81 @@ * Synchronize under certain conditions the tcx modes and set overlap * windows accordingly *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void sync_tcx_mode( + Encoder_State **st /* i/o: Encoder state */ +) +{ + const Word32 prevAccNrg0 = st[0]->hTranDet->subblockEnergies.accSubblockNrg[st[0]->hTranDet->subblockEnergies.nDelay]; + move32(); + const Word32 prevAccNrg1 = st[1]->hTranDet->subblockEnergies.accSubblockNrg[st[1]->hTranDet->subblockEnergies.nDelay]; + move32(); + const Word32 lastAccNrg0 = st[0]->hTranDet->subblockEnergies.accSubblockNrg[add( st[0]->hTranDet->subblockEnergies.nDelay, st[0]->hTranDet->transientDetector.nSubblocksToCheck )]; + move32(); + const Word32 lastAccNrg1 = st[1]->hTranDet->subblockEnergies.accSubblockNrg[add( st[1]->hTranDet->subblockEnergies.nDelay, st[1]->hTranDet->transientDetector.nSubblocksToCheck )]; + move32(); + + test(); + test(); + IF( EQ_16( st[0]->hTcxEnc->tcxMode, st[1]->hTcxEnc->tcxMode ) && EQ_32( st[0]->element_brate, IVAS_48k ) && + NE_16( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ) ) + { + test(); + IF( EQ_16( st[0]->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) || EQ_16( st[1]->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) /* synchronize overlaps */ + { + st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode = s_max( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ); + move16(); + move16(); + } + ELSE + { + st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode = s_min( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ); + move16(); + move16(); + } + } + test(); + test(); + test(); + IF( GT_32( prevAccNrg0, Mpy_32_16_1( prevAccNrg1, 1311 ) ) && GT_32( prevAccNrg1, Mpy_32_16_1( prevAccNrg0, 1311 ) ) /* 14 dB */ + && GT_32( lastAccNrg0, Mpy_32_16_1( lastAccNrg1, 2048 ) ) && GT_32( lastAccNrg1, Mpy_32_16_1( lastAccNrg0, 2048 ) ) ) /* 12 dB */ + { + st[0]->hTcxEnc->tcxMode = st[1]->hTcxEnc->tcxMode = s_max( st[0]->hTcxEnc->tcxMode, st[1]->hTcxEnc->tcxMode ); /* synchronize TCX mode of both channels */ + move16(); + move16(); + + IF( EQ_16( st[0]->hTcxEnc->tcxMode, TCX_10 ) ) + { + IF( EQ_16( st[0]->hTcxCfg->tcx_curr_overlap_mode, ALDO_WINDOW ) ) + { + st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode; + move16(); + } + + IF( EQ_16( st[0]->hTcxCfg->tcx_last_overlap_mode, ALDO_WINDOW ) ) + { + st[0]->hTcxCfg->tcx_last_overlap_mode = st[1]->hTcxCfg->tcx_last_overlap_mode; + move16(); + } + } + IF( EQ_16( st[1]->hTcxEnc->tcxMode, TCX_10 ) ) + { + IF( EQ_16( st[1]->hTcxCfg->tcx_curr_overlap_mode, ALDO_WINDOW ) ) + { + st[1]->hTcxCfg->tcx_curr_overlap_mode = st[0]->hTcxCfg->tcx_curr_overlap_mode; + } + + IF( EQ_16( st[1]->hTcxCfg->tcx_last_overlap_mode, ALDO_WINDOW ) ) + { + st[1]->hTcxCfg->tcx_last_overlap_mode = st[0]->hTcxCfg->tcx_last_overlap_mode; + } + } + } + + return; +} +#else static void sync_tcx_mode( Encoder_State **st /* i/o: Encoder state */ ) @@ -67,54 +142,382 @@ static void sync_tcx_mode( { st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode = max( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ); } - else + else + { + st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode = min( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ); + } + } + + if ( ( prevAccNrg0 * 25.0f > prevAccNrg1 ) && ( prevAccNrg1 * 25.0f > prevAccNrg0 ) && /* 14 dB */ + ( lastAccNrg0 * 16.0f > lastAccNrg1 ) && ( lastAccNrg1 * 16.0f > lastAccNrg0 ) ) /* 12 dB */ + { + st[0]->hTcxEnc->tcxMode = st[1]->hTcxEnc->tcxMode = max( st[0]->hTcxEnc->tcxMode, st[1]->hTcxEnc->tcxMode ); /* synchronize TCX mode of both channels */ + + if ( st[0]->hTcxEnc->tcxMode == TCX_10 ) + { + if ( st[0]->hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ) + { + st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode; + } + + if ( st[0]->hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ) + { + st[0]->hTcxCfg->tcx_last_overlap_mode = st[1]->hTcxCfg->tcx_last_overlap_mode; + } + } + + if ( st[1]->hTcxEnc->tcxMode == TCX_10 ) + { + if ( st[1]->hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ) + { + st[1]->hTcxCfg->tcx_curr_overlap_mode = st[0]->hTcxCfg->tcx_curr_overlap_mode; + } + + if ( st[1]->hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ) + { + st[1]->hTcxCfg->tcx_last_overlap_mode = st[0]->hTcxCfg->tcx_last_overlap_mode; + } + } + } + + return; +} +#endif + +/*-------------------------------------------------------------------* + * stereo_mdct_core_enc() + * + * joint stereo mdct core encoder + *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED +void stereo_mdct_core_enc( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ + float old_wsp[CPE_CHANNELS][L_WSP], /* i : 12.8kHz weighted speech (for LTP */ + float pitch_buf[CPE_CHANNELS][NB_SUBFR16k] /* o : floating pitch for each subframe */ +) +{ + int16_t i, ch, nSubframes, L_subframeTCX; + int16_t n, nAvailBits; + int16_t tnsSize[CPE_CHANNELS][NB_DIV]; /* number of tns parameters put into prm */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV]; /* number of tns bits in the frame */ + float *p_orig_spectrum_long[CPE_CHANNELS], orig_spectrum_long[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ + float *orig_spectrum[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ + float powerSpec[CPE_CHANNELS][N_MAX]; + float *p_powerSpec[CPE_CHANNELS]; + float powerSpecMsInv_long[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ + float *powerSpecMsInv[CPE_CHANNELS][NB_DIV]; + float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ + float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; + float *inv_mdst_spectrum[CPE_CHANNELS][NB_DIV]; + float *inv_spectrum[CPE_CHANNELS][NB_DIV]; + float *p_mdst_spectrum_long[CPE_CHANNELS], mdst_spectrum_long[CPE_CHANNELS][N_MAX]; + float *mdst_spectrum[CPE_CHANNELS][NB_DIV]; + Encoder_State *st, **sts; + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct; + BSTR_ENC_HANDLE hBstr; + int16_t ms_mask[2][MAX_SFB]; + int16_t p_param[CPE_CHANNELS][NB_DIV]; + int16_t stereo_bits; + int16_t meta_bits, signal_bits; + + push_wmops( "stereo_mdct_core_enc" ); + + L_subframeTCX = 0; /* to avoid compilation warning */ + + /*--------------------------------------------------------------* + * Set pointers + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + p_mdst_spectrum_long[ch] = mdst_spectrum_long[ch]; + p_orig_spectrum_long[ch] = orig_spectrum_long[ch]; + } + + sts = hCPE->hCoreCoder; + hStereoMdct = hCPE->hStereoMdct; + hBstr = sts[0]->hBstr; + + meta_bits = hCPE->hMetaData->nb_bits_tot; + signal_bits = hBstr->nb_bits_tot; + + /*--------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + sts[0]->hTcxEnc->tfm_mem = sts[1]->hTcxEnc->tfm_mem = sqrtf( 0.5f * ( sts[0]->hTcxEnc->tfm_mem * sts[0]->hTcxEnc->tfm_mem + sts[1]->hTcxEnc->tfm_mem * sts[1]->hTcxEnc->tfm_mem ) ); /* RMS */ + sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt = sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt = 0.5f * ( sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt + sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt ); + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + SetTCXModeInfo( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + + /* adaptively sync tcx modes*/ + if ( ( hCPE->last_element_mode == IVAS_CPE_MDCT ) && ( abs( sts[0]->hTcxCfg->tcx_last_overlap_mode - sts[1]->hTcxCfg->tcx_last_overlap_mode ) > 2 || + sts[0]->hTcxCfg->tcx_last_overlap_mode == sts[1]->hTcxCfg->tcx_last_overlap_mode || + sts[0]->hTcxCfg->tcx_last_overlap_mode + sts[1]->hTcxCfg->tcx_last_overlap_mode == 5 ) ) /* disable syncing for stereo switching or large diff in last frame overlap */ + { + sync_tcx_mode( sts ); + } + + if ( hCPE->hCoreCoder[0]->igf ) + { + initMdctStereoEncData_fx( hCPE->hStereoMdct, STEREO_FORMAT, IVAS_CPE_MDCT, hCPE->element_brate, hCPE->hCoreCoder[0]->bwidth, hCPE->hCoreCoder[0]->igf, hCPE->hCoreCoder[0]->hIGFEnc->igfData.igfInfo.grid, 0 ); + + stereo_mdct_init_igf_start_band_fx( &( hCPE->hStereoMdct->stbParamsTCX20 ), 16384 /* 1.0f in Q14 */, hCPE->hCoreCoder[0]->bwidth, hCPE->element_brate ); + stereo_mdct_init_igf_start_band_fx( &( hCPE->hStereoMdct->stbParamsTCX10 ), 8192 /* 0.5f in Q14 */, hCPE->hCoreCoder[0]->bwidth, hCPE->element_brate ); + stereo_mdct_init_igf_start_band_fx( &( hCPE->hStereoMdct->stbParamsTCX20afterACELP ), 20480 /* 1.25f in Q14 */, hCPE->hCoreCoder[0]->bwidth, hCPE->element_brate ); + } + else + { + hCPE->hStereoMdct->stbParamsTCX20.sfbIgfStart = -1; + hCPE->hStereoMdct->stbParamsTCX10.sfbIgfStart = -1; + hCPE->hStereoMdct->stbParamsTCX10.nBandsStereoCore = hCPE->hStereoMdct->stbParamsTCX10.sfbCnt; + hCPE->hStereoMdct->stbParamsTCX20.nBandsStereoCore = hCPE->hStereoMdct->stbParamsTCX20.sfbCnt; + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + orig_spectrum[ch][0] = orig_spectrum_long[ch]; + orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; + quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; + quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; + inv_mdst_spectrum[ch][0] = powerSpecMsInv[ch][0] = powerSpecMsInv_long[ch]; + inv_mdst_spectrum[ch][1] = powerSpecMsInv[ch][1] = powerSpecMsInv_long[ch] + N_TCX10_MAX; + inv_spectrum[ch][0] = quantized_spectrum[ch][0]; + inv_spectrum[ch][1] = quantized_spectrum[ch][1]; + mdst_spectrum[ch][0] = mdst_spectrum_long[ch]; + mdst_spectrum[ch][1] = mdst_spectrum_long[ch] + N_TCX10_MAX; + sts[ch]->hTcxEnc->tns_ms_flag[0] = 0; + sts[ch]->hTcxEnc->tns_ms_flag[1] = 0; + } + + /*--------------------------------------------------------------* + * MDCT core preprocessing: + * - initialization + * - Core Signal Analysis: MDCT, TNS + * - Envelope Quantization and FDNS + * - TNS + *---------------------------------------------------------------*/ + + ivas_mdct_core_whitening_enc( hCPE, new_samples, old_wsp, pitch_buf, p_mdst_spectrum_long, + tnsBits, p_orig_spectrum_long, tnsSize, p_param, hBstr, 0, CPE_CHANNELS ); + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + st->side_bits_frame_channel += NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL; + } + } + + sts[0]->side_bits_frame_channel += SMDCT_NBBITS_SPLIT_RATIO; + + + /*--------------------------------------------------------------* + * Stereo Processing + *---------------------------------------------------------------*/ + + if ( !hStereoMdct->isSBAStereoMode ) + { + stereo_coder_tcx( hStereoMdct, sts, ms_mask, mdst_spectrum, inv_spectrum, inv_mdst_spectrum, 0 ); + } + + /*--------------------------------------------------------------* + * Power spectrum calculation + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + nSubframes = ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX / nSubframes; + if ( sts[ch]->last_core == ACELP_CORE ) + { + L_subframeTCX += L_subframeTCX / 4; + } + + for ( n = 0; n < nSubframes; n++ ) + { + if ( sts[ch]->hTcxEnc->tns_ms_flag[n] ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpecMsInv[ch][n][i] = inv_mdst_spectrum[ch][n][i] * inv_mdst_spectrum[ch][n][i] + inv_spectrum[ch][n][i] * inv_spectrum[ch][n][i]; + powerSpec[ch][i + n * L_subframeTCX] = mdst_spectrum[ch][n][i] * mdst_spectrum[ch][n][i] + sts[ch]->hTcxEnc->spectrum[n][i] * sts[ch]->hTcxEnc->spectrum[n][i]; + } + } + else + { + if ( hStereoMdct->mdct_stereo_mode[n] != SMDCT_DUAL_MONO ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + powerSpecMsInv[ch][n][0] = inv_spectrum[ch][n][0] * inv_spectrum[ch][n][0]; + for ( i = 1; i < L_subframeTCX - 1; i++ ) + { + float mdst = ( inv_spectrum[ch][n][i + 1] - inv_spectrum[ch][n][i - 1] ); /* An MDST estimate */ + powerSpecMsInv[ch][n][i] = mdst * mdst + inv_spectrum[ch][n][i] * inv_spectrum[ch][n][i]; + } + powerSpecMsInv[ch][n][L_subframeTCX - 1] = inv_spectrum[ch][n][L_subframeTCX - 1] * inv_spectrum[ch][n][L_subframeTCX - 1]; + } + + /* power spectrum: MDCT^2 + MDST^2 */ + powerSpec[ch][n * L_subframeTCX] = sts[ch]->hTcxEnc->spectrum[n][0] * sts[ch]->hTcxEnc->spectrum[n][0]; + for ( i = 1; i < L_subframeTCX - 1; i++ ) + { + float mdst = ( sts[ch]->hTcxEnc->spectrum[n][i + 1] - sts[ch]->hTcxEnc->spectrum[n][i - 1] ); /* An MDST estimate */ + powerSpec[ch][i + n * L_subframeTCX] = mdst * mdst + sts[ch]->hTcxEnc->spectrum[n][i] * sts[ch]->hTcxEnc->spectrum[n][i]; + } + powerSpec[ch][L_subframeTCX - 1 + n * L_subframeTCX] = sts[ch]->hTcxEnc->spectrum[n][L_subframeTCX - 1] * sts[ch]->hTcxEnc->spectrum[n][L_subframeTCX - 1]; + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + if ( st->last_core == ACELP_CORE ) + { + L_subframeTCX += L_subframeTCX / 4; + } + + if ( ( st->hTcxEnc->tcxMode == TCX_20 ) && ( st->element_brate < HQ_96k || st->igf ) ) + { + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + + ComputeSpectrumNoiseMeasure( powerSpec[ch], L_subframeTCX, st->hTcxEnc->nmStartLine * ( L_subframeTCX / st->hTcxEnc->L_frameTCX ), + ( st->L_frame * st->last_sr_core != st->L_frame_past * st->sr_core ) || ( st->last_core != TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); + } + + st->hTcxEnc->measuredBwRatio_flt = 1.f; /* No bandwidth limit for the noise filling */ + } + + /*--------------------------------------------------------------* + * IGF + *---------------------------------------------------------------*/ + + if ( sts[0]->igf || sts[1]->igf ) + { + if ( sts[0]->hTcxEnc->tcxMode == sts[1]->hTcxEnc->tcxMode ) + { + /* Band-wise M/S for MDST */ + nSubframes = ( sts[0]->hTcxEnc->tcxMode == TCX_20 || sts[1]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( n = 0; n < nSubframes; n++ ) + { + if ( ( hStereoMdct->mdct_stereo_mode[n] != hStereoMdct->IGFStereoMode[n] || hStereoMdct->mdct_stereo_mode[n] == SMDCT_BW_MS ) && !hStereoMdct->isSBAStereoMode ) + { + p_powerSpec[0] = powerSpec[0]; + p_powerSpec[1] = powerSpec[1]; + ProcessStereoIGF( hStereoMdct, sts, ms_mask, orig_spectrum, p_powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); + } + else + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + /* update the pointer to the buffer of indices of the second channel */ + if ( ch == 1 ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); + } + } + } + } + else + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + /* update the pointer to the buffer of indices of the second channel */ + if ( ch == 1 ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + if ( st->igf ) + { + for ( n = 0; n < nSubframes; n++ ) + { + ProcessIGF( st, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); + } + } + } + } + + /*write IGF data to bitstream*/ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode = min( st[0]->hTcxCfg->tcx_curr_overlap_mode, st[1]->hTcxCfg->tcx_curr_overlap_mode ); + st = sts[ch]; + enc_prm_igf_mdct( st, hBstr ); } } - if ( ( prevAccNrg0 * 25.0f > prevAccNrg1 ) && ( prevAccNrg1 * 25.0f > prevAccNrg0 ) && /* 14 dB */ - ( lastAccNrg0 * 16.0f > lastAccNrg1 ) && ( lastAccNrg1 * 16.0f > lastAccNrg0 ) ) /* 12 dB */ + /* correct side bits per channel*/ + sts[0]->side_bits_frame_channel -= SMDCT_NBBITS_SPLIT_RATIO; + if ( !hStereoMdct->isSBAStereoMode ) { - st[0]->hTcxEnc->tcxMode = st[1]->hTcxEnc->tcxMode = max( st[0]->hTcxEnc->tcxMode, st[1]->hTcxEnc->tcxMode ); /* synchronize TCX mode of both channels */ + stereo_bits = write_stereo_to_bitstream( hStereoMdct, sts, ms_mask, 0, hBstr ); + } + else + { + stereo_bits = 0; + } - if ( st[0]->hTcxEnc->tcxMode == TCX_10 ) - { - if ( st[0]->hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ) - { - st[0]->hTcxCfg->tcx_curr_overlap_mode = st[1]->hTcxCfg->tcx_curr_overlap_mode; - } + /*--------------------------------------------------------------* + * Split available bits between channels + *---------------------------------------------------------------*/ - if ( st[0]->hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ) - { - st[0]->hTcxCfg->tcx_last_overlap_mode = st[1]->hTcxCfg->tcx_last_overlap_mode; - } - } + FindSplitRatio( hCPE, sts ); - if ( st[1]->hTcxEnc->tcxMode == TCX_10 ) - { - if ( st[1]->hTcxCfg->tcx_curr_overlap_mode == ALDO_WINDOW ) - { - st[1]->hTcxCfg->tcx_curr_overlap_mode = st[0]->hTcxCfg->tcx_curr_overlap_mode; - } + assert( hStereoMdct->split_ratio > 0 && hStereoMdct->split_ratio < SMDCT_BITRATE_RATIO_RANGE ); - if ( st[1]->hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ) - { - st[1]->hTcxCfg->tcx_last_overlap_mode = st[0]->hTcxCfg->tcx_last_overlap_mode; - } - } + /* Split available bits between channels */ + nAvailBits = sts[0]->bits_frame_channel + sts[1]->bits_frame_channel - hBstr->nb_bits_tot - sts[0]->core * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL + SMDCT_MINIMUM_ARITH_BITS ) - sts[1]->core * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL + SMDCT_MINIMUM_ARITH_BITS ); + + /* remove metadata bits */ + nAvailBits -= meta_bits; + + nAvailBits -= SMDCT_NBBITS_SPLIT_RATIO; + + splitAvailableBits( nAvailBits, hStereoMdct->split_ratio, hStereoMdct->isSBAStereoMode, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel ); + + sts[0]->bits_frame_channel += sts[0]->core * SMDCT_MINIMUM_ARITH_BITS; + sts[1]->bits_frame_channel += sts[1]->core * SMDCT_MINIMUM_ARITH_BITS; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts[ch]->total_brate = ( sts[ch]->bits_frame_channel + sts[ch]->side_bits_frame_channel ) * FRAMES_PER_SEC; } + stereo_bits += SMDCT_NBBITS_SPLIT_RATIO; + assert( ( sts[0]->total_brate + sts[1]->total_brate + ( stereo_bits + signal_bits + meta_bits ) * FRAMES_PER_SEC ) == hCPE->element_brate + hCPE->brate_surplus ); + assert( hStereoMdct->split_ratio > 0 && hStereoMdct->split_ratio < SMDCT_BITRATE_RATIO_RANGE ); - return; -} + push_next_indice( hBstr, hStereoMdct->split_ratio, SMDCT_NBBITS_SPLIT_RATIO ); -/*-------------------------------------------------------------------* - * stereo_mdct_core_enc() - * - * joint stereo mdct core encoder - *-------------------------------------------------------------------*/ + ivas_mdct_quant_coder( hCPE, tnsBits, tnsSize, p_param, 0 ); + pop_wmops(); + + return; +} +#else void stereo_mdct_core_enc( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ @@ -130,8 +533,8 @@ void stereo_mdct_core_enc( Word32 *orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; Word32 *p_powerSpec_fx[CPE_CHANNELS]; -#ifdef MSAN_FIX /*To be removed later*/ - Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX] = { 0 }; /* MS inv power spectrum, also inverse MDST spectrum */ +#ifdef MSAN_FIX /*To be removed later*/ + Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ #else Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ #endif // MSAN_FIX @@ -148,6 +551,9 @@ void stereo_mdct_core_enc( float *p_orig_spectrum_long[CPE_CHANNELS], orig_spectrum_long[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ float *orig_spectrum[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ float powerSpec[CPE_CHANNELS][N_MAX]; +#ifdef IVAS_FLOAT_FIXED + Word16 q_powerSpec; +#endif float *p_powerSpec[CPE_CHANNELS]; float powerSpecMsInv_long[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ float *powerSpecMsInv[CPE_CHANNELS][NB_DIV]; @@ -157,6 +563,13 @@ void stereo_mdct_core_enc( float *inv_spectrum[CPE_CHANNELS][NB_DIV]; float *p_mdst_spectrum_long[CPE_CHANNELS], mdst_spectrum_long[CPE_CHANNELS][N_MAX]; float *mdst_spectrum[CPE_CHANNELS][NB_DIV]; +#ifdef IVAS_FLOAT_FIXED + Word32 mdst_spectrum_long_fx[CPE_CHANNELS][N_MAX]; + Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word16 q_powSpec[MCT_MAX_CHANNELS], q_spec, tmp_s; + Word16 tmp_q_powSpec[N_MAX], tmp_q_powSpecInv[N_MAX], *tmp_q_psi[2]; + Word64 W_tmp; +#endif Encoder_State *st, **sts; STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct; BSTR_ENC_HANDLE hBstr; @@ -175,12 +588,20 @@ void stereo_mdct_core_enc( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { - orig_spectrum_fx[ch][0] = orig_spectrum_long_fx[ch]; - orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; p_mdst_spectrum_long[ch] = mdst_spectrum_long[ch]; p_orig_spectrum_long[ch] = orig_spectrum_long[ch]; +#ifdef IVAS_FLOAT_FIXED + orig_spectrum_fx[ch][0] = orig_spectrum_long_fx[ch]; + orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; +#endif } + set16_fx( tmp_q_powSpecInv, 63, L_FRAME48k ); + set16_fx( tmp_q_powSpec, 63, L_FRAME48k ); + + tmp_q_psi[0] = tmp_q_powSpecInv; + tmp_q_psi[1] = &tmp_q_powSpecInv[N_TCX10_MAX]; + sts = hCPE->hCoreCoder; hStereoMdct = hCPE->hStereoMdct; hBstr = sts[0]->hBstr; @@ -194,21 +615,79 @@ void stereo_mdct_core_enc( sts[0]->hTcxEnc->tfm_mem = sts[1]->hTcxEnc->tfm_mem = sqrtf( 0.5f * ( sts[0]->hTcxEnc->tfm_mem * sts[0]->hTcxEnc->tfm_mem + sts[1]->hTcxEnc->tfm_mem * sts[1]->hTcxEnc->tfm_mem ) ); /* RMS */ sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt = sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt = 0.5f * ( sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt + sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + Word16 q_com = Q31; + q_com = L_get_q1( st->prevEnergyHF ); + q_com = s_min( q_com, L_get_q1( st->currEnergyHF ) ); + st->prevEnergyHF_fx = floatToFixed_32( st->prevEnergyHF, q_com ); + st->currEnergyHF_fx = floatToFixed_32( st->currEnergyHF, q_com ); + st->currEnergyHF_e_fx = sub( Q31, q_com ); + IF( st->hTranDet ) + { + floatToFixed_arr( st->hTranDet->subblockEnergies.subblockNrgChange_flt, st->hTranDet->subblockEnergies.subblockNrgChange, Q15 - NRG_CHANGE_E, NSUBBLOCKS + MAX_TD_DELAY ); + } + IF( st->hTcxEnc ) + { + st->hTcxEnc->tfm_mem_fx = floatToFixed_32( st->hTcxEnc->tfm_mem, Q31 ); + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + } + } +#endif + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + SetTCXModeInfo_ivas_fx( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( st->hTcxEnc ) + { + st->hTcxEnc->tfm_mem = fixedToFloat_32( st->hTcxEnc->tfm_mem_fx, Q31 ); + } + } +#endif +#else for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; SetTCXModeInfo( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); } - +#endif /* adaptively sync tcx modes*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 temp_q = Q_factor_arrL( sts[0]->hTranDet->subblockEnergies.accSubblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + temp_q = s_min( temp_q, Q_factor_arrL( sts[1]->hTranDet->subblockEnergies.accSubblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY + 1 ) ); + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + floatToFixed_arrL32( st->hTranDet->subblockEnergies.accSubblockNrg_flt, st->hTranDet->subblockEnergies.accSubblockNrg, temp_q, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + } +#endif + + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) && ( GT_16( abs_s( sub( sts[0]->hTcxCfg->tcx_last_overlap_mode, sts[1]->hTcxCfg->tcx_last_overlap_mode ) ), extract_l( 2 ) ) || + EQ_16( sts[0]->hTcxCfg->tcx_last_overlap_mode, sts[1]->hTcxCfg->tcx_last_overlap_mode ) || + EQ_16( add( sts[0]->hTcxCfg->tcx_last_overlap_mode, sts[1]->hTcxCfg->tcx_last_overlap_mode ), extract_l( 5 ) ) ) ) /* disable syncing for stereo switching or large diff in last frame overlap */ + { + sync_tcx_mode( sts ); + } + +#else if ( ( hCPE->last_element_mode == IVAS_CPE_MDCT ) && ( abs( sts[0]->hTcxCfg->tcx_last_overlap_mode - sts[1]->hTcxCfg->tcx_last_overlap_mode ) > 2 || sts[0]->hTcxCfg->tcx_last_overlap_mode == sts[1]->hTcxCfg->tcx_last_overlap_mode || sts[0]->hTcxCfg->tcx_last_overlap_mode + sts[1]->hTcxCfg->tcx_last_overlap_mode == 5 ) ) /* disable syncing for stereo switching or large diff in last frame overlap */ { sync_tcx_mode( sts ); } - +#endif if ( hCPE->hCoreCoder[0]->igf ) { #ifndef IVAS_FLOAT_FIXED @@ -242,6 +721,13 @@ void stereo_mdct_core_enc( quantized_spectrum_fx[ch][1] = quantized_spectrum_long_fx[ch] + N_TCX10_MAX; inv_spectrum_fx[ch][0] = quantized_spectrum_fx[ch][0]; inv_spectrum_fx[ch][1] = quantized_spectrum_fx[ch][1]; + mdst_spectrum_fx[ch][0] = mdst_spectrum_long_fx[ch]; + mdst_spectrum_fx[ch][1] = mdst_spectrum_long_fx[ch] + N_TCX10_MAX; + set32_fx( powerSpecMsInv_long_fx[ch], 0, N_MAX ); + set32_fx( quantized_spectrum_long_fx[ch], 0, N_MAX ); + set32_fx( mdst_spectrum_long_fx[ch], 0, N_MAX ); + set32_fx( powerSpec_fx[ch], 0, N_MAX ); + set32_fx( powerSpecMsInv_long_fx[ch], 0, N_MAX ); #endif // IVAS_FLOAT_FIXED orig_spectrum[ch][0] = orig_spectrum_long[ch]; orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; @@ -255,6 +741,10 @@ void stereo_mdct_core_enc( mdst_spectrum[ch][1] = mdst_spectrum_long[ch] + N_TCX10_MAX; sts[ch]->hTcxEnc->tns_ms_flag[0] = 0; sts[ch]->hTcxEnc->tns_ms_flag[1] = 0; + set_f( powerSpecMsInv_long[ch], 0.0, N_MAX ); + set_f( quantized_spectrum_long[ch], 0.0, N_MAX ); + set_f( mdst_spectrum_long[ch], 0.0, N_MAX ); + set_f( powerSpec[ch], 0.0, N_MAX ); } /*--------------------------------------------------------------* @@ -293,9 +783,9 @@ void stereo_mdct_core_enc( #else #if 1 Word16 k; - Word16 q_spec = Q31; + q_spec = Q31; Word16 length; - Word32 *mdst_spectrum_fx[2][2]; + Word32 *mdst_spectrum_fix[2][2]; FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); @@ -305,7 +795,7 @@ void stereo_mdct_core_enc( } FOR( k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) { - mdst_spectrum_fx[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); + mdst_spectrum_fix[ch][k] = (Word32 *) malloc( sizeof( Word32 ) * length ); q_spec = s_min( q_spec, Q_factor_arrL( sts[ch]->hTcxEnc->spectrum[k], length ) - 1 ); q_spec = s_min( q_spec, Q_factor_arrL( mdst_spectrum[ch][k], length ) - 1 ); } @@ -322,12 +812,12 @@ void stereo_mdct_core_enc( { floatToFixed_arrL32( sts[ch]->hTcxEnc->spectrum[k], sts[ch]->hTcxEnc->spectrum_fx[k], q_spec, length ); sts[ch]->hTcxEnc->spectrum_e[k] = sub( Q31, q_spec ); - floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_spec, length ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fix[ch][k], q_spec, length ); } } #endif - stereo_coder_tcx_fx( hStereoMdct, sts, ms_mask, mdst_spectrum_fx, inv_spectrum_fx, inv_mdst_spectrum_fx, 0, q_spec ); + stereo_coder_tcx_fx( hStereoMdct, sts, ms_mask, mdst_spectrum_fix, inv_spectrum_fx, inv_mdst_spectrum_fx, 0, q_spec ); #if 1 FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -341,8 +831,8 @@ void stereo_mdct_core_enc( fixedToFloat_arrL32( sts[ch]->hTcxEnc->spectrum_fx[k], sts[ch]->hTcxEnc->spectrum[k], q_spec, length ); fixedToFloat_arrL32( inv_spectrum_fx[ch][k], inv_spectrum[ch][k], q_spec, length ); fixedToFloat_arrL32( inv_mdst_spectrum_fx[ch][k], inv_mdst_spectrum[ch][k], q_spec, length ); - fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_spec, length ); - free( mdst_spectrum_fx[ch][k] ); + fixedToFloat_arrL32( mdst_spectrum_fix[ch][k], mdst_spectrum[ch][k], q_spec, length ); + free( mdst_spectrum_fix[ch][k] ); } } #endif @@ -352,7 +842,213 @@ void stereo_mdct_core_enc( /*--------------------------------------------------------------* * Power spectrum calculation *---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 length, k; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + if ( sts[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + for ( k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + + q_spec = Q_factor_arrL( inv_mdst_spectrum[ch][k], length ); + q_spec = min( q_spec, Q_factor_arrL( inv_spectrum[ch][k], length ) ); + q_spec = min( q_spec, Q_factor_arrL( mdst_spectrum[ch][k], length ) ); + q_spec = min( q_spec, Q_factor_arrL( sts[ch]->hTcxEnc->spectrum[k], length ) ) - 1; + + floatToFixed_arrL32( inv_mdst_spectrum[ch][k], inv_mdst_spectrum_fx[ch][k], q_spec, length ); + floatToFixed_arrL32( inv_spectrum[ch][k], inv_spectrum_fx[ch][k], q_spec, length ); + floatToFixed_arrL32( mdst_spectrum[ch][k], mdst_spectrum_fx[ch][k], q_spec, length ); + + sts[ch]->hTcxEnc->spectrum_e[k] = sub( Q31, q_spec ); + floatToFixed_arrL32( sts[ch]->hTcxEnc->spectrum[k], sts[ch]->hTcxEnc->spectrum_fx[k], q_spec, length ); + } + } +#endif + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + L_subframeTCX = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + L_subframeTCX = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + } + + /* in MCT only relevant for bitrate switching from non-MCT bitrates */ + IF( EQ_16( sts[ch]->last_core, ACELP_CORE ) ) + { + L_subframeTCX = add( L_subframeTCX, shr( L_subframeTCX, 2 ) ); + } + + FOR( n = 0; n < nSubframes; n++ ) + { + q_spec = sub( 31, sts[ch]->hTcxEnc->spectrum_e[n] ); + + IF( sts[ch]->hTcxEnc->tns_ms_flag[n] ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + FOR( i = 0; i < L_subframeTCX; i++ ) + { + W_tmp = W_mac_32_32( W_mult_32_32( mdst_spectrum_fx[ch][n][i], mdst_spectrum_fx[ch][n][i] ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpec_fx[ch][add( i, imult1616( n, L_subframeTCX ) )] = W_extract_h( W_tmp ); + tmp_q_powSpec[add( i, imult1616( n, L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + + W_tmp = W_mac_32_32( W_mult_32_32( inv_mdst_spectrum_fx[ch][n][i], inv_mdst_spectrum_fx[ch][n][i] ), inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpecMsInv_fx[ch][n][i] = W_extract_h( W_tmp ); + tmp_q_psi[n][i] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + } + } + ELSE + { + IF( NE_16( hStereoMdct->mdct_stereo_mode[n], SMDCT_DUAL_MONO ) ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + W_tmp = W_mult_32_32( inv_spectrum_fx[ch][n][0], inv_spectrum_fx[ch][n][0] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpecMsInv_fx[ch][n][0] = W_extract_h( W_tmp ); + tmp_q_psi[n][0] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + + FOR( i = 1; i < L_subframeTCX - 1; i++ ) + { + Word32 mdst_fx = L_sub( inv_spectrum_fx[ch][n][i + 1], inv_spectrum_fx[ch][n][i - 1] ); /* An MDST estimate */ + + W_tmp = W_mac_32_32( W_mult_32_32( mdst_fx, mdst_fx ), inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpecMsInv_fx[ch][n][i] = W_extract_h( W_tmp ); + tmp_q_psi[n][i] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + } + + W_tmp = W_mult_32_32( inv_spectrum_fx[ch][n][L_subframeTCX - 1], inv_spectrum_fx[ch][n][L_subframeTCX - 1] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpecMsInv_fx[ch][n][L_subframeTCX - 1] = W_extract_h( W_tmp ); + tmp_q_psi[n][L_subframeTCX - 1] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + } + + /* power spectrum: MDCT^2 + MDST^2 */ + W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][0], sts[ch]->hTcxEnc->spectrum_fx[n][0] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpec_fx[ch][n * L_subframeTCX] = W_extract_h( W_tmp ); + tmp_q_powSpec[n * L_subframeTCX] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + + FOR( i = 1; i < L_subframeTCX - 1; i++ ) + { + Word32 mdst_fx = L_sub( sts[ch]->hTcxEnc->spectrum_fx[n][i + 1], sts[ch]->hTcxEnc->spectrum_fx[n][i - 1] ); /* An MDST estimate */ + + W_tmp = W_mac_32_32( W_mult_32_32( mdst_fx, mdst_fx ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpec_fx[ch][add( i, imult1616( n, L_subframeTCX ) )] = W_extract_h( W_tmp ); + tmp_q_powSpec[add( i, imult1616( n, L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + } + + W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1], sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1] ); + tmp_s = sub( W_norm( W_tmp ), 1 ); + W_tmp = W_shl( W_tmp, tmp_s ); + powerSpec_fx[ch][add( sub( L_subframeTCX, 1 ), imult1616( n, L_subframeTCX ) )] = W_extract_h( W_tmp ); + tmp_q_powSpec[add( sub( L_subframeTCX, 1 ), imult1616( n, L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 + move32(); + move16(); + } + } + + /* Aligning the Q-factors */ + { + FOR( i = 0; i < N_MAX; i++ ) + { + if ( powerSpec_fx[ch][i] == 0 ) + { + tmp_q_powSpec[i] = 63; + move16(); + } + if ( powerSpecMsInv_fx[ch][0][i] == 0 ) + { + tmp_q_powSpecInv[i] = 63; + move16(); + } + } + minimum_s( tmp_q_powSpec, N_MAX, &q_powSpec[ch] ); + minimum_s( tmp_q_powSpecInv, N_MAX, &tmp_s ); + q_powSpec[ch] = s_min( q_powSpec[ch], tmp_s ); + move16(); + + FOR( n = 0; n < nSubframes; n++ ) + { + FOR( i = 0; i < L_subframeTCX; i++ ) + { + powerSpecMsInv_fx[ch][n][i] = L_shr( powerSpecMsInv_fx[ch][n][i], sub( tmp_q_psi[n][i], q_powSpec[ch] ) ); + powerSpec_fx[ch][add( i, imult1616( n, L_subframeTCX ) )] = L_shr( powerSpec_fx[ch][add( i, imult1616( n, L_subframeTCX ) )], sub( tmp_q_powSpec[i], q_powSpec[ch] ) ); + move32(); + move32(); + } + } + } + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_spec = 31; + move16(); + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + length = sts[ch]->hTcxEnc->L_frameTCX / ( ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV ); + if ( sts[ch]->last_core == ACELP_CORE ) + { + length += length / 4; + } + for ( k = 0; k <= ( ( sts[ch]->core == TCX_20_CORE ) ? 1 : NB_DIV ) - 1; k++ ) + { + if ( sts[ch]->hTcxEnc->spectrum[k] ) + { + q_spec = 31 - sts[ch]->hTcxEnc->spectrum_e[k]; + fixedToFloat_arrL32( sts[ch]->hTcxEnc->spectrum_fx[k], sts[ch]->hTcxEnc->spectrum[k], q_spec, length ); + fixedToFloat_arrL32( inv_spectrum_fx[ch][k], inv_spectrum[ch][k], q_spec, length ); + } + if ( mdst_spectrum[ch][k] ) + { + fixedToFloat_arrL32( inv_mdst_spectrum_fx[ch][k], inv_mdst_spectrum[ch][k], q_spec, length ); + fixedToFloat_arrL32( mdst_spectrum_fx[ch][k], mdst_spectrum[ch][k], q_spec, length ); + } + } + fixedToFloat_arrL( powerSpecMsInv_fx[ch][0], powerSpecMsInv[ch][0], q_powSpec[ch], L_FRAME48k ); + fixedToFloat_arrL( powerSpec_fx[ch], powerSpec[ch], q_powSpec[ch], sts[ch]->hTcxEnc->L_frameTCX ); + } +#endif +#else for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { nSubframes = ( sts[ch]->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; @@ -398,7 +1094,64 @@ void stereo_mdct_core_enc( } } } +#endif +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_powerSpec = Q_factor_arrL( powerSpec[0], L_subframeTCX ); + q_powerSpec = s_min( q_powerSpec, Q_factor_arrL( powerSpec[1], L_subframeTCX ) ); + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + floatToFixed_arrL32( powerSpec[ch], powerSpec_fx[ch], q_powerSpec, N_MAX ); + } +#endif + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + ELSE + { + nSubframes = NB_DIV; + move16(); + } + L_subframeTCX = idiv1616( st->hTcxEnc->L_frameTCX, nSubframes ); + + IF( st->last_core == ACELP_CORE ) + { + L_subframeTCX = add( L_subframeTCX, shr( L_subframeTCX, 2 ) ); + } + test(); + test(); + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) && ( LT_32( st->element_brate, HQ_96k ) || st->igf ) ) + { + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + ComputeSpectrumNoiseMeasure_fx( powerSpec_fx[ch], L_subframeTCX, i_mult( st->hTcxEnc->nmStartLine, idiv1616( L_subframeTCX, st->hTcxEnc->L_frameTCX ) ), + NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); + } + st->hTcxEnc->measuredBwRatio = ONE_IN_Q14; /* No bandwidth limit for the noise filling */ + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( st->hTcxEnc ) + { + st->hTcxEnc->measuredBwRatio_flt = fix16_to_float( st->hTcxEnc->measuredBwRatio, Q14 ); + } + } +#endif +#else for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; @@ -416,14 +1169,13 @@ void stereo_mdct_core_enc( * and quantization (0: tonal, 1: noise-like). * * Detect low pass if present. * *-----------------------------------------------------------*/ - ComputeSpectrumNoiseMeasure( powerSpec[ch], L_subframeTCX, st->hTcxEnc->nmStartLine * ( L_subframeTCX / st->hTcxEnc->L_frameTCX ), ( st->L_frame * st->last_sr_core != st->L_frame_past * st->sr_core ) || ( st->last_core != TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); } st->hTcxEnc->measuredBwRatio_flt = 1.f; /* No bandwidth limit for the noise filling */ } - +#endif /*--------------------------------------------------------------* * IGF *---------------------------------------------------------------*/ @@ -516,7 +1268,7 @@ void stereo_mdct_core_enc( } floatToFixed_arr16( &hGrid->whiteningThreshold_flt[0][0], &hGrid->whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); } -#endif /**********************************flt to fix ends here*******************************************************/ +#endif /**********************************flt to fix ends here*******************************************************/ hIGFEnc[0]->spec_be_igf_e = p_orig_spectrum_e[0]; hIGFEnc[1]->spec_be_igf_e = p_orig_spectrum_e[1]; ProcessStereoIGF_fx( hStereoMdct, sts, ms_mask, @@ -551,7 +1303,7 @@ void stereo_mdct_core_enc( } } } -#endif /**********************************fix to flt ends here*******************************************************/ +#endif /**********************************fix to flt ends here*******************************************************/ #else ProcessStereoIGF( hStereoMdct, sts, ms_mask, orig_spectrum, p_powerSpec, powerSpecMsInv, inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); #endif // IVAS_FLOAT_FIXED @@ -595,7 +1347,7 @@ void stereo_mdct_core_enc( } /*write IGF data to bitstream*/ - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; enc_prm_igf_mdct( st, hBstr ); @@ -670,9 +1422,10 @@ void stereo_mdct_core_enc( push_next_indice( hBstr, hStereoMdct->split_ratio, SMDCT_NBBITS_SPLIT_RATIO ); - ivas_mdct_quant_coder( hCPE, tnsBits, tnsSize, p_param, 0 ); + ivas_mdct_quant_coder_fx( hCPE, tnsBits, tnsSize, p_param, 0 ); pop_wmops(); return; } +#endif diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 7b3fb8f5f9bb9153e0948e6d3591ae1b936bcc4c..0c7908c317fcf98a44489f94016ffc587be8d8b2 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -41,6 +41,7 @@ #include "wmc_auto.h" #include "ivas_prot.h" #ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" #include "prot_fx.h" #include "prot_fx_enc.h" #include "rom_com_fx.h" @@ -866,8 +867,8 @@ void stereo_tcx_core_enc( tmp1 = idiv1616( tmp1, n_subframes ); } tmp2 = imult1616( n, NPRM_DIV ); - /* TODO: integrate this. */ - QuantizeSpectrum( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); + + QuantizeSpectrum_ivas_fx( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); } /* Update tcx overlap mode */ diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 21ef9508695d2afdcb3ca487aded0f130a3b40ce..efe00e51a2effb70e2af6dfbfa8db2edcfcdc2bc 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -1073,6 +1073,22 @@ void tcx_noise_factor_fx( Word16 *quantized_fac_ns /* o: quantized noise factor */ ); +void tcx_noise_factor_ivas_fx( + Word32 *x_orig, /* i: unquantized mdct coefficients */ + Word16 x_orig_e, /* i: exponent */ + Word32 *sqQ, /* i: quantized mdct coefficients, exponent = x_orig_e */ + Word16 iFirstLine, /* i: first coefficient to be considered */ + Word16 lowpassLine, /* i: last nonzero coefficients after low-pass */ + Word16 nTransWidth, /* i: minimum size of hole to be checked */ + Word16 L_frame, /* i: frame length */ + Word16 gain_tcx, /* i: tcx gain */ + Word16 gain_tcx_e, /* i: gain exponent */ + Word16 tiltCompFactor, /* i: LPC tilt compensation factor */ + Word16 *fac_ns, /* o: noise factor, Q15 */ + Word16 *quantized_fac_ns, /* o: quantized noise factor, Q0 */ + Word16 element_mode /* i: element mode */ +); + void tcx_encoder_memory_update_fx( Word16 *wsig, /* i: targert weighted signal */ Word16 *xn_buf, /* i/o: mdct output buffer/TD weigthed synthesis */ diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index e008f1dd8c7d2c96c2073a2cf51d656b310877de..0d765c232df3544ae579cac0e747d861c895cf58 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1052,6 +1052,7 @@ typedef struct lpd_state_structure float tilt_code_flt; float gc_threshold_flt; /* Noise enhancer - threshold for gain_code */ float dispMem_flt[8]; /* Noise enhancer - phase dispersion algorithm memory */ + Word32 dispMem[8]; /* Noise enhancer - phase dispersion algorithm memory */ Word16 tilt_code; Word32 gc_threshold; /* exponent = 15, 15Q16 */ struct dispMem_fx dm_fx; /* Noise enhancer - phase dispersion algorithm memory */ @@ -1615,6 +1616,9 @@ typedef struct tcx_enc_structure Word16 noiseTiltFactor; /* compensation for LPC tilt in noise filling */ int16_t noiseLevelMemory_cnt; /* counter of consecutive low TCX noise levels */ float ltpGainMemory[N_LTP_GAIN_MEMS]; /* for smoothing noiseTransWidth */ +#ifdef IVAS_FLOAT_FIXED + Word16 ltpGainMemory_fx[N_LTP_GAIN_MEMS]; /* for smoothing noiseTransWidth */ +#endif STnsData tnsData[2]; // int16_t fUseTns[2]; Word8 fUseTns[2]; @@ -1641,6 +1645,10 @@ typedef struct tcx_enc_structure Word16 tcxltp_norm_corr_past; float tcxltp_norm_corr_mem_flt; float kernel_switch_corr_past_flt; +#ifdef IVAS_FLOAT_FIXED + Word16 tcxltp_norm_corr_mem; + Word16 kernel_switch_corr_past; +#endif uint16_t kernel_type[2]; /* transform kernel type in each subframe (MDCT or MDST) */ uint16_t kernel_symmetry_past; /* last TDA symmetry (0 for MDCT, 1 for MDST type) */ uint16_t enc_ste_pre_corr_past; @@ -1652,6 +1660,9 @@ typedef struct tcx_enc_structure float *speech_ltp_flt; float *new_speech_ltp_flt; Word16 buf_speech_ltp[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_buf_speech_ltp; +#endif Word16 *speech_ltp; Word16 *new_speech_ltp; int16_t tcxltp_filt_idx; @@ -1688,7 +1699,7 @@ typedef struct tcx_enc_structure float tcx_target_bits_fac_flt; Word16 Txnq[L_FRAME32k / 2 + 64]; /* Q target (overlap or ACELP+ZIR, use Aq) */ Word16 *acelp_zir; - Word16 tcx_target_bits_fac; + Word16 tcx_target_bits_fac; // Q14// int16_t tns_ms_flag[2]; Word32 *spectrum_fx[2]; /* MDCT output for a short block */ @@ -1855,7 +1866,10 @@ typedef struct enc_core_structure Word16 mem_preemph_fx; /* preemphasis filter memory */ - Word16 old_wsp_fx[L_WSP_MEM]; /* old weighted signal vector */ + Word16 old_wsp_fx[L_WSP_MEM]; /* old weighted signal vector */ +#ifdef IVAS_FLOAT_FIXED + Word16 exp_old_wsp; +#endif /*Word16 old_exc_fx[L_EXC_MEM];*/ /* old excitation vector */ Word16 old_wsp2_fx[( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM]; /* old decimated weighted signal vector qwsp */ Word16 mem_wsp_fx; /* weighted signal vector memory */ @@ -2001,6 +2015,14 @@ typedef struct enc_core_structure Word16 *buf_speech_enc; Word16 *buf_wspeech_enc; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_buf_speech_enc_pe; + Word16 exp_buf_speech_enc; + Word16 exp_old_inp_12k8; + Word16 exp_old_inp_16k; + Word16 exp_buf_wspeech_enc; +#endif + /*----------------------------------------------------------------------------------* * Noise estimation *----------------------------------------------------------------------------------*/ @@ -2264,6 +2286,10 @@ typedef struct enc_core_structure int16_t bpf_gain_param; float mem_bpf[2 * L_FILT16k]; float mem_error_bpf[2 * L_FILT16k]; +#ifdef IVAS_FLOAT_FIXED + Word32 mem_bpf_fx1[2 * L_FILT16k]; + Word32 mem_error_bpf_fx[2 * L_FILT16k]; +#endif Word16 bpf_T[NB_SUBFR16k]; Word16 bpf_gainT[NB_SUBFR16k]; diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index a8937b4889b69fcea91bc111d2e220672effa503..45ef64e1e344a815df2b0a6fb399c199f5fbf14b 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1511,7 +1511,120 @@ int16_t tcx_res_Q_spec( * * *---------------------------------------------------------------------*/ +#if 0 // Not Tested: Some dependency +void ProcessIGF_ivas_fx( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State *st, /**< in: Encoder state */ + Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ + Word16 *pMDCTSpectrum_e, + Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 *pPowerSpectrum_e, + Word16 isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ + Word16 isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ + Word16 frameno /**< in: flag indicating index of current subframe */ +) +{ + Word16 igfGridIdx; + Word16 isIndepFlag; + Word16 bsBits; + Word16 bsStart; + BSTR_ENC_HANDLE hBstr = st->hBstr; + + + isIndepFlag = 1; + move16(); + test(); + IF( isTransition && isTCX20 ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + IF( isTCX20 ) + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + ELSE + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + if ( EQ_16( frameno, 1 ) ) + { + isIndepFlag = 0; + move16(); + } + } + } + + IGFEncApplyMono_fx( hInstance, /**< in: instance handle of IGF Encoder */ + igfGridIdx, /**< in: IGF grid index */ + st, /**< in: Encoder state */ + pMDCTSpectrum, /**< in: MDCT spectrum */ + *pMDCTSpectrum_e, + pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + *pPowerSpectrum_e, + isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + isTNSActive, /**< in: flag indicating if the TNS is active */ + ( st->last_core == ACELP_CORE ) ); + { + const Word32 tns_predictionGain = st->hIGFEnc->tns_predictionGain; + const Word16 startLine = st->hIGFEnc->infoStartLine; + const Word16 endLine = st->hIGFEnc->infoStopLine; + const Word16 maxOrder = 8; + const Word32 *spec_before = st->hIGFEnc->spec_be_igf; + Word16 curr_order = 0; + Word16 A[ITF_MAX_FILTER_ORDER + 1]; + Word16 Q_A; + Word16 predictionGain = 0; + Word16 *flatteningTrigger = &( st->hIGFEnc->flatteningTrigger ); + + ITF_Detect_fx( spec_before, startLine, endLine, maxOrder, A, &Q_A, &predictionGain, &curr_order, shl( st->hIGFEnc->spec_be_igf_e, 1 ) ); + *flatteningTrigger = 0; + test(); + IF( LT_32( tns_predictionGain, 9646899l /*1.15 Q23*/ ) && + LT_16( predictionGain, 147 /*1.15 Q7*/ ) ) + { + *flatteningTrigger = 1; + } + } + + // IVAS_CODE_BITSTREAM + bsStart = hBstr->next_ind_fx; + + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + IF( isTCX20 ) + { + IGFEncWriteBitstream_fx( hInstance, NULL, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + } + ELSE + { + IGFEncWriteBitstream_fx( hInstance, st->hBstr, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); + } + +#ifndef IVAS_CODE_BITSTREAM + bsBits = sub( hBstr->next_ind_fx, bsStart ); + IF( !isTCX20 ) + { + IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot, hBstr->ind_list ); + } +#else + PMT( "New bit stream implementation to be checked" ) + bsBits = sub( hBstr->next_ind_fx, bsStart ); + IF( !isTCX20 ) + { + IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot_fx, hBstr->ind_list_fx ); + } + +#endif +} +#endif void ProcessIGF( Encoder_State *st, /* i : Encoder state */ float *pMDCTSpectrum, /* i : MDCT spectrum */ diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index dc6dc6b7ed762ae7c291b0caa7da5235eaf37761..b64532e69816a5374c4443de056e1758ce65b6bd 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -1441,6 +1441,340 @@ void tcx_noise_factor_fx( *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) ); } +#ifdef IVAS_FLOAT_FIXED +void tcx_noise_factor_ivas_fx( + Word32 *x_orig, /* i: unquantized mdct coefficients */ + Word16 x_orig_e, /* i: exponent */ + Word32 *sqQ, /* i: quantized mdct coefficients, exponent = x_orig_e */ + Word16 iFirstLine, /* i: first coefficient to be considered */ + Word16 lowpassLine, /* i: last nonzero coefficients after low-pass */ + Word16 nTransWidth, /* i: minimum size of hole to be checked */ + Word16 L_frame, /* i: frame length */ + Word16 gain_tcx, /* i: tcx gain */ + Word16 gain_tcx_e, /* i: gain exponent */ + Word16 tiltCompFactor, /* i: LPC tilt compensation factor */ + Word16 *fac_ns, /* o: noise factor, Q15 */ + Word16 *quantized_fac_ns, /* o: quantized noise factor, Q0 */ + Word16 element_mode /* i: element mode */ +) +{ + Word16 i, k = 0, maxK, segmentOffset; + Word32 sqErrorNrg, n; + Word16 inv_gain2, inv_gain2_e, tilt_factor, nTransWidth_1; + Word32 accu1, accu2, tmp32; + Word16 tmp1, tmp2, s; + Word16 c1, c2; + Word16 att; /* noise level attenuation factor for transient windows */ + Word32 xMax; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + move16(); + + assert( nTransWidth <= 16 ); + + c1 = sub( shl( nTransWidth, 1 ), 4 ); + c2 = mult( 9216 /*0.28125f Q15*/, inv_int[nTransWidth] ); + nTransWidth_1 = sub( nTransWidth, 1 ); + + /*Adjust noise filling level*/ + sqErrorNrg = L_deposit_l( 0 ); + n = L_deposit_l( 0 ); + + /* get inverse frame length */ + tmp1 = getInvFrameLen( L_frame ); + + /* tilt_factor = 1.0f /(float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */ + tmp32 = BASOP_Util_Log2( L_deposit_h( s_max( 0x3000, tiltCompFactor ) ) ); /* 6Q25 */ + tmp32 = L_shr( Mpy_32_16_1( tmp32, negate( tmp1 ) ), 6 ); + tilt_factor = round_fx( BASOP_Util_InvLog2( L_sub( tmp32, 0x2000000 ) ) ); /* 1Q14 */ + + /* inv_gain2 = 1.0f / ((float)(nTransWidth * nTransWidth) * gain_tcx); */ + tmp32 = L_mult( imult1616( nTransWidth, nTransWidth ), gain_tcx ); /* 15Q16 */ + tmp1 = norm_l( tmp32 ); + inv_gain2 = round_fx( L_shl( tmp32, tmp1 ) ); + inv_gain2_e = add( sub( 15, tmp1 ), gain_tcx_e ); + inv_gain2 = Inv16( inv_gain2, &inv_gain2_e ); + inv_gain2 = shr( inv_gain2, 2 ); /* 2 bits headroom */ + inv_gain2_e = add( inv_gain2_e, 2 ); + + /* find last nonzero line below iFirstLine, use it as start offset */ + i = iFirstLine; + move16(); + + IF( EQ_16( element_mode, IVAS_CPE_MDCT ) ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */ + { + segmentOffset = i; + maxK = 1; + move16(); + move16(); + } + ELSE + { + /* find last nonzero line below iFirstLine, use it as start offset */ + tmp1 = shr( iFirstLine, 1 ); + FOR( i = iFirstLine; i > tmp1; i-- ) + { + IF( sqQ[i] != 0 ) + { + BREAK; + } + } + /* inv_gain2 *= (float)pow(tilt_factor, (float)i); */ + FOR( k = 0; k < i; k++ ) + { + inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); + } + + /* initialize left (k) and right (maxK) non-zero neighbor pointers */ + k = 0; + move16(); + FOR( maxK = 1; maxK < nTransWidth; maxK++ ) + { + IF( sqQ[i + maxK] != 0 ) + { + BREAK; + } + } + i = add( i, 1 ); + segmentOffset = i; + move16(); + } + + IF( LE_16( nTransWidth, 3 ) ) + { + accu1 = L_deposit_l( 0 ); + accu2 = L_deposit_l( 0 ); + xMax = L_deposit_l( 0 ); + + FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k++ ) + { + xMax = L_max( xMax, L_abs( x_orig[k] ) ); + } + s = sub( norm_l( xMax ), 4 ); + + FOR( k = s_and( i, (Word16) 0xFFFE ); k < lowpassLine; k += 2 ) + { + /* even-index bins, left sub-win */ + tmp1 = round_fx( L_shl( x_orig[k], s ) ); + accu1 = L_mac0( accu1, tmp1, tmp1 ); + + /* odd-index bins, right sub-win */ + tmp1 = round_fx( L_shl( x_orig[k + 1], s ) ); + accu2 = L_mac0( accu2, tmp1, tmp1 ); + } + k = 0; + move16(); + + if ( accu1 == 0 ) + accu1 = L_deposit_l( 1 ); + if ( accu2 == 0 ) + accu2 = L_deposit_l( 1 ); + + att = BASOP_Util_Divide3232_Scale( L_shl( L_min( accu1, accu2 ), 1 ), L_add( accu1, accu2 ), &s ); + att = Sqrt16( att, &s ); + BASOP_SATURATE_WARNING_OFF_EVS; /* att is always <= 1.0 */ +#ifdef BASOP_NOGLOB + att = shl_o( att, s, &Overflow ); +#else + att = shl( att, s ); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + } + ELSE + { + att = 0x7FFF; + move16(); + } + + accu1 = L_deposit_l( 0 ); + + tmp1 = sub( lowpassLine, nTransWidth ); + FOR( ; i <= tmp1; i++ ) + { + inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); + + IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */ + { + k = sub( i, segmentOffset ); + + IF( k > 0 ) /* add segment sum to sum of segment magnitudes */ + { + IF( LE_16( nTransWidth, 3 ) ) + { + tmp2 = sub( k, c1 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_mac( n, nTransWidth_1, (Word16) 0x8000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], c2 ); + } + ELSE + { + tmp2 = sub( k, 12 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_sub( n, 0x70000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); + } + sqErrorNrg = L_add( sqErrorNrg, accu1 ); + accu1 = L_deposit_l( 0 ); /* segment ended here, so reset segment sum */ + k = 0; + move16(); + } + + FOR( ; maxK < nTransWidth; maxK++ ) + { + IF( sqQ[i + maxK] != 0 ) + { + BREAK; + } + } + segmentOffset = add( i, 1 ); /* new segment might start at next line */ + } + ELSE /* current line is zero, so update pointers & segment sum */ + { + if ( LT_16( k, nTransWidth ) ) + { + k = add( k, 1 ); + } + + tmp2 = sub( maxK, nTransWidth ); + test(); + if ( tmp2 < 0 && NE_16( element_mode, IVAS_CPE_MDCT ) ) + { + maxK = sub( maxK, 1 ); + } + + test(); + if ( ( tmp2 >= 0 ) && ( sqQ[i + sub( nTransWidth, 1 )] != 0 ) ) + { + maxK = sub( nTransWidth, 1 ); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) ); + accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) ); + } + } + + FOR( ; i < lowpassLine; i++ ) + { + inv_gain2 = shl( mult( inv_gain2, tilt_factor ), 1 ); + + IF( EQ_16( maxK, 1 ) ) /* current line is not zero, so reset pointers */ + { + k = sub( i, segmentOffset ); + + IF( k > 0 ) /* add segment sum to sum of segment magnitudes */ + { + IF( LE_16( nTransWidth, 3 ) ) + { + tmp2 = sub( k, c1 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_mac( n, nTransWidth_1, (Word16) 0x8000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], c2 ); + } + ELSE + { + tmp2 = sub( k, 12 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_sub( n, 0x70000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); + } + sqErrorNrg = L_add( sqErrorNrg, accu1 ); + } + segmentOffset = add( i, 1 ); /* no new segments since maxK remains 1 */ + } + ELSE /* current line is zero, so update pointers & energy sum */ + { + if ( LT_16( k, nTransWidth ) ) + { + k = add( k, 1 ); + } + if ( LT_16( maxK, nTransWidth ) ) + { + maxK = sub( maxK, 1 ); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult( inv_gain2, shl( imult1616( k, maxK ), 8 ) ); + accu1 = L_add( accu1, L_abs( Mpy_32_16_1( x_orig[i], tmp2 ) ) ); + } + } + + k = sub( i, segmentOffset ); + IF( k > 0 ) /* add last segment sum to sum of segment magnitudes */ + { + IF( LE_16( nTransWidth, 3 ) ) + { + tmp2 = sub( k, c1 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_mac( n, nTransWidth_1, (Word16) 0x8000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], c2 ); + } + ELSE + { + tmp2 = sub( k, 12 ); + if ( tmp2 > 0 ) + n = L_msu( n, k, (Word16) 0x8000 ); + if ( tmp2 > 0 ) + n = L_sub( n, 0x70000 ); + if ( tmp2 <= 0 ) + n = L_mac( n, int_sqr[k], 1152 /*0.03515625f Q15*/ ); + } + sqErrorNrg = L_add( sqErrorNrg, accu1 ); + } + + /* noise level factor: average of segment magnitudes of noise bins */ + IF( n > 0 ) + { + tmp1 = BASOP_Util_Divide3232_Scale( Mpy_32_16_1( sqErrorNrg, att ), n, &s ); + s = add( add( add( s, x_orig_e ), inv_gain2_e ), 7 - 15 ); + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + tmp1 = shl_o( tmp1, s, &Overflow ); +#else /* BASOP_NOGLOB */ + tmp1 = shl( tmp1, s ); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + } + ELSE + { + tmp1 = 0; + move16(); + } + + /* quantize, dequantize noise level factor (range 0.09375 - 0.65625) */ + tmp2 = round_fx( L_shr( L_mult( tmp1, 22016 /*1.34375f Q14*/ ), 14 - NBITS_NOISE_FILL_LEVEL ) ); + + if ( GT_16( tmp2, ( 1 << NBITS_NOISE_FILL_LEVEL ) - 1 ) ) + { + tmp2 = ( 1 << NBITS_NOISE_FILL_LEVEL ) - 1; + move16(); + } + + *quantized_fac_ns = tmp2; + move16(); + + *fac_ns = extract_l( L_mult0( *quantized_fac_ns, shr( 24576 /*0.75f Q15*/, NBITS_NOISE_FILL_LEVEL ) ) ); +} +#endif void tcx_encoder_memory_update_fx( Word16 *wsig, /* i : target weighted signal */