diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c index 48985e9a94dbe53e63eed5b4a51dbf52b0cc1bb6..e0eed1b7b48f470ee04d5b1344abba41f7d9c9f9 100644 --- a/lib_com/igf_base.c +++ b/lib_com/igf_base.c @@ -40,6 +40,9 @@ #include "prot.h" #include "rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#endif /*---------------------------------------------------------------------* * IGF_ApplyTransFac_flt() @@ -504,6 +507,12 @@ static void IGF_gridSetUp_flt( hGrid->sfbWrap[t] = 0; } +#ifdef IVAS_FLOAT_FIXED + hGrid->fFactor = float_to_fix16(hGrid->fFactor_flt, Q14); + hGrid->lFactor = float_to_fix16(hGrid->lFactor_flt, Q14); + hGrid->gFactor = float_to_fix16(hGrid->gFactor_flt, Q14); +#endif + return; } diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 6e0f00159604df950a8176ee4b973e03fb834ec6..92e765d697a6dc5083975d49371aba5be405f172 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -64,6 +64,7 @@ #define SQRT2 1.414213562373095f #define SQRT2_FIXED 1518500250 // Q30 #define SQRT2_OVER_2 (SQRT2 / 2.0f) +#define SQRT2_OVER_2_FIXED 1518500250 // Q31 #define INV_SQRT2 7.071067811865475e-1f /* 1/sqrt(2) */ #define INV_SQRT3 0.577350269189626f /* 1/sqrt(3) */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 9438ed5b6f903980505b60b0cff810e7429bcb1c..83b4fda485f485cb250ef30e37312e44850f70e8 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -378,6 +378,28 @@ void init_tcx_info_fx( Word16 *L_spec /* o : spectrum length */ ); +void decoder_tcx_IGF_mono_fx( + Decoder_State *st, /* i/o: coder memory state */ + Word32 x_fx[], /* o : de-quatized coefficients */ + Word16 *x_e, /* o : de-quatized coefficients exponent */ + const Word16 L_frame, /* i : frame length */ + const Word16 left_rect, /* i : left part is rectangular */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 frame_cnt /* i : frame counter in the super_frame */ +); + +void decoder_tcx_IGF_stereo_fx( + Decoder_State **sts, /* i/o: coder memory states */ + STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo structure */ + Word16 ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ + float *x[CPE_CHANNELS][NB_DIV], /* o : de-quatized coefficients */ + const Word16 L_frame, /* i : frame length */ + const Word16 left_rect, /* i : left part is rectangular */ + const Word16 k, /* i : Subframe index */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); + void IGFDecReplicateTCX10State_fx( IGF_DEC_INSTANCE_HANDLE hIGFDec /* i/o: instance handle of IGF Decoder */ ); diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 10afe3df1db8871a078f0f057877a731f294a87a..985e88b9cb72ec6b715b850a9c0f8ca70a1bea49 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -8026,6 +8026,20 @@ void IGFDecApplyMono_ivas( Word16 element_mode /**< in: | IVAS element mode */ ); +void IGFDecApplyStereo( + const IGF_DEC_INSTANCE_HANDLE hIGFDecL, /* i : instance handle of IGF Decoder */ + const IGF_DEC_INSTANCE_HANDLE hIGFDecR, /* i : instance handle of IGF Decoder */ + Word32 *spectrumL_fx, /* i/o: L MDCT spectrum */ + Word16 *spectrumL_e, /* i/o: L MDCT spectrum exp */ + Word32 *spectrumR_fx, /* i/o: R MDCT spectrum */ + Word16 *spectrumR_e, /* i/o: R MDCT spectrum exp */ + const Word16 igfGridIdx, /* i : in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 *coreMsMask, + const Word16 restrict_hopsize, + const Word16 bfi, /* i : frame loss == 1, frame good == 0 */ + const Word16 bfi_apply_damping +); + void IGFDecSetMode( const IGF_DEC_INSTANCE_HANDLE hIGFDec, /* o : instance handle of IGF Decoder */ const Word32 total_brate, /* i : bitrate */ @@ -8051,7 +8065,7 @@ void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, const Word16 igfGridIdx /**< in: | IGF grid index */ ); -void IGFDecUpdateInfo_fx( +void IGFDecUpdateInfo_ivas_fx( const IGF_DEC_INSTANCE_HANDLE hIGFDec, /* i/o: instance handle of IGF Decoder */ const Word16 subFrameIdx, /* i : subframe index */ const Word16 igfGridIdx /* i : IGF grid index */ diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c index 36ddb05ec6d9b57627224295d826ebe9fb7589b8..1f7aae46999e6253bf119e523ae7cdede127e529 100644 --- a/lib_dec/dec_tcx.c +++ b/lib_dec/dec_tcx.c @@ -2524,38 +2524,7 @@ void decoder_tcx_IGF_mono( igfGridIdx = ( st->last_core == ACELP_CORE || ( left_rect && bfi ) ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; } -#ifdef IVAS_FLOAT_FIXED - Word16 len; - Word32 x_fx[N_MAX]; - Word16 x_e; - len = ((igfGridIdx == IGF_GRID_LB_SHORT) ? (N_MAX_TCX - IGF_START_MN) / 2 : (N_MAX_TCX - IGF_START_MN)); - IGF_GRID *hGrid = &st->hIGFDec->igfData.igfInfo.grid[igfGridIdx]; - Word16 stop = hGrid->stopLine; - - // Float to fixed - f2me_buf(x, x_fx, &x_e, stop); - hGrid->fFactor = float_to_fix16(hGrid->fFactor_flt, Q14); - hGrid->lFactor = float_to_fix16(hGrid->lFactor_flt, Q14); - hGrid->gFactor = float_to_fix16(hGrid->gFactor_flt, Q14); - // u8bit to 16bit - FOR(int l = 0; l < IGF_START_MX; l++) - { - st->hIGFDec->infoTCXNoise_evs[l] = (Word16)st->hIGFDec->infoTCXNoise[l]; - } - - IGFDecApplyMono_ivas( st->hIGFDec, x_fx, &x_e, igfGridIdx, bfi, st->element_mode ); - - // Fixed to float - me2f_buf(x_fx, x_e, x, stop); - me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, len); - // 16bit to u8bit - FOR(Word16 l = 0; l < IGF_START_MX; l++) - { - st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; - } -#else IGFDecApplyMono_flt( st->hIGFDec, x, igfGridIdx, bfi, st->element_mode ); -#endif } return; diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index 994546a0ff5a46a72de876f9c1d2a96d8802bd62..efce8a1780e6db586f99e2c58c758584d3eb9322 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -2458,18 +2458,225 @@ void init_tcx_info_fx( test(); IF( st->igf ) { - if ( EQ_16( *L_frame, shr( st->L_frame, 1 ) ) && ( st->tcxonly ) ) + IF ( EQ_16( *L_frame, shr( st->L_frame, 1 ) ) && ( st->tcxonly ) ) { - IGFDecUpdateInfo_fx( st->hIGFDec, frame_cnt, IGF_GRID_LB_SHORT ); + IGFDecUpdateInfo_ivas_fx( st->hIGFDec, frame_cnt, IGF_GRID_LB_SHORT ); } - else + ELSE + { + IGFDecUpdateInfo_ivas_fx( st->hIGFDec, frame_cnt, ( st->last_core == ACELP_CORE || ( *left_rect && st->bfi ) ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM ); + } + } +} + + +/*-------------------------------------------------------------------* + * decoder_tcx_IGF_mono_fx() + * + * TCX: apply mono IGF + *-------------------------------------------------------------------*/ + +void decoder_tcx_IGF_mono_fx( + Decoder_State *st, /* i/o: coder memory state */ + Word32 x_fx[], /* o : de-quatized coefficients */ + Word16 *x_e, /* o : de-quatized coefficients exponent */ + const Word16 L_frame, /* i : frame length */ + const Word16 left_rect, /* i : left part is rectangular */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 frame_cnt /* i : frame counter in the super_frame */ +) +{ + Word16 igfGridIdx; + + test(); + IF( EQ_16( L_frame, shr( st->L_frame, 1 ) ) && ( st->tcxonly ) ) + { + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + } + ELSE + { + IF( ( EQ_16( st->last_core, ACELP_CORE ) || left_rect ) ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + } + + IGFDecUpdateInfo_ivas_fx( st->hIGFDec, frame_cnt, igfGridIdx ); + + IF ( st->igf ) + { + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + /*st->hIGFDec.igfData.igfInfo.nfSeed = (int16_t)(*nf_seed * 31821L + 13849L);*/ + + test(); + IF ( NE_16( L_frame, shr(st->L_frame, 1) ) && st->tcxonly ) + { + IF ( EQ_16( st->last_core, ACELP_CORE ) || ( left_rect && bfi ) ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + } + + IGFDecApplyMono_ivas( st->hIGFDec, x_fx, x_e, igfGridIdx, bfi, st->element_mode ); + + } + + return; +} + + +void decoder_tcx_IGF_stereo_fx( + Decoder_State **sts, /* i/o: coder memory states */ + STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo structure */ + Word16 ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ + float *x[CPE_CHANNELS][NB_DIV], /* o : de-quatized coefficients */ + const Word16 L_frame, /* i : frame length */ + const Word16 left_rect, /* i : left part is rectangular */ + const Word16 k, /* i : Subframe index */ + const Word16 bfi, /* i : bad frame indicator */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +) +{ + Word16 coreMsMask[N_MAX]; + STEREO_MDCT_BAND_PARAMETERS *sfbConf; + Word16 core, sfb, igfGridIdx, restrict_hopsize; + + core = sts[0]->core; + move16(); + + /* assumptions: stereo filling was already done on the flattened spectra + * IGF region is always coded M/S, never L/R (to be done in the encoder) + * for residual bands with stereo filling infoTcxNoise is set to zero + * both channels have the same IGF configuration + */ + + + /* initialization */ + IF( EQ_16( core, TCX_20_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20; + } + ELSE + { + sfbConf = &hStereoMdct->stbParamsTCX10; + } + + IF ( EQ_16( sts[0]->last_core, ACELP_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; + } + + /* create line wise ms mask for the core bands */ + set16_fx( coreMsMask, 0, N_MAX ); + + FOR ( sfb = 0; sfb < sfbConf->sfbCnt; sfb++ ) + { + set16_fx( &coreMsMask[sfbConf->sfbOffset[sfb]], ms_mask[k][sfb], sfbConf->sfbOffset[sfb + 1] - sfbConf->sfbOffset[sfb] ); + } + + IF( EQ_16( L_frame, shr( sts[0]->L_frame, 1 )) && ( sts[0]->tcxonly ) ) + { + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + } + ELSE + { + IF( EQ_16( sts[0]->last_core, ACELP_CORE ) || left_rect ) { - IGFDecUpdateInfo_fx( st->hIGFDec, frame_cnt, ( st->last_core == ACELP_CORE || ( *left_rect && st->bfi ) ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM ); + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + } + IGFDecUpdateInfo_ivas_fx( sts[0]->hIGFDec, k, igfGridIdx ); + + + IF( EQ_16( L_frame, shr( sts[1]->L_frame, 1 ) ) && ( sts[1]->tcxonly ) ) + { + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + } + ELSE + { + IF( EQ_16( sts[1]->last_core, ACELP_CORE ) || left_rect ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); } } + IGFDecUpdateInfo_ivas_fx( sts[1]->hIGFDec, k, igfGridIdx ); + + + IF ( sts[0]->igf ) + { + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + test(); + IF ( NE_16( L_frame, shr( sts[0]->L_frame, 1 ) ) && ( sts[0]->tcxonly ) ) + { + IF ( EQ_16( sts[0]->last_core, ACELP_CORE ) || ( left_rect && bfi ) ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + } + + restrict_hopsize = 0; + move16(); + IF( EQ_16( hStereoMdct->IGFStereoMode[k], SMDCT_BW_MS ) ) + { + restrict_hopsize = 1; + move16(); + } + + Word32 x_fx[NB_DIV][N_MAX]; + Word16 x_e[NB_DIV]; + Word16 stop1, stop2; + + stop1 = sts[0]->hIGFDec->igfData.igfInfo.grid[igfGridIdx].stopLine; + stop2 = sts[1]->hIGFDec->igfData.igfInfo.grid[igfGridIdx].stopLine; + f2me_buf(x[0][k], x_fx[0], &x_e[0], stop1); + f2me_buf(x[1][k], x_fx[1], &x_e[1], stop2); + + IGFDecApplyStereo( sts[0]->hIGFDec, sts[1]->hIGFDec, x_fx[0], &x_e[0], x_fx[1], &x_e[1], igfGridIdx, coreMsMask, restrict_hopsize, bfi, MCT_flag ); + + me2f_buf(x_fx[0], x_e[0], x[0][k], stop1); + me2f_buf(x_fx[1], x_e[1], x[1][k], stop2); + } + + return; } + void decoder_tcx_fx( Decoder_State *st, Word16 prm[], @@ -3608,9 +3815,9 @@ void decoder_tcx_noisefilling_fx( { IGFDecCopyLPCFlatSpectrum_fx( st->hIGFDec, x, *x_e, IGF_GRID_LB_SHORT ); /* also replace flat spectrum for the second TCX10 sub frame */ - IGFDecUpdateInfo_fx( st->hIGFDec, 1, IGF_GRID_LB_SHORT ); + IGFDecUpdateInfo_ivas_fx( st->hIGFDec, 1, IGF_GRID_LB_SHORT ); IGFDecCopyLPCFlatSpectrum_fx( st->hIGFDec, x, *x_e, IGF_GRID_LB_SHORT ); - IGFDecUpdateInfo_fx( st->hIGFDec, 0, IGF_GRID_LB_SHORT ); + IGFDecUpdateInfo_ivas_fx( st->hIGFDec, 0, IGF_GRID_LB_SHORT ); Copy( st->hIGFDec->igfData.igf_curr_subframe[0][0], st->hIGFDec->igfData.igf_curr_subframe[1][0], IGF_MAX_SFB ); } ELSE IF( bfi && st->igf && ( frame_cnt == 0 ) && ( EQ_16( L_frameTCX, shr( hTcxDec->L_frameTCX, 1 ) ) ) ) @@ -3674,16 +3881,16 @@ void decoder_tcx_noiseshaping_igf_fx( test(); test(); test(); - IF ( st->igf && ( !bfi || ( EQ_16(st->element_mode, IVAS_CPE_MDCT) && st->prev_bfi ) ) ) + IF( st->igf && ( !bfi || ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && st->prev_bfi ) ) ) { test(); - IF ( ( EQ_16(L_frame, shr(st->L_frame, 1) ) ) && ( st->tcxonly ) ) + IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly ) ) { IGFDecCopyLPCFlatSpectrum_fx( st->hIGFDec, x_fx, *x_e, IGF_GRID_LB_SHORT ); } ELSE { - IF (EQ_16(st->last_core, ACELP_CORE)) + IF( EQ_16( st->last_core, ACELP_CORE ) ) { IGFDecCopyLPCFlatSpectrum_fx( st->hIGFDec, x_fx, *x_e, IGF_GRID_LB_TRAN ); } @@ -3700,7 +3907,7 @@ void decoder_tcx_noiseshaping_igf_fx( test(); test(); test(); - IF(gainlpc2_fx && gainlpc2_e && NE_16(st->element_mode, IVAS_CPE_MDCT) && (!st->enablePlcWaveadjust || !bfi || (EQ_16(*temp_concealment_method, TCX_TONAL)))) + IF( gainlpc2_fx && gainlpc2_e && NE_16( st->element_mode, IVAS_CPE_MDCT ) && ( !st->enablePlcWaveadjust || !bfi || ( EQ_16( *temp_concealment_method, TCX_TONAL ) ) ) ) { Word16 spec_side_x_e, frame_side_x_e; @@ -3708,45 +3915,44 @@ void decoder_tcx_noiseshaping_igf_fx( move16(); /* NOTE: this function updates x till L_frame. From L_frame to L_spec, the exponent needs to be updated. */ - mdct_noiseShaping_ivas_fx(x_fx, x_e, L_frame, gainlpc2_fx, gainlpc2_e); + mdct_noiseShaping_ivas_fx( x_fx, x_e, L_frame, gainlpc2_fx, gainlpc2_e ); frame_side_x_e = *x_e; move16(); - IF(bfi == 0) + IF( bfi == 0 ) { - FOR (i = L_frame; i < L_spec; i++) + FOR( i = L_frame; i < L_spec; i++ ) { - x_fx[i] = Mpy_32_16_1(x_fx[i], gainlpc2_fx[FDNS_NPTS - 1]); + x_fx[i] = Mpy_32_16_1( x_fx[i], gainlpc2_fx[FDNS_NPTS - 1] ); move32(); } - spec_side_x_e = add(spec_side_x_e, gainlpc2_e[FDNS_NPTS-1]); + spec_side_x_e = add( spec_side_x_e, gainlpc2_e[FDNS_NPTS - 1] ); } - IF (LT_16(spec_side_x_e, frame_side_x_e)) + IF( LT_16( spec_side_x_e, frame_side_x_e ) ) { /* If the exponent on the spec side (i>L_frame) is lesser, then shift all the values in the spec side by the difference to make both sides have the same exponent. */ - FOR (i = L_frame; i < L_spec; i++) + FOR( i = L_frame; i < L_spec; i++ ) { - x_fx[i] = L_shr(x_fx[i], sub(frame_side_x_e, spec_side_x_e)); + x_fx[i] = L_shr( x_fx[i], sub( frame_side_x_e, spec_side_x_e ) ); move32(); } } - ELSE IF (GT_16(spec_side_x_e, frame_side_x_e)) + ELSE IF( GT_16( spec_side_x_e, frame_side_x_e ) ) { /* If the exponent on the spec side (i>L_frame) is greater, then shift all the values in the frame side (itonal_mdct_plc_active && NE_16(st->element_mode, IVAS_CPE_MDCT) ) + IF( bfi && st->tonal_mdct_plc_active && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { TonalMDCTConceal_Apply_ivas_fx( st->hTonalMDCTConc, x_fx, x_e, st->hTcxCfg->psychParamsCurrent ); /* If exponent has been updated after TonalMDCTConceal_Apply, then shift the spectrum to common exponent. */ curr_x_e = *x_e; move16(); - IF(NE_16(curr_x_e, prev_x_e)) + IF( NE_16( curr_x_e, prev_x_e ) ) { - *x_e = s_max(curr_x_e, prev_x_e); - FOR(i = 0; i < L_frameTCX; i++) + *x_e = s_max( curr_x_e, prev_x_e ); + FOR( i = 0; i < L_frameTCX; i++ ) { Word16 n_idx = st->hTonalMDCTConc->pTCI_float->numIndexes; Word16 l_idx = st->hTonalMDCTConc->pTCI_float->lowerIndex[0]; Word16 u_idx = st->hTonalMDCTConc->pTCI_float->upperIndex[n_idx - 1]; test(); - IF(GE_16(i, l_idx) && LE_16(i, u_idx)) + IF( GE_16( i, l_idx ) && LE_16( i, u_idx ) ) { - x_fx[i] = L_shr(x_fx[i], sub(*x_e, curr_x_e)); + x_fx[i] = L_shr( x_fx[i], sub( *x_e, curr_x_e ) ); } ELSE { - x_fx[i] = L_shr(x_fx[i], sub(*x_e, prev_x_e)); + x_fx[i] = L_shr( x_fx[i], sub( *x_e, prev_x_e ) ); } } } } test(); - IF ( st->hTonalMDCTConc != NULL && NE_16(st->element_mode, IVAS_CPE_MDCT) ) + IF( st->hTonalMDCTConc != NULL && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { - tmp32 = L_deposit_h(0); - IF(GT_16(hTcxDec->tcxltp_last_gain_unmodified, 0)) + tmp32 = L_deposit_h( 0 ); + IF( GT_16( hTcxDec->tcxltp_last_gain_unmodified, 0 ) ) { tmp32 = st->old_fpitch; move32(); @@ -3797,27 +4003,27 @@ void decoder_tcx_noiseshaping_igf_fx( tmp8 = 0; move16(); test(); - IF (bfi && st->tonal_mdct_plc_active) + IF( bfi && st->tonal_mdct_plc_active ) { tmp8 = 1; move16(); } TonalMDCTConceal_UpdateState( st->hTonalMDCTConc, - L_frameTCX, - tmp32, - bfi, - tmp8 ); + L_frameTCX, + tmp32, + bfi, + tmp8 ); } *x_len = L_frameTCX; move16(); - IF ( st->enablePlcWaveadjust != 0 ) + IF( st->enablePlcWaveadjust != 0 ) { test(); /* spectrum concealment */ - IF ( bfi && EQ_16(*temp_concealment_method, TCX_NONTONAL) ) + IF( bfi && EQ_16( *temp_concealment_method, TCX_NONTONAL ) ) { concealment_decode_fix( st->core, x_fx, x_e, &st->hPlcInfo ); } @@ -3825,7 +4031,7 @@ void decoder_tcx_noiseshaping_igf_fx( /* update spectrum buffer, tonality flag, etc. */ concealment_update_x( bfi, st->core, st->tonality_flag, x_fx, x_e, &st->hPlcInfo ); - *x_len = s_max(*x_len, st->hPlcInfo->L_frameTCX); + *x_len = s_max( *x_len, st->hPlcInfo->L_frameTCX ); } /*-----------------------------------------------------------* @@ -3834,15 +4040,15 @@ void decoder_tcx_noiseshaping_igf_fx( test(); test(); - IF(st->igf && !((EQ_16(L_frame, shr(st->L_frame, 1))) && (st->tcxonly))) + IF( st->igf && !( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly ) ) ) { - IF ( NE_16(st->element_mode, IVAS_CPE_MDCT) ) + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { Word16 igfGridIdx; test(); test(); - IF((EQ_16(st->last_core, ACELP_CORE)) || (left_rect&&bfi)) + IF( ( EQ_16( st->last_core, ACELP_CORE ) ) || ( left_rect && bfi ) ) { /* packet loss after first TCX must be handled like transition frame */ igfGridIdx = IGF_GRID_LB_TRAN; @@ -3852,19 +4058,19 @@ void decoder_tcx_noiseshaping_igf_fx( igfGridIdx = IGF_GRID_LB_NORM; } - IGFDecApplyMono_ivas(st->hIGFDec, x_fx, x_e, igfGridIdx, bfi, st->element_mode); + IGFDecApplyMono_ivas( st->hIGFDec, x_fx, x_e, igfGridIdx, bfi, st->element_mode ); - *x_len = s_max(*x_len, st->hIGFDec->igfData.igfInfo.grid[igfGridIdx].stopLine); + *x_len = s_max( *x_len, st->hIGFDec->igfData.igfInfo.grid[igfGridIdx].stopLine ); } } - IF(st->igf && ((EQ_16(L_frame, shr(st->L_frame, 1))) && (st->tcxonly))) + IF( st->igf && ( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly ) ) ) { - IF(NE_16(st->element_mode, IVAS_CPE_MDCT)) + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { - IGFDecApplyMono_ivas(st->hIGFDec, x_fx, x_e, IGF_GRID_LB_SHORT, bfi, st->element_mode); + IGFDecApplyMono_ivas( st->hIGFDec, x_fx, x_e, IGF_GRID_LB_SHORT, bfi, st->element_mode ); - *x_len = s_max(*x_len, st->hIGFDec->igfData.igfInfo.grid[IGF_GRID_LB_SHORT].stopLine); + *x_len = s_max( *x_len, st->hIGFDec->igfData.igfInfo.grid[IGF_GRID_LB_SHORT].stopLine ); } } diff --git a/lib_dec/igf_dec_fx.c b/lib_dec/igf_dec_fx.c index c90968534a1ec403d0fd97cf4c4bb0c5f5d37e43..1d0b527059d10273c1bd8d93a9a08ed1260e7dbc 100644 --- a/lib_dec/igf_dec_fx.c +++ b/lib_dec/igf_dec_fx.c @@ -22,6 +22,7 @@ #include "ivas_prot_fx.h" #endif + /**********************************************************************/ /* get scalefactor of an Word32 array with condition **************************************************************************/ @@ -292,6 +293,194 @@ static void IGF_replaceTCXNoise_2_new_ivas( Word32 *in, /**< in } } +/**********************************************************************/ /* +replaces TCX noise with noise band ratio (for IVAS) +**************************************************************************/ +static void IGF_replaceTCXNoise_2_new_ivas_with_shift( Word32 *in, /**< in/out: | MDCT spectrum */ + Word16 *in_e, /**< in: | MDCT spectrum exp */ + const Word16 *TCXNoise, /**< in: Q0 | tcx noise indicator vector */ + const Word16 start, /**< in: Q0 | start MDCT subband index */ + const Word16 stop, /**< in: Q0 | stop MDCT subband index */ + Word32 totalNoiseNrg, /**< in: | measured noise energy */ + Word16 totalNoiseNrg_e, /**< in: | measured noise energy exp */ + const Word16 n_noise_bands, /**< in: | number of noise bands in src */ + Word16 *nfSeed /**< in: | random generator noise seed */ +) +{ + Word16 sb; + Word16 g; + Word16 val; + Word32 rE; + Word32 L_tmp; + Word16 n_noise_bands_tile; + Word16 noise_band_ratio; + Word16 in_e_arr[IGF_START_MX + MAX_IGF_SFB_LEN]; + assert(LE_16(stop, IGF_START_MX + MAX_IGF_SFB_LEN)); + + n_noise_bands_tile = 0; + move16(); + val = 0; + move16(); + rE = 0; + move32(); + + set16_fx(in_e_arr + start, *in_e, stop - start); + + FOR( sb = start; sb < stop; sb++ ) + { + IF ( TCXNoise[sb] ) + { + val = Random( nfSeed ); + move16(); + in[sb] = L_deposit_l( val ); + move32(); + in_e_arr[sb] = 31; + val = shr( val, 5 ); + rE = L_mac( rE, val, val ); + n_noise_bands_tile = add( n_noise_bands_tile, 1 ); + } + } + + + IF( n_noise_bands_tile != 0 ) + { + noise_band_ratio = div_s( n_noise_bands_tile, n_noise_bands ); // Q15 + + /* make sure that rE is never 0 */ + if ( rE == 0 ) + { + rE = L_add( totalNoiseNrg, 0 ); /* save move32() -> use L_add(x, 0) = x; */ + } + + /* if totalNoiseNrg == 0, then rE must be at least 0x00010000, otherwise division by 0 will occur */ + if ( totalNoiseNrg == 0 ) + { + rE = L_max( rE, 0x00010000 ); + } + + Word16 tmp, tmp_e; + L_tmp = Mpy_32_16_1( totalNoiseNrg, noise_band_ratio ); + tmp = BASOP_Util_Divide3232_Scale( L_tmp, rE, &tmp_e ); + tmp_e = add( tmp_e, sub( totalNoiseNrg_e, 40 ) ); + g = Sqrt16( tmp, &tmp_e ); + + FOR( sb = start; sb < stop; sb++ ) + { + Word16 nrm = norm_l(in[sb]); + in[sb] = L_shl(in[sb], nrm); + in_e_arr[sb] = sub(in_e_arr[sb], nrm); + IF ( TCXNoise[sb] ) + { + //Word16 nrm = norm_l( in[sb] ); + //in[sb] = L_shl( in[sb], nrm ); // exp: 31 - nrm + //in_e_arr[sb] = sub(in_e_arr[sb], nrm); + in[sb] = Mpy_32_16_1( in[sb], g ); // exp: 31 - nrm + tmp_e + in_e_arr[sb] = add(in_e_arr[sb], tmp_e); + //in[sb] = L_shr( in[sb], sub( in_e, 31 - nrm + tmp_e ) ); // Making the exponent same as original + move32(); + } + } + } + + Word16 max_e = MIN16B; + FOR(sb = start; sb < stop; sb++) + { + max_e = s_max(max_e, in_e_arr[sb]); + } + FOR(sb = start; sb < stop; sb++) + { + in[sb] = L_shr(in[sb], sub(max_e, in_e_arr[sb])); + move32(); + } + *in_e = max_e; + move16(); +} + +/**********************************************************************/ /* +replaces TCX noise with noise band ratio (for IVAS) +**************************************************************************/ +static void IGF_replaceTCXNoise_2_new_ivas_with_var_shift( Word32 *in, /**< in/out: | MDCT spectrum */ + Word16 *in_e_arr, /**< in/out: | MDCT spectrum exp */ + const Word16 *TCXNoise, /**< in: | tcx noise indicator vector */ + const Word16 start, /**< in: | start MDCT subband index */ + const Word16 stop, /**< in: | stop MDCT subband index */ + Word32 totalNoiseNrg, /**< in: | measured noise energy */ + Word16 totalNoiseNrg_e, /**< in: | measured noise energy exp */ + const Word16 n_noise_bands, /**< in: | number of noise bands in src */ + Word16 *nfSeed /**< in: | random generator noise seed */ +) +{ + Word16 sb; + Word16 g; + Word16 val; + Word32 rE; + Word32 L_tmp; + Word16 n_noise_bands_tile; + Word16 noise_band_ratio; + + n_noise_bands_tile = 0; + move16(); + val = 0; + move16(); + rE = 0; + move32(); + + FOR( sb = start; sb < stop; sb++ ) + { + IF( TCXNoise[sb] ) + { + val = Random( nfSeed ); + move16(); + in[sb] = L_deposit_l( val ); + move32(); + in_e_arr[sb] = 31; + val = shr( val, 5 ); + rE = L_mac( rE, val, val ); + n_noise_bands_tile = add( n_noise_bands_tile, 1 ); + } + } + + + IF( n_noise_bands_tile != 0 ) + { + noise_band_ratio = div_s( n_noise_bands_tile, n_noise_bands ); // Q15 + + /* make sure that rE is never 0 */ + IF( rE == 0 ) + { + rE = L_add( totalNoiseNrg, 0 ); /* save move32() -> use L_add(x, 0) = x; */ + } + + /* if totalNoiseNrg == 0, then rE must be at least 0x00010000, otherwise division by 0 will occur */ + IF( totalNoiseNrg == 0 ) + { + rE = L_max( rE, 0x00010000 ); + } + + Word16 tmp, tmp_e; + L_tmp = Mpy_32_16_1( totalNoiseNrg, noise_band_ratio ); + tmp = BASOP_Util_Divide3232_Scale( L_tmp, rE, &tmp_e ); + tmp_e = add( tmp_e, sub( totalNoiseNrg_e, 40 ) ); + g = Sqrt16( tmp, &tmp_e ); + + FOR( sb = start; sb < stop; sb++ ) + { + Word16 nrm = norm_l( in[sb] ); + in[sb] = L_shl( in[sb], nrm ); + move32(); + in_e_arr[sb] = sub( in_e_arr[sb], nrm ); + move16(); + IF( TCXNoise[sb] ) + { + in[sb] = Mpy_32_16_1( in[sb], g ); + move32(); + in_e_arr[sb] = add( in_e_arr[sb], tmp_e ); + move16(); + } + } + } +} + /**********************************************************************/ /* reads whitening levels **************************************************************************/ @@ -359,6 +548,39 @@ static void IGF_setLinesToZero(const Word16 startLin } +/**********************************************************************/ /* +Convert igfSpectrum fixed point values with exponent per index to per tile. +**************************************************************************/ +static void IGF_convert_exponent_per_idx_to_per_tile( H_IGF_GRID hGrid, + Word32 *igfSpec, + Word16 *igfSpec_e_per_idx, + Word16 *igfSpec_e_per_tile ) +{ + Word16 i; + Word16 j; + Word16 max_e; + Word16 start; + Word16 stop; + FOR( i = 0; i < hGrid->nTiles; i++ ) + { + start = hGrid->tile[i]; + move16(); + stop = hGrid->tile[i + 1]; + move16(); + + maximum_fx( igfSpec_e_per_idx + start, sub( stop, start ), &max_e ); + + FOR( j = start; j < stop; j++ ) + { + igfSpec[j] = L_shr( igfSpec[j], sub( max_e, igfSpec_e_per_idx[j] ) ); + move32(); + } + + igfSpec_e_per_tile[i] = max_e; + move16(); + } +} + /**********************************************************************/ /* prepare IGF spectrum **************************************************************************/ @@ -718,6 +940,378 @@ static void IGF_prep_ivas( IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in } } + +/**********************************************************************/ /* +prepare IGF spectrum in stereo +**************************************************************************/ +static void IGF_prepStereo( + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateDataL, /* i : IGF private data handle */ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateDataR, /* i : IGF private data handle */ + const Word16 igfGridIdx, /* i : in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 *TCXNoiseL, /* i : left TCX noise vector */ + const Word16 *TCXNoiseR, /* i : right TCX noise vector */ + Word32 *igf_specL_fx, /* i/o: prepared left IGF spectrum */ + Word16 *igf_specL_e_arr, /* i/o: prepared left IGF spectrum exponents for each index */ + Word32 *igf_specR_fx, /* i/o: prepared right IGF spectrum */ + Word16 *igf_specR_e_arr, /* i/o: prepared right IGF spectrum exponents for each index */ + const Word32 *src_specL_fx, /* i : left source spectrum */ + const Word16 src_specL_e, /* i : left source spectrum exp */ + const Word32 *src_specR_fx, /* i : right source spectrum */ + const Word16 src_specR_e, /* i : right source spectrum exp */ + const Word16 *coreMsMask /* i : line wise ms Mask */ +) +{ + H_IGF_GRID hGrid; + H_IGF_INFO hInfoL, hInfoR; + Word16 tb, sfb, strt_cpy, tile_idx; + Word16 *swb_offset; + const Word32 c_fx = SQRT2_OVER_2_FIXED; // Q31 + Word16 selectionL = 0; // 0 -> IGF, 1 -> pSpecFlat + Word16 selectionR = 0; // 0 -> IGF, 1 -> pSpecFlat + + hInfoL = &hPrivateDataL->igfInfo; + hInfoR = &hPrivateDataR->igfInfo; + hGrid = &hPrivateDataL->igfInfo.grid[igfGridIdx]; + swb_offset = hGrid->swb_offset; + + FOR( tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++ ) + { + Word16 tile_width, stop; + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + tile_width = sub( swb_offset[hGrid->sfbWrap[tile_idx + 1]], swb_offset[hGrid->sfbWrap[tile_idx]] ); + stop = add( strt_cpy, tile_width ); + + IF( EQ_16( IGF_WHITENING_STRONG, hPrivateDataL->currWhiteningLevel[tile_idx] ) ) + { + tb = swb_offset[hGrid->sfbWrap[tile_idx]]; + move16(); + + FOR( tb = swb_offset[hGrid->sfbWrap[tile_idx]]; tb < swb_offset[hGrid->sfbWrap[tile_idx + 1]]; tb++ ) + { + igf_specL_fx[tb] = L_deposit_l( Random( hInfoL->nfSeed ) ); /* 31Q0, fill LSBs */ + move32(); + igf_specL_e_arr[tb] = 31; + move16(); + } + } + ELSE + { + IF( EQ_16( IGF_WHITENING_MID, hPrivateDataL->currWhiteningLevel[tile_idx] ) ) + { + IF( hPrivateDataL->n_noise_bands ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specL_fx, + igf_specL_e_arr, + TCXNoiseL, + strt_cpy, + stop, + hPrivateDataL->totalNoiseNrg, + hPrivateDataL->totalNoiseNrg_exp, + hPrivateDataL->n_noise_bands, + hInfoL->nfSeed ); + } + selectionL = 0; + move16(); + } + ELSE + { + IF( hPrivateDataL->n_noise_bands_off ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specL_fx, + igf_specL_e_arr, + TCXNoiseL, + strt_cpy, + stop, + hPrivateDataL->totalNoiseNrg_off, + hPrivateDataL->totalNoiseNrg_off_exp, + hPrivateDataL->n_noise_bands_off, + hInfoL->nfSeed ); + } + selectionL = 1; + move16(); + } + + IF( EQ_16( IGF_WHITENING_MID, hPrivateDataL->currWhiteningLevel[tile_idx] ) ) + { + IF( hPrivateDataR->n_noise_bands ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specR_fx, + igf_specR_e_arr, + TCXNoiseR, + strt_cpy, + stop, + hPrivateDataR->totalNoiseNrg, + hPrivateDataR->totalNoiseNrg_exp, + hPrivateDataR->n_noise_bands, + hInfoR->nfSeed ); + } + selectionR = 0; + move16(); + } + ELSE + { + IF( hPrivateDataR->n_noise_bands_off ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specR_fx, + igf_specR_e_arr, + TCXNoiseR, + strt_cpy, + stop, + hPrivateDataR->totalNoiseNrg_off, + hPrivateDataR->totalNoiseNrg_off_exp, + hPrivateDataR->n_noise_bands_off, + hInfoR->nfSeed ); + } + selectionR = 1; + move16(); + } + + FOR( sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++ ) + { + FOR( tb = swb_offset[sfb]; tb < swb_offset[sfb + 1]; tb++ ) + { + Word16 tmp_e; + Word32 tmpL, tmpR; + Word32 selL, selR; + Word16 selL_e, selR_e; + + selL = igf_specL_fx[strt_cpy]; + move32(); + selL_e = igf_specL_e_arr[strt_cpy]; + move16(); + selR = igf_specR_fx[strt_cpy]; + move32(); + selR_e = igf_specR_e_arr[strt_cpy]; + move16(); + IF( selectionL ) + { + selL = src_specL_fx[strt_cpy]; + move32(); + selL_e = src_specL_e; + move16(); + } + IF( selectionR ) + { + selR = src_specR_fx[strt_cpy]; + move32(); + selR_e = src_specR_e; + move16(); + } + + IF( EQ_16( coreMsMask[tb], 0 ) ) + { + IF( EQ_16( coreMsMask[strt_cpy], 0 ) ) /* LR->LR */ + { + igf_specL_fx[tb] = selL; + move32(); + igf_specL_e_arr[tb] = selL_e; + move16(); + } + ELSE /* MS/DR -> LR */ + { + tmpL = Mpy_32_32( selL, c_fx ); + tmpR = Mpy_32_32( selR, c_fx ); + igf_specL_fx[tb] = BASOP_Util_Add_Mant32Exp( tmpL, selL_e, tmpR, selR_e, &tmp_e ); + move32(); + igf_specL_e_arr[tb] = tmp_e; + move16(); + } + } + ELSE + { + IF( EQ_16( coreMsMask[strt_cpy], 0 ) ) /* LR->MS/DR */ + { + tmpL = Mpy_32_32( selL, c_fx ); + tmpR = Mpy_32_32( selR, c_fx ); + igf_specL_fx[tb] = BASOP_Util_Add_Mant32Exp( tmpL, selL_e, tmpR, selR_e, &tmp_e ); + move32(); + igf_specL_e_arr[tb] = tmp_e; + move16(); + } + ELSE /* MS/DR -> MS/DR */ + { + igf_specL_fx[tb] = selL; + move32(); + igf_specL_e_arr[tb] = selL_e; + move16(); + } + } + strt_cpy = add( strt_cpy, 1 ); + } + } + } + + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + IF( EQ_16( IGF_WHITENING_STRONG, hPrivateDataR->currWhiteningLevel[tile_idx] ) ) + { + tb = swb_offset[hGrid->sfbWrap[tile_idx]]; + + FOR( tb = swb_offset[hGrid->sfbWrap[tile_idx]]; tb < swb_offset[hGrid->sfbWrap[tile_idx + 1]]; tb++ ) + { + igf_specR_fx[tb] = L_deposit_l( Random( hInfoR->nfSeed ) ); /* 31Q0, fill LSBs */ + move32(); + igf_specR_e_arr[tb] = 31; + move16(); + } + } + ELSE + { + IF( NE_16( hPrivateDataR->currWhiteningLevel[tile_idx], hPrivateDataL->currWhiteningLevel[tile_idx] ) ) + { + IF( EQ_16( IGF_WHITENING_MID, hPrivateDataR->currWhiteningLevel[tile_idx] ) ) + { + IF( hPrivateDataL->n_noise_bands ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specL_fx, + igf_specL_e_arr, + TCXNoiseL, + strt_cpy, + stop, + hPrivateDataL->totalNoiseNrg, + hPrivateDataL->totalNoiseNrg_exp, + hPrivateDataL->n_noise_bands, + hInfoL->nfSeed ); + } + selectionL = 0; + move16(); + } + ELSE + { + IF( hPrivateDataL->n_noise_bands_off ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specL_fx, + igf_specL_e_arr, + TCXNoiseL, + strt_cpy, + stop, + hPrivateDataL->totalNoiseNrg_off, + hPrivateDataL->totalNoiseNrg_off_exp, + hPrivateDataL->n_noise_bands_off, + hInfoL->nfSeed ); + } + selectionL = 1; + move16(); + } + + IF( EQ_16( IGF_WHITENING_MID, hPrivateDataR->currWhiteningLevel[tile_idx] ) ) + { + IF( hPrivateDataR->n_noise_bands ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specR_fx, + igf_specR_e_arr, + TCXNoiseR, + strt_cpy, + stop, + hPrivateDataR->totalNoiseNrg, + hPrivateDataR->totalNoiseNrg_exp, + hPrivateDataR->n_noise_bands, + hInfoR->nfSeed ); + } + selectionR = 0; + move16(); + } + ELSE + { + IF( hPrivateDataR->n_noise_bands_off ) + { + IGF_replaceTCXNoise_2_new_ivas_with_var_shift( igf_specR_fx, + igf_specR_e_arr, + TCXNoiseR, + strt_cpy, + stop, + hPrivateDataR->totalNoiseNrg_off, + hPrivateDataR->totalNoiseNrg_off_exp, + hPrivateDataR->n_noise_bands_off, + hInfoR->nfSeed ); + } + selectionR = 1; + move16(); + } + } + + FOR( sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++ ) + { + FOR( tb = swb_offset[sfb]; tb < swb_offset[sfb + 1]; tb++ ) + { + Word32 tmpL, tmpR; + Word16 tmp_e; + Word32 selL, selR; + Word16 selL_e, selR_e; + + selL = igf_specL_fx[strt_cpy]; + move32(); + selL_e = igf_specL_e_arr[strt_cpy]; + move16(); + selR = igf_specR_fx[strt_cpy]; + move32(); + selR_e = igf_specR_e_arr[strt_cpy]; + move16(); + IF( selectionL ) + { + selL = src_specL_fx[strt_cpy]; + move32(); + selL_e = src_specL_e; + move16(); + } + IF( selectionR ) + { + selR = src_specR_fx[strt_cpy]; + move32(); + selR_e = src_specR_e; + move16(); + } + + IF( EQ_16( coreMsMask[tb], 0 ) ) + { + IF( EQ_16( coreMsMask[strt_cpy], 0 ) ) /* LR->LR */ + { + igf_specR_fx[tb] = selR; + move32(); + igf_specR_e_arr[tb] = selR_e; + move16(); + } + ELSE /* MS/DR -> LR */ + { + tmpL = Mpy_32_32( selL, c_fx ); + tmpR = Mpy_32_32( selR, c_fx ); + igf_specR_fx[tb] = BASOP_Util_Add_Mant32Exp( tmpL, selL_e, L_negate( tmpR ), selR_e, &tmp_e ); + move32(); + igf_specR_e_arr[tb] = tmp_e; + move16(); + } + } + ELSE + { + IF( EQ_16( coreMsMask[strt_cpy], 0 ) ) /* LR->MS/DR */ + { + tmpL = Mpy_32_32( selL, c_fx ); + tmpR = Mpy_32_32( selR, c_fx ); + igf_specR_fx[tb] = BASOP_Util_Add_Mant32Exp( tmpL, selL_e, L_negate( tmpR ), selR_e, &tmp_e ); + move32(); + igf_specR_e_arr[tb] = tmp_e; + move16(); + } + ELSE /* MS/DR -> MS/DR */ + { + igf_specR_fx[tb] = selR; + move32(); + igf_specR_e_arr[tb] = selR_e; + move16(); + } + } + strt_cpy = add( strt_cpy, 1 ); + } + } + } + } + + return; +} + /**********************************************************************/ /* calculates IGF energies **************************************************************************/ @@ -2996,7 +3590,7 @@ void IGFDecApplyMono_ivas( const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in FOR( i = 0; i < hGrid->nTiles; i++ ) { - IF( hPrivateData->currWhiteningLevel[i] == IGF_WHITENING_OFF ) + IF( EQ_16( hPrivateData->currWhiteningLevel[i], IGF_WHITENING_OFF ) ) { hPrivateData->headroom_TCX_noise = IGF_getScaleFactor32Cond( hInstance->infoTCXNoise_evs + hGrid->minSrcSubband, @@ -3052,6 +3646,352 @@ void IGFDecApplyMono_ivas( const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in } } +/**********************************************************************/ /* +apply the IGF decoder in stereo +**************************************************************************/ +void IGFDecApplyStereo( + const IGF_DEC_INSTANCE_HANDLE hIGFDecL, /* i : instance handle of IGF Decoder */ + const IGF_DEC_INSTANCE_HANDLE hIGFDecR, /* i : instance handle of IGF Decoder */ + Word32 *spectrumL_fx, /* i/o: L MDCT spectrum */ + Word16 *spectrumL_e, /* i/o: L MDCT spectrum exp */ + Word32 *spectrumR_fx, /* i/o: R MDCT spectrum */ + Word16 *spectrumR_e, /* i/o: R MDCT spectrum exp */ + const Word16 igfGridIdx, /* i : in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 *coreMsMask, + const Word16 restrict_hopsize, + const Word16 bfi, /* i : frame loss == 1, frame good == 0 */ + const Word16 bfi_apply_damping ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateDataL, hPrivateDataR; + H_IGF_GRID hGrid; + Word16 i, whiteningLevel; + float igf_specL[IGF_MAX_GRANULE_LEN], igf_specR[IGF_MAX_GRANULE_LEN]; + Word32 igf_specL_fx[IGF_MAX_GRANULE_LEN]; + Word32 igf_specR_fx[IGF_MAX_GRANULE_LEN]; + Word16 igf_specL_e[IGF_MAX_TILES]; + Word16 igf_specR_e[IGF_MAX_TILES]; + Word16 igf_specL_e_arr[IGF_MAX_GRANULE_LEN]; + Word16 igf_specR_e_arr[IGF_MAX_GRANULE_LEN]; + + Word16 specMedL_e; /* | exponent of the medium whitened spectrum */ + Word16 specMedR_e; /* | exponent of the medium whitened spectrum */ + Word16 v_len; + Word16 s_l; + + set_f( igf_specL, 0.f, IGF_MAX_GRANULE_LEN ); + set_f( igf_specR, 0.f, IGF_MAX_GRANULE_LEN ); + + set32_fx(igf_specL_fx, 0, IGF_MAX_GRANULE_LEN); + set32_fx(igf_specR_fx, 0, IGF_MAX_GRANULE_LEN); + set16_fx(igf_specL_e, 0, IGF_MAX_TILES); + set16_fx(igf_specR_e, 0, IGF_MAX_TILES); + set16_fx(igf_specL_e_arr, 0, IGF_MAX_GRANULE_LEN); + set16_fx(igf_specR_e_arr, 0, IGF_MAX_GRANULE_LEN); + + /* initialize variables */ + whiteningLevel = IGF_MID_WHITENING_LEVEL2; + move16(); + + IF(EQ_16(igfGridIdx, IGF_GRID_LB_SHORT)) + { + v_len = ( N_MAX_TCX - IGF_START_MN ) / 2; + move16(); + } + ELSE + { + v_len = (N_MAX_TCX - IGF_START_MN); + move16(); + } + + set16_fx( hIGFDecL->flag_sparse, 0, v_len ); + set16_fx( hIGFDecR->flag_sparse, 0, v_len ); + + /* TODO: remove float code */ + set_f( hIGFDecL->virtualSpec_float, 0.f, v_len ); + set_f( hIGFDecR->virtualSpec_float, 0.f, v_len ); + + set32_fx( hIGFDecL->virtualSpec_fx, 0, v_len ); + set32_fx( hIGFDecR->virtualSpec_fx, 0, v_len ); + + hPrivateDataL = &hIGFDecL->igfData; + hGrid = &hPrivateDataL->igfInfo.grid[igfGridIdx]; + hPrivateDataL->n_noise_bands = 0; + move16(); + hPrivateDataL->n_noise_bands_off = 0; + move16(); + hPrivateDataL->restrict_hopsize = restrict_hopsize; + move16(); + + hPrivateDataR = &hIGFDecR->igfData; + hPrivateDataR->n_noise_bands = 0; + move16(); + hPrivateDataR->n_noise_bands_off = 0; + move16(); + hPrivateDataR->restrict_hopsize = restrict_hopsize; + move16(); + + specMedL_e = 0; + move16(); + specMedR_e = 0; + move16(); + hPrivateDataL->totalNoiseNrg = 0; + move32(); + hPrivateDataL->totalNoiseNrg_off = 0; + move32(); + hPrivateDataR->totalNoiseNrg = 0; + move32(); + hPrivateDataR->totalNoiseNrg_off = 0; + move32(); + hPrivateDataL->totalNoiseNrg_exp = 0; + move16(); + hPrivateDataL->totalNoiseNrg_off_exp = 0; + move16(); + hPrivateDataR->totalNoiseNrg_exp = 0; + move16(); + hPrivateDataR->totalNoiseNrg_off_exp = 0; + move16(); + + /* TODO: remove float code: */ + hPrivateDataL->totalNoiseNrg_float = 0.f; + hPrivateDataL->totalNoiseNrg_off_float = 0.f; + hPrivateDataR->totalNoiseNrg_float = 0.f; + hPrivateDataR->totalNoiseNrg_off_float = 0.f; + + /* concealment counter */ + IF ( bfi ) + { + hPrivateDataL->frameLossCounter = add(hPrivateDataL->frameLossCounter,1); + hPrivateDataR->frameLossCounter = add(hPrivateDataR->frameLossCounter,1); + } + ELSE + { + hPrivateDataL->frameLossCounter = 0; + move16(); + hPrivateDataR->frameLossCounter = 0; + move16(); + } + + /* skip IGF processing if all IGF levels are zero */ + test(); + IF ( !hIGFDecL->infoIGFAllZero || !hIGFDecR->infoIGFAllZero ) + { + FOR ( i = 0; i < hGrid->nTiles; i++ ) + { + test(); + IF ( EQ_16(hPrivateDataL->currWhiteningLevel[i], IGF_WHITENING_MID) || EQ_16(hPrivateDataR->currWhiteningLevel[i], IGF_WHITENING_MID) ) + { + IF ( !bfi ) + { + s_l = getScaleFactor32(hPrivateDataL->pSpecFlat + hGrid->minSrcSubband - whiteningLevel, + add(sub(hGrid->startLine, hGrid->minSrcSubband), whiteningLevel)); + IGF_getWhiteSpectralData_ivas( hPrivateDataL->pSpecFlat, + hPrivateDataL->pSpecFlat_exp, + s_l, + igf_specL_fx, + &specMedL_e, + hGrid->minSrcSubband, + hGrid->startLine, + whiteningLevel ); + } + ELSE + { + Copy32( hPrivateDataL->pSpecFlat, igf_specL_fx, hGrid->startLine ); + specMedL_e = hPrivateDataL->pSpecFlat_exp; + move16(); + } + + hPrivateDataL->headroom_TCX_noise_white = IGF_getScaleFactor32Cond( hIGFDecL->infoTCXNoise_evs + hGrid->minSrcSubband, + igf_specL_fx + hGrid->minSrcSubband, + sub( hGrid->startLine, hGrid->minSrcSubband ) ); + hPrivateDataL->n_noise_bands = IGF_replaceTCXNoise_1( igf_specL_fx, + hPrivateDataL->headroom_TCX_noise_white, + hIGFDecL->infoTCXNoise_evs, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateDataL->totalNoiseNrg ); + + hPrivateDataL->totalNoiseNrg_exp = shl( sub( specMedL_e, sub( hPrivateDataL->headroom_TCX_noise_white, 5 ) ), 1 ); + + IF ( !bfi ) + { + s_l = getScaleFactor32(hPrivateDataR->pSpecFlat + hGrid->minSrcSubband - whiteningLevel, + add(sub(hGrid->startLine, hGrid->minSrcSubband), whiteningLevel)); + IGF_getWhiteSpectralData_ivas( hPrivateDataR->pSpecFlat, + hPrivateDataR->pSpecFlat_exp, + s_l, + igf_specR_fx, + &specMedR_e, + hGrid->minSrcSubband, + hGrid->startLine, + whiteningLevel ); + } + ELSE + { + Copy32( hPrivateDataR->pSpecFlat, igf_specR_fx, hGrid->startLine ); + specMedR_e = hPrivateDataL->pSpecFlat_exp; + move16(); + } + + hPrivateDataR->headroom_TCX_noise_white = IGF_getScaleFactor32Cond( hIGFDecR->infoTCXNoise_evs + hGrid->minSrcSubband, + igf_specR_fx + hGrid->minSrcSubband, + sub( hGrid->startLine, hGrid->minSrcSubband ) ); + hPrivateDataR->n_noise_bands = IGF_replaceTCXNoise_1( igf_specR_fx, + hPrivateDataR->headroom_TCX_noise_white, + hIGFDecR->infoTCXNoise_evs, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateDataR->totalNoiseNrg ); + hPrivateDataR->totalNoiseNrg_exp = shl( sub( specMedR_e, sub( hPrivateDataR->headroom_TCX_noise_white, 5 ) ), 1 ); + + BREAK; + } + } + + FOR( i = 0; i < hGrid->nTiles; i++ ) + { + test(); + IF( EQ_16( hPrivateDataL->currWhiteningLevel[i], IGF_WHITENING_OFF ) || EQ_16( hPrivateDataR->currWhiteningLevel[i], IGF_WHITENING_OFF ) ) + { + hPrivateDataL->headroom_TCX_noise_white = IGF_getScaleFactor32Cond( hIGFDecL->infoTCXNoise_evs + hGrid->minSrcSubband, + hPrivateDataL->pSpecFlat + hGrid->minSrcSubband, + sub( hGrid->startLine, hGrid->minSrcSubband ) ); + hPrivateDataL->n_noise_bands_off = IGF_replaceTCXNoise_1( hPrivateDataL->pSpecFlat, + hPrivateDataL->headroom_TCX_noise_white, + hIGFDecL->infoTCXNoise_evs, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateDataL->totalNoiseNrg_off ); + hPrivateDataL->totalNoiseNrg_off_exp = shl( sub( hPrivateDataL->pSpecFlat_exp, sub( hPrivateDataL->headroom_TCX_noise_white, 5 ) ), 1 ); + + hPrivateDataR->headroom_TCX_noise_white = IGF_getScaleFactor32Cond( hIGFDecR->infoTCXNoise_evs + hGrid->minSrcSubband, + hPrivateDataR->pSpecFlat + hGrid->minSrcSubband, + sub( hGrid->startLine, hGrid->minSrcSubband ) ); + hPrivateDataR->n_noise_bands_off = IGF_replaceTCXNoise_1( hPrivateDataR->pSpecFlat, + hPrivateDataR->headroom_TCX_noise_white, + hIGFDecR->infoTCXNoise_evs, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateDataR->totalNoiseNrg_off ); + hPrivateDataR->totalNoiseNrg_off_exp = shl( sub( hPrivateDataR->pSpecFlat_exp, sub( hPrivateDataR->headroom_TCX_noise_white, 5 ) ), 1 ); + + + BREAK; + } + } + + /* apply IGF in three steps: */ + IF( specMedL_e ) + { + set16_fx( igf_specL_e_arr + hGrid->minSrcSubband, specMedL_e, sub( hGrid->stopLine, hGrid->minSrcSubband ) ); + } + IF( specMedR_e ) + { + set16_fx( igf_specR_e_arr + hGrid->minSrcSubband, specMedR_e, sub( hGrid->stopLine, hGrid->minSrcSubband ) ); + } + + IGF_prepStereo( hPrivateDataL, + hPrivateDataR, + igfGridIdx, + hIGFDecL->infoTCXNoise_evs, + hIGFDecR->infoTCXNoise_evs, + igf_specL_fx, + igf_specL_e_arr, + igf_specR_fx, + igf_specR_e_arr, + hPrivateDataL->pSpecFlat, + hPrivateDataL->pSpecFlat_exp, + hPrivateDataR->pSpecFlat, + hPrivateDataR->pSpecFlat_exp, + coreMsMask ); + + IGF_convert_exponent_per_idx_to_per_tile( + hGrid, + igf_specL_fx, + igf_specL_e_arr, + igf_specL_e ); + IGF_convert_exponent_per_idx_to_per_tile( + hGrid, + igf_specR_fx, + igf_specR_e_arr, + igf_specR_e ); + + // Fixed to float + FOR(i = 0; i < hGrid->nTiles; i++) + { + Word16 start = hGrid->tile[i]; + Word16 stop = hGrid->tile[i + 1]; + me2f_buf(igf_specL_fx + start, igf_specL_e[i], igf_specL + start, stop - start); + me2f_buf(igf_specR_fx + start, igf_specR_e[i], igf_specR + start, stop - start); + } + //for (int l = hGrid->minSrcSubband; l < hGrid->stopLine; l++) + //{ + // igf_specL[l] = me2f(igf_specL_fx[l], igf_specL_e_arr[l]); + // igf_specR[l] = me2f(igf_specR_fx[l], igf_specR_e_arr[l]); + //} + hPrivateDataL->totalNoiseNrg_float = me2f(hPrivateDataL->totalNoiseNrg, hPrivateDataL->totalNoiseNrg_exp); + hPrivateDataR->totalNoiseNrg_float = me2f(hPrivateDataR->totalNoiseNrg, hPrivateDataR->totalNoiseNrg_exp); + hPrivateDataL->totalNoiseNrg_off_float = me2f(hPrivateDataL->totalNoiseNrg_off, hPrivateDataL->totalNoiseNrg_off_exp); + hPrivateDataR->totalNoiseNrg_off_float = me2f(hPrivateDataR->totalNoiseNrg_off, hPrivateDataR->totalNoiseNrg_off_exp); + + //IGF_calc_flt( hPrivateDataL, igfGridIdx, spectrumL, igf_specL ); + //IGF_calc_flt( hPrivateDataR, igfGridIdx, spectrumR, igf_specR ); + //IGF_appl_flt( hPrivateDataL, igfGridIdx, spectrumL, igf_specL, hIGFDecL->virtualSpec_float, hIGFDecL->flag_sparse, bfi_apply_damping ); + //IGF_appl_flt( hPrivateDataR, igfGridIdx, spectrumR, igf_specR, hIGFDecR->virtualSpec_float, hIGFDecR->flag_sparse, bfi_apply_damping ); + + IGF_calc_ivas( hPrivateDataL, + igfGridIdx, + spectrumL_fx, + *spectrumL_e, + igf_specL_fx, + igf_specL_e); + IGF_calc_ivas(hPrivateDataR, + igfGridIdx, + spectrumR_fx, + *spectrumR_e, + igf_specR_fx, + igf_specR_e); + IGF_appl_ivas(hPrivateDataL, + igfGridIdx, + spectrumL_fx, + spectrumL_e, + igf_specL_fx, + igf_specL_e, + hIGFDecL->virtualSpec, + &hIGFDecL->virtualSpec_e, + hIGFDecL->flag_sparseBuf, + bfi_apply_damping); + IGF_appl_ivas(hPrivateDataR, + igfGridIdx, + spectrumR_fx, + spectrumR_e, + igf_specR_fx, + igf_specR_e, + hIGFDecR->virtualSpec, + &hIGFDecR->virtualSpec_e, + hIGFDecR->flag_sparseBuf, + bfi_apply_damping); + } + + /* reset TCX noise indicator vector */ + IF( EQ_16( igfGridIdx, IGF_GRID_LB_SHORT ) ) + { + set_c( (int8_t *) ( hIGFDecL->infoTCXNoise ), 0, IGF_START_MX / 2 ); + set_c( (int8_t *) ( hIGFDecR->infoTCXNoise ), 0, IGF_START_MX / 2 ); + set16_fx( hIGFDecL->infoTCXNoise_evs, 0, IGF_START_MX / 2 ); + set16_fx( hIGFDecR->infoTCXNoise_evs, 0, IGF_START_MX / 2 ); + } + ELSE + { + set_c( (int8_t *) ( hIGFDecL->infoTCXNoise ), 0, IGF_START_MX ); + set_c( (int8_t *) ( hIGFDecR->infoTCXNoise ), 0, IGF_START_MX ); + set16_fx( hIGFDecL->infoTCXNoise_evs, 0, IGF_START_MX ); + set16_fx( hIGFDecR->infoTCXNoise_evs, 0, IGF_START_MX ); + } + + return; +} + + /**********************************************************************/ /* set mode is used to init the IGF dec with a new bitrate **************************************************************************/ @@ -3202,12 +4142,12 @@ void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, } /*-------------------------------------------------------------------* - * IGFDecUpdateInfo_fx() + * IGFDecUpdateInfo_ivas_fx() * * updates the start/stop frequency of IGF according to igfGridIdx *-------------------------------------------------------------------*/ -void IGFDecUpdateInfo_fx( +void IGFDecUpdateInfo_ivas_fx( const IGF_DEC_INSTANCE_HANDLE hIGFDec, /* i/o: instance handle of IGF Decoder */ const Word16 subFrameIdx, /* i : index of subframe */ const Word16 igfGridIdx /* i : IGF grid index */ @@ -3234,7 +4174,7 @@ void IGFDecUpdateInfo_fx( } hPrivateData = &hIGFDec->igfData; - if ( hIGFDec->isIGFActive ) + IF ( hIGFDec->isIGFActive ) { hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; hIGFDec->infoIGFStartFreq = hGrid->startFrequency; @@ -3243,6 +4183,13 @@ void IGFDecUpdateInfo_fx( hIGFDec->infoIGFStopLine = hGrid->stopLine; } + /* TODO: this was added to keep the EVS 16-bit noise info in sync. */ + FOR(int l = 0; l < IGF_START_MX; l++) + { + // u8bit to 16bit + hIGFDec->infoTCXNoise_evs[l] = (Word16)hIGFDec->infoTCXNoise[l]; + } + return; } diff --git a/lib_dec/ivas_mct_core_dec.c b/lib_dec/ivas_mct_core_dec.c index c5e020653bea24e879020a258a698712c533587a..f04208fab94b5d7a376cf027eb3f165f094fb4ae 100644 --- a/lib_dec/ivas_mct_core_dec.c +++ b/lib_dec/ivas_mct_core_dec.c @@ -250,10 +250,42 @@ void ivas_mct_core_dec( { L_spec = st->hTcxCfg->tcx_coded_lines / nSubframes; - init_tcx_info( st, st->L_frame / nSubframes, st->hTcxDec->L_frameTCX / nSubframes, k, bfi, &tcx_offset, &tcx_offsetFB, &L_frame, &L_frameTCX, &left_rect, &L_spec ); +#ifdef IVAS_FLOAT_FIXED + init_tcx_info_fx( st, st->L_frame / nSubframes, st->hTcxDec->L_frameTCX / nSubframes, k, bfi, &tcx_offset, &tcx_offsetFB, &L_frame, &L_frameTCX, &left_rect, &L_spec ); + + // Float to fixed + Word32 x_fx[N_MAX]; + Word16 x_e, stop; + Word16 tmp_igfGridIdx = IGF_GRID_LB_SHORT; + IF(NE_16(L_frame, shr(st->L_frame, 1)) && st->tcxonly) + { + tmp_igfGridIdx = (EQ_16(st->last_core, ACELP_CORE) || (left_rect && bfi)) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; + } + stop = st->hIGFDec->igfData.igfInfo.grid[tmp_igfGridIdx].stopLine; + IF(st->igf) + { + f2me_buf(x[ch][k], x_fx, &x_e, stop); + } + /* mono or dual mono IGF decoding */ + decoder_tcx_IGF_mono_fx( st, x_fx, &x_e, L_frame, left_rect, bfi, k ); + + IF(st->igf) + { + // Fixed to float + me2f_buf(x_fx, x_e, x[ch][k], stop); + me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, (N_MAX_TCX - IGF_START_MN)); + // 16bit to u8bit + FOR(Word16 l = 0; l < IGF_START_MX; l++) + { + st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; + } + } +#else + init_tcx_info( st, st->L_frame / nSubframes, st->hTcxDec->L_frameTCX / nSubframes, k, bfi, &tcx_offset, &tcx_offsetFB, &L_frame, &L_frameTCX, &left_rect, &L_spec ); /* mono or dual mono IGF decoding */ decoder_tcx_IGF_mono( st, x[ch][k], L_frame, left_rect, bfi, k ); +#endif } } } diff --git a/lib_dec/ivas_mct_dec_mct_fx.c b/lib_dec/ivas_mct_dec_mct_fx.c index e541ff96dbfd30ce805b7ae3c7b3afb23f449fcc..7de40a898efc6304b65bd675ea8abc09bebbd05c 100644 --- a/lib_dec/ivas_mct_dec_mct_fx.c +++ b/lib_dec/ivas_mct_dec_mct_fx.c @@ -334,7 +334,7 @@ void mctStereoIGF_dec_fx( #ifdef IVAS_FLOAT_FIX_TBD decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); #else - decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x_flt, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); + decoder_tcx_IGF_stereo_fx( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x_flt, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); #endif } ELSE @@ -365,7 +365,34 @@ void mctStereoIGF_dec_fx( Float32 *x_flt = malloc( ( L_FRAME48k / 2 ) * sizeof( Float32 ) ); fixedToFloat_arrL( x[p_ch[ch]][k], x_flt, Q12, L_FRAME48k / 2 ); - decoder_tcx_IGF_mono( st, x_flt, L_frame[ch], left_rect[ch], bfi, k ); + + // Float to fixed + Word32 x_fx[N_MAX]; + Word16 x_e, stop; + Word16 tmp_igfGridIdx = IGF_GRID_LB_SHORT; + IF(NE_16(L_frame[ch], shr(st->L_frame, 1)) && st->tcxonly) + { + tmp_igfGridIdx = (EQ_16(st->last_core, ACELP_CORE) || (left_rect[ch] && bfi)) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; + } + stop = st->hIGFDec->igfData.igfInfo.grid[tmp_igfGridIdx].stopLine; + IF(st->igf) + { + f2me_buf(x_flt, x_fx, &x_e, stop); + } + + decoder_tcx_IGF_mono_fx( st, x_fx, &x_e, L_frame[ch], left_rect[ch], bfi, k ); + + IF(st->igf) + { + // Fixed to float + me2f_buf(x_fx, x_e, x_flt, stop); + me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, (N_MAX_TCX - IGF_START_MN)); + // 16bit to u8bit + FOR(Word16 l = 0; l < IGF_START_MX; l++) + { + st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; + } + } floatToFixed_arrL( x_flt, x[p_ch[ch]][k], Q12, L_FRAME48k / 2 ); @@ -409,7 +436,8 @@ void mctStereoIGF_dec_fx( #ifndef IVAS_FLOAT_FIX_TBD Float32 *x_flt[NB_DIV]; - x_flt[0] = malloc( ( L_FRAME48k ) * sizeof( Float32 ) ); + //x_flt[0] = malloc( ( L_FRAME48k ) * sizeof( Float32 ) ); + x_flt[0] = malloc( ( 2*N_MAX ) * sizeof( Float32 ) ); x_flt[1] = x_flt[0] + L_FRAME48k / 2; fixedToFloat_arrL( x[ch][0], x_flt[0], Q12, L_FRAME48k / 2 ); @@ -433,7 +461,32 @@ void mctStereoIGF_dec_fx( #ifdef IVAS_FLOAT_FIX_TBD decoder_tcx_IGF_mono( st, x[ch][k], L_frame[0], left_rect[0], bfi, k ); #else - decoder_tcx_IGF_mono( st, x_flt[k], L_frame[0], left_rect[0], bfi, k ); + // Float to fixed + Word32 x_fx[N_MAX]; + Word16 x_e, stop; + Word16 tmp_igfGridIdx = IGF_GRID_LB_SHORT; + IF(NE_16(L_frame[0], shr(st->L_frame, 1)) && st->tcxonly) + { + tmp_igfGridIdx = (EQ_16(st->last_core, ACELP_CORE) || (left_rect[0] && bfi)) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; + } + stop = st->hIGFDec->igfData.igfInfo.grid[tmp_igfGridIdx].stopLine; + IF(st->igf) + { + f2me_buf(x_flt[k], x_fx, &x_e, stop); + } + decoder_tcx_IGF_mono_fx( st, x_fx, &x_e, L_frame[0], left_rect[0], bfi, k ); + + IF(st->igf) + { + // Fixed to float + me2f_buf(x_fx, x_e, x_flt[k], stop); + me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, (N_MAX_TCX - IGF_START_MN)); + // 16bit to u8bit + FOR(Word16 l = 0; l < IGF_START_MX; l++) + { + st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; + } + } #endif } #ifndef IVAS_FLOAT_FIX_TBD diff --git a/lib_dec/ivas_stereo_mdct_core_dec_fx.c b/lib_dec/ivas_stereo_mdct_core_dec_fx.c index 07f059e960ff73f5f405386b6216675982e22ed0..31c92055e12d8713a06fae53f8916522f851ca29 100644 --- a/lib_dec/ivas_stereo_mdct_core_dec_fx.c +++ b/lib_dec/ivas_stereo_mdct_core_dec_fx.c @@ -233,7 +233,36 @@ void stereo_mdct_core_dec_fx( for ( k = 0; k < nSubframes[ch]; k++ ) { /* mono or dual mono IGF decoding */ +#ifdef IVAS_FLOAT_FIXED + //// Float to fixed + Word32 x_fx[N_MAX]; + Word16 x_e; + Word16 stop = 0; + Word16 tmp_igfGridIdx = IGF_GRID_LB_SHORT; + IF(NE_16(L_frame[ch], shr(st->L_frame, 1)) && st->tcxonly) + { + tmp_igfGridIdx = (EQ_16(st->last_core, ACELP_CORE) || (left_rect[ch] && bfi)) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; + } + stop = st->hIGFDec->igfData.igfInfo.grid[tmp_igfGridIdx].stopLine; + IF(st->igf) + { + f2me_buf(x[ch][k], x_fx, &x_e, stop); + } + decoder_tcx_IGF_mono_fx( st, x_fx, &x_e, L_frame[ch], left_rect[ch], bfi, k ); + IF(st->igf) + { + // Fixed to float + me2f_buf(x_fx, x_e, x[ch][k], stop); + me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, ((tmp_igfGridIdx == IGF_GRID_LB_SHORT) ? (N_MAX_TCX - IGF_START_MN) / 2 : (N_MAX_TCX - IGF_START_MN))); + // 16bit to u8bit + FOR(Word16 l = 0; l < IGF_START_MX; l++) + { + st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; + } + } +#else decoder_tcx_IGF_mono( st, x[ch][k], L_frame[ch], left_rect[ch], bfi, k ); +#endif } } } @@ -249,7 +278,11 @@ void stereo_mdct_core_dec_fx( assert( ( sts[0]->core == sts[1]->core ) || ( hCPE->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) ); /* stereo IGF decoding */ +#ifdef IVAS_FLOAT_FIXED + decoder_tcx_IGF_stereo_fx( sts, hCPE->hStereoMdct, ms_mask, x, L_frame[0], left_rect[0], k, bfi, 0 /* MCT_flag */ ); +#else decoder_tcx_IGF_stereo( sts, hCPE->hStereoMdct, ms_mask, x, L_frame[0], left_rect[0], k, bfi, 0 /* MCT_flag */ ); +#endif } else { @@ -257,7 +290,37 @@ void stereo_mdct_core_dec_fx( { st = sts[ch]; /* mono or dual mono IGF decoding */ +#ifdef IVAS_FLOAT_FIXED + // Float to fixed + Word32 x_fx[N_MAX]; + Word16 x_e; + Word16 stop; + + Word16 tmp_igfGridIdx = IGF_GRID_LB_SHORT; + IF(NE_16(L_frame[ch], shr(st->L_frame, 1)) && st->tcxonly) + { + tmp_igfGridIdx = (EQ_16(st->last_core, ACELP_CORE) || (left_rect[ch] && bfi)) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM; + } + stop = st->hIGFDec->igfData.igfInfo.grid[tmp_igfGridIdx].stopLine; + IF(st->igf) + { + f2me_buf(x[ch][k], x_fx, &x_e, stop); + } + decoder_tcx_IGF_mono_fx( st, x_fx, &x_e, L_frame[ch], left_rect[ch], bfi, k ); + // Fixed to float + IF(st->igf) + { + me2f_buf(x_fx, x_e, x[ch][k], stop); + me2f_buf(st->hIGFDec->virtualSpec, st->hIGFDec->virtualSpec_e, st->hIGFDec->virtualSpec_float, (N_MAX_TCX - IGF_START_MN)); + // 16bit to u8bit + FOR(Word16 l = 0; l < IGF_START_MX; l++) + { + st->hIGFDec->infoTCXNoise[l] = (uint8_t)st->hIGFDec->infoTCXNoise_evs[l]; + } + } +#else decoder_tcx_IGF_mono( st, x[ch][k], L_frame[ch], left_rect[ch], bfi, k ); +#endif } } }