From 7a4790add139b630e350398e8f9e545e5c203eae Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sun, 25 Feb 2024 10:47:55 +0530 Subject: [PATCH] Functions in ivas_ism_dtx_dec converted to fixed point. --- lib_com/ivas_prot.h | 14 ++++ lib_com/prot_fx2.h | 7 ++ lib_com/tools.c | 26 ++++++ lib_dec/ivas_ism_dtx_dec.c | 167 +++++++++++++++++++++++++++++++++---- lib_dec/ivas_jbm_dec.c | 80 ++++++++++++++++++ lib_dec/ivas_stat_dec.h | 4 + 6 files changed, 284 insertions(+), 14 deletions(-) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 9f9dd5af3..a180ac8f7 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -1219,6 +1219,12 @@ int16_t ivas_ism_dtx_enc( int16_t md_diff_flag[], /* o : metadata differential flag */ int16_t *sid_flag /* o : indication of SID frame */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_ism_dtx_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word16 *nb_bits_metadata /* o : number of metadata bits */ +); +#endif // IVAS_FLOAT_FIXED void ivas_ism_dtx_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ @@ -1284,6 +1290,14 @@ void ivas_get_ism_sid_quan_bitbudget( int16_t *nBits_coh, /* o : number of Q bits for coherence */ int16_t *nBits_sce_id /* o : number of Q bits for sce_id_dtx */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_ism_dtx_limit_noise_energy_for_near_silence_fx( + SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder structures */ + const Word16 sce_id_dtx, /* i : SCE DTX ID */ + const Word16 nchan_transport, /* i : number of transport channels */ + Word16 *Q_cngNoiseLevel +); +#endif // IVAS_FLOAT_FIXED void ivas_ism_dtx_limit_noise_energy_for_near_silence( SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder structures */ diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index b7baf8e9f..18fb66328 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -5427,6 +5427,13 @@ Word32 dotp_fixed( const Word16 n /* i : vector length */ ); +/*! r: dot product of x[] and y[] in case of overflow*/ +Word32 dotp_fixed_o( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ + Word16 *res_q ); void lsf_end_dec_fx( Decoder_State* st, /* i/o: decoder state structure */ Word16 mode2_flag, diff --git a/lib_com/tools.c b/lib_com/tools.c index ae1bf97af..7486a24b3 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -863,6 +863,32 @@ Word32 dotp_fixed( } +/*To calculate dot product of two 32 bit arrays in case of overflow*/ +Word32 dotp_fixed_o( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ + Word16 *res_q /*stores resultant Q*/ +) +{ + Word16 i; + Word64 suma; /*resultant q= q(x)+q(y)-9-x such that q<=31*/ + + suma = W_shr( W_mult_32_32( x[0], y[0] ), log_len); + + FOR( i = 1; i < n; i++ ) + { + suma = W_add( suma, W_shr( W_mult_32_32( x[i], y[i] ), log_len) ); + } + *res_q = add(sub(*res_q , log_len) , 1); + WHILE( GT_64(suma , MAX_32) || GT_16(*res_q,31)) + { + suma = W_shr( suma, 1 ); + *res_q= sub(*res_q,1); + } + return (Word32) suma; +} /*---------------------------------------------------------------------* * inv_sqrt() * diff --git a/lib_dec/ivas_ism_dtx_dec.c b/lib_dec/ivas_ism_dtx_dec.c index 67b408406..4f8027b3e 100644 --- a/lib_dec/ivas_ism_dtx_dec.c +++ b/lib_dec/ivas_ism_dtx_dec.c @@ -37,23 +37,116 @@ #include "ivas_prot_fx.h" #include "prot.h" #include "wmc_auto.h" -#include "ivas_prot_fx.h" #ifdef IVAS_FLOAT_FIXED -static Word16 float_to_fix16(float number, Word16 Q); -static float fix16_to_float(Word16 number, Word16 Q); +#include "prot_fx2.h" -static Word16 float_to_fix16(float number, Word16 Q){ - Word16 ret=(Word16)(number * ((UWord16)1 << Q)); - return ret; -} +#endif +/*-------------------------------------------------------------------* + * ivas_ism_dtx_dec_fx() + * + * ISM DTX Metadata decoding routine + *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_ism_dtx_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word16 *nb_bits_metadata /* o : number of metadata bits */ +) +{ + Word16 ch, nchan_ism, nchan_ism_prev; + Word32 ivas_total_brate; + Word16 md_diff_flag[MAX_NUM_OBJECTS]; + Word16 flag_noisy_speech, sce_id_dtx; + Decoder_State *st; -static float fix16_to_float(Word16 number, Word16 Q){ - float ret=(float) number / ((UWord16)1 << Q); - return ret; -} + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + move32(); -#endif + nchan_ism_prev = st_ivas->nchan_ism; + move16(); + + IF ( !st_ivas->bfi && EQ_32(ivas_total_brate , IVAS_SID_5k2) ) + { + /* 'nchan_ism' was read in ivas_dec_setup() */ + nchan_ism = st_ivas->nchan_ism; + + /* ism_mode was read in ivas_dec_setup() as well as reconfiguration ivas_ism_dec_config() */ + } + ELSE + { + nchan_ism = nchan_ism_prev; + } + move16(); + + /* Metadata decoding and dequantization */ + ivas_ism_metadata_sid_dec_fx( st_ivas->hSCE, ivas_total_brate, st_ivas->bfi, nchan_ism, st_ivas->nchan_transport, st_ivas->ism_mode, + &flag_noisy_speech, &sce_id_dtx, st_ivas->hIsmMetaData, nb_bits_metadata ); + + IF ( EQ_32(ivas_total_brate , IVAS_SID_5k2) && !st_ivas->bfi ) + { + IF ( st_ivas->hParamIsmDec != NULL ) + { + st_ivas->hParamIsmDec->hParamIsm->flag_noisy_speech = flag_noisy_speech; + move16(); + } + + st_ivas->hISMDTX.sce_id_dtx = sce_id_dtx; + move16(); + } + + set16_fx( md_diff_flag, 1, nchan_ism ); + + IF ( EQ_16(st_ivas->ism_mode , ISM_MODE_PARAM) ) + { + FOR ( ch = 0; ch < nchan_ism; ch++ ) + { + st_ivas->hParamIsmDec->azimuth_values_fx[ch] = st_ivas->hIsmMetaData[ch]->azimuth_fx; + st_ivas->hParamIsmDec->elevation_values_fx[ch] = st_ivas->hIsmMetaData[ch]->elevation_fx; + move32(); + move32(); + } + } + /* synch common seed between SCEs */ + IF ( EQ_16(st_ivas->ism_mode , ISM_MODE_DISC) ) + { + FOR ( ch = 0; ch < nchan_ism; ++ch ) + { + st_ivas->hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed = st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed; + move16(); + } + } + + update_last_metadata_fx( nchan_ism, st_ivas->hIsmMetaData, md_diff_flag ); + + st_ivas->hISMDTX.ism_dtx_hangover_cnt = 0; + move16(); + + IF ( EQ_32(ivas_total_brate , IVAS_SID_5k2) && !st_ivas->bfi ) + { + FOR ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + nb_bits_metadata[ch] = nb_bits_metadata[sce_id_dtx]; + move16(); + } + } + + IF ( !st_ivas->bfi ) + { + FOR ( ch = 0; ch < st_ivas->nchan_transport; ch++ ) + { + st = st_ivas->hSCE[ch]->hCoreCoder[0]; + st->bit_stream = st_ivas->hSCE[0]->hCoreCoder[0]->bit_stream; + st->next_bit_pos = 0; /* note: needed in paramISM -> discISM switching */ + st->cng_ism_flag = 1; + move16(); + move16(); + st->L_frame = s_min( st->L_frame, L_FRAME16k ); /* note: needed for switching from active frame with L_frame=640 to CNG in object with no SID */ + } + } + + return; +} +#endif // IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * ivas_ism_dtx_dec() @@ -163,8 +256,8 @@ void ivas_ism_dtx_dec( { if ( EQ_16(md_diff_flag[ch], 1 ) ) { - st_ivas->hIsmMetaData[ch]->last_azimuth = fix16_to_float(st_ivas->hIsmMetaData[ch]->last_azimuth_fx, 7 ); - st_ivas->hIsmMetaData[ch]->last_elevation = fix16_to_float(st_ivas->hIsmMetaData[ch]->last_elevation_fx, 8); + st_ivas->hIsmMetaData[ch]->last_azimuth = fixedToFloat(st_ivas->hIsmMetaData[ch]->last_azimuth_fx, 7 ); + st_ivas->hIsmMetaData[ch]->last_elevation = fixedToFloat(st_ivas->hIsmMetaData[ch]->last_elevation_fx, 8); } } #else @@ -203,6 +296,52 @@ void ivas_ism_dtx_dec( * for DTX frames where the energy of the sent noise estimate of the dominant object * is near silence, limit the other objects CNG energies to the same level *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_ism_dtx_limit_noise_energy_for_near_silence_fx( + SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder structures */ + const Word16 sce_id_dtx, /* i : SCE DTX ID */ + const Word16 nchan_transport, /* i : number of transport channels */ + Word16 *Q_cngNoiseLevel /* i : stores Q factor of hFdCngCom->cngNoiseLevel for various channels*/ +) +{ + Word32 fac_fx, cng_noise_nrg_obj_fx, cng_noise_nrg_dominant_fx, Q_fac; + Word16 ch, cng_noise_level_len, Q_cng_noise_nrg_dominant; + HANDLE_FD_CNG_COM hFdCngCom; + hFdCngCom = hSCE[sce_id_dtx]->hCoreCoder[0]->hFdCngDec->hFdCngCom; + cng_noise_level_len = sub(hFdCngCom->stopFFTbin , hFdCngCom->startBand); + Q_cng_noise_nrg_dominant = add(Q_cngNoiseLevel[sce_id_dtx] , Q_cngNoiseLevel[sce_id_dtx]);/*stores Q for cng_noise_nrg_dominant_fx*/ + cng_noise_nrg_dominant_fx = dotp_fixed_o( hFdCngCom->cngNoiseLevel, hFdCngCom->cngNoiseLevel, cng_noise_level_len, 9 /*log2(len(hFdCngCom->cngNoiseLevel))*/, &Q_cng_noise_nrg_dominant );/*Resultant Q_cng_noise_nrg_dominant= (Q_cng_noise_nrg_dominant-x)<=31*/ + IF ( LT_32(cng_noise_nrg_dominant_fx , L_shl_sat(1, Q_cng_noise_nrg_dominant)))/*cng_noise_nrg_dominant<1.f*/ + { + FOR ( ch = 0; ch < nchan_transport; ch++ ) + { + IF ( EQ_16(ch , sce_id_dtx) ) + { + continue; + } + hFdCngCom = hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom; + cng_noise_level_len = sub(hFdCngCom->stopFFTbin , hFdCngCom->startBand); + Word16 Q_cng_noise_nrg_obj = add(Q_cngNoiseLevel[ch] , Q_cngNoiseLevel[ch]);/*Stores Q-factor of cng_noise_nrg_obj*/ + cng_noise_nrg_obj_fx = dotp_fixed_o( hFdCngCom->cngNoiseLevel, hFdCngCom->cngNoiseLevel, cng_noise_level_len, 9, &Q_cng_noise_nrg_obj );/*Resultant Q_cng_noise_nrg_obj= (Q_cng_noise_nrg_obj-x)<=31*/ + IF( GT_32(cng_noise_nrg_obj_fx , cng_noise_nrg_dominant_fx) ) + { + Word32 temp = divide3232( L_shr( cng_noise_nrg_dominant_fx, 1 ), cng_noise_nrg_obj_fx );/*Stores value of cng_noise_nrg_dominant_fx/cng_noise_nrg_obj_fx*/ + Word16 Q_temp = Q_cng_noise_nrg_dominant - 1 - Q_cng_noise_nrg_obj + 15;/*Stores resultant Q after divide3232 operation above*/ + IF (Q_temp % 2 == 1 )/*Making Q_temp even for sqrt function*/ + { + Q_temp = sub(Q_temp , 1); + temp = L_shr( temp, 1 ); + } + fac_fx = getSqrtWord32(temp);/*Resultant Q=Q_temp/2*/ + Q_fac = shr( Q_temp, 1 ); + v_multc_fixed( hFdCngCom->cngNoiseLevel, fac_fx, hFdCngCom->cngNoiseLevel, cng_noise_level_len );/*Resultant Q of cngNoiseLevel is Q_cngNoiseLevel for ch*/ + scale_sig32( hFdCngCom->cngNoiseLevel, cng_noise_level_len, negate(31 - Q_fac) );/*Restoring Q of hFdCngCom->cngNoiseLevel to Q_cngNoiseLevel */ + } + } + } + return; +} +#endif // IVAS_FLOAT_FIXED void ivas_ism_dtx_limit_noise_energy_for_near_silence( SCE_DEC_HANDLE hSCE[], /* i/o: SCE decoder structures */ diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 551e55fde..d035ef3dc 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -220,7 +220,57 @@ ivas_error ivas_jbm_dec_tc( /* Metadata decoding and configuration */ if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) { +#ifdef IVAS_FLOAT_FIXED +#if 1/*Cleanup changes: float to fixed*/ + FOR( Word16 ind = 0; ind < st_ivas->nchan_ism; ind++ ) + { + st_ivas->hIsmMetaData[ind]->azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->elevation * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_elevation * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_true_azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_true_azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_true_elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_true_elevation * ( 1 << 22 ) ); + } + FOR( Word16 ind = 0; ind < st_ivas->nchan_transport; ind++ ) + st_ivas->hSCE[ind]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx = (Word16) ( st_ivas->hSCE[ind]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_flt * 32767 ); + IF( st_ivas->hParamIsmDec ) + { + floatToFixed_arrL( st_ivas->hParamIsmDec->azimuth_values, st_ivas->hParamIsmDec->azimuth_values_fx, 22, st_ivas->nchan_ism ); + floatToFixed_arrL( st_ivas->hParamIsmDec->elevation_values, st_ivas->hParamIsmDec->elevation_values_fx, 22, st_ivas->nchan_ism ); + } + FOR( Word16 ch = 0; ch < st_ivas->nchan_ism; ch++ ) + { + st_ivas->hIsmMetaData[ch]->last_azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->last_azimuth, 22 ); + st_ivas->hIsmMetaData[ch]->last_elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->last_elevation, 22 ); + } +#endif + ivas_ism_dtx_dec_fx( st_ivas, nb_bits_metadata ); +#if 1/*Cleanup changes: fixed to float*/ + FOR( Word16 ind = 0; ind < st_ivas->nchan_ism; ind++ ) + { + st_ivas->hIsmMetaData[ind]->azimuth = (float) ( st_ivas->hIsmMetaData[ind]->azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->elevation = (float) ( st_ivas->hIsmMetaData[ind]->elevation_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_azimuth = (float) ( st_ivas->hIsmMetaData[ind]->last_azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_elevation = (float) ( st_ivas->hIsmMetaData[ind]->last_elevation_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_true_azimuth = (float) ( st_ivas->hIsmMetaData[ind]->last_true_azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_true_elevation = (float) ( st_ivas->hIsmMetaData[ind]->last_true_elevation_fx ) / (float) ( 1 << 22 ); + } + FOR( Word16 ind = 0; ind < st_ivas->nchan_transport; ind++ ) + st_ivas->hSCE[ind]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_flt = (float) ( st_ivas->hSCE[ind]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx ) / 32767.f; + IF( st_ivas->hParamIsmDec ) + { + fixedToFloat_arrL( st_ivas->hParamIsmDec->azimuth_values_fx, st_ivas->hParamIsmDec->azimuth_values, 22, st_ivas->nchan_ism); + fixedToFloat_arrL( st_ivas->hParamIsmDec->elevation_values_fx, st_ivas->hParamIsmDec->elevation_values, 22, st_ivas->nchan_ism); + } + FOR(Word16 ch = 0; ch < st_ivas->nchan_ism; ch++ ) + { + st_ivas->hIsmMetaData[ch]->last_azimuth = fixedToFloat( st_ivas->hIsmMetaData[ch]->last_azimuth_fx, 22 ); + st_ivas->hIsmMetaData[ch]->last_elevation = fixedToFloat( st_ivas->hIsmMetaData[ch]->last_elevation_fx, 22 ); + } +#endif +#else ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ); +#endif // IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED Word32 *output_fx[1]; @@ -254,7 +304,37 @@ ivas_error ivas_jbm_dec_tc( } #endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word16 Q_cngNoiseLevel[MAX_SCE]; + Word16 cng_noise_level_len, ch; + HANDLE_FD_CNG_COM hFdCngCom; + FOR(ch = 0; ch < 4; ch++) + { + IF(st_ivas->hSCE[ch] != NULL) + { + hFdCngCom = st_ivas->hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom; + cng_noise_level_len = sub(hFdCngCom->stopFFTbin, hFdCngCom->startBand); + Q_cngNoiseLevel[ch] = Q_factor_arrL(hFdCngCom->cngNoiseLevel_flt, cng_noise_level_len); + floatToFixed_arrL(hFdCngCom->cngNoiseLevel_flt, hFdCngCom->cngNoiseLevel, Q_cngNoiseLevel[ch], cng_noise_level_len); + } + } +#endif + ivas_ism_dtx_limit_noise_energy_for_near_silence_fx( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport , Q_cngNoiseLevel); +#if 1 + FOR(ch = 0; ch < 4; ch++) + { + IF(st_ivas->hSCE[ch] != NULL) + { + hFdCngCom = st_ivas->hSCE[ch]->hCoreCoder[0]->hFdCngDec->hFdCngCom; + cng_noise_level_len = sub(hFdCngCom->stopFFTbin, hFdCngCom->startBand); + fixedToFloat_arrL(hFdCngCom->cngNoiseLevel, hFdCngCom->cngNoiseLevel_flt, Q_cngNoiseLevel[ch], cng_noise_level_len); + } + } +#endif +#else ivas_ism_dtx_limit_noise_energy_for_near_silence( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); +#endif // IVAS_FLOAT_FIXED } else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index c683cfec7..00b8868c8 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -615,6 +615,10 @@ typedef struct ivas_param_ism_dec_data_structure /*Parameter decoding*/ float azimuth_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; float elevation_values[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; +#ifdef IVAS_FLOAT_FIXED + Word32 azimuth_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; + Word32 elevation_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; +#endif // IVAS_FLOAT_FIXED float power_ratios[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS][MAX_PARAM_ISM_WAVE]; /*sub-modules*/ -- GitLab