From 6cfcf27f5a82ffb774e10686a6d11b778dbf4f6a Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 21 Feb 2024 15:32:12 +0530 Subject: [PATCH] Functions in stereo_mdct_core_dec and sub-funcs converted to fxd [x] Functions is ivas_stereo_mdct_core_dec and related sub functions converted to fixed point. [x] ivas_mdct_core_tns_ns function is partially ported and untested yet. So function call is disabled currently. --- lib_com/ivas_prot.h | 8 + lib_com/ivas_prot_fx.h | 44 +++ lib_com/ivas_stereo_psychlpc_com.c | 20 ++ lib_com/prot_fx2.h | 12 + lib_com/tns_base.c | 166 +++++++++ lib_dec/core_dec_init.c | 2 +- lib_dec/dec_tcx.c | 539 ++++++++++++++++++++++++++++ lib_dec/igf_dec.c | 12 + lib_dec/ivas_init_dec.c | 3 + lib_dec/ivas_mdct_core_dec.c | 184 +++++++++- lib_dec/ivas_stereo_mdct_core_dec.c | 45 ++- 11 files changed, 1027 insertions(+), 8 deletions(-) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 826fbb1ae..7db30e207 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -2605,11 +2605,19 @@ void InitPsychLPC( const TCX_CONFIG_HANDLE hTcxCfg /* i : TCX configuration handle */ ); +#ifndef IVAS_FLOAT_FIXED void SetCurrentPsychParams( const int16_t core, const int16_t last_frame_was_concealed_cng, TCX_CONFIG_HANDLE hTcxCfg ); +#else +void SetCurrentPsychParams( + const Word16 core, + const Word16 last_frame_was_concealed_cng, + TCX_CONFIG_HANDLE hTcxCfg +); +#endif void stereo_coder_tcx( STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: MDCT encoder structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index b18dcbdd2..b60fcd60b 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -1153,5 +1153,49 @@ void stereo_icBWE_dec_fx( const Word16 output_frame, /* i : frame length */ Word16 *Q_syn ); + +void decoder_tcx_tns_fx( + Decoder_State *st, /* i/o: coder memory state */ + const Word16 L_frame_glob, /* i : frame length */ + const Word16 L_spec, + const Word16 L_frame, + const Word16 L_frameTCX, + Word32 x_fx[N_MAX], + const Word16 fUseTns, /* i : flag that is set if TNS data is present */ + STnsData *tnsData, + const Word16 bfi, /* i : Bad frame indicator */ + const Word16 frame_cnt, /* i : frame counter in the super frame */ + const Word16 whitenedDomain ); + +void ivas_mdct_core_tns_ns_fx( + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + Word16 fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10 */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ + Word32 *x_fx[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ + Word32 Aq_fx[CPE_CHANNELS][(NB_SUBFR16k + 1) * (M + 1)], /* o : LP coefficients */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + Word16 x_e[CPE_CHANNELS][NB_DIV] +); + +void decoder_tcx_imdct_fx( + Decoder_State *st, /* i/o: coder memory state */ + const int16_t L_frame_glob, /* i : frame length */ + const int16_t L_frameTCX_glob, + const int16_t L_spec, + const int16_t tcx_offset, + const int16_t tcx_offsetFB, + const int16_t L_frame, + const int16_t L_frameTCX, + const int16_t left_rect, + float x[N_MAX], + float xn_buf[], + const uint16_t kernelType, /* i : TCX transform kernel type */ + const int16_t fUseTns, /* i : flag that is set if TNS data is present */ + float synth[], /* i/o: synth[-M..L_frame] */ + float synthFB[], + const int16_t bfi, /* i : Bad frame indicator */ + const int16_t frame_cnt, /* i : frame counter in the super frame */ + const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ +); #endif diff --git a/lib_com/ivas_stereo_psychlpc_com.c b/lib_com/ivas_stereo_psychlpc_com.c index 52c99854c..c68350c1b 100644 --- a/lib_com/ivas_stereo_psychlpc_com.c +++ b/lib_com/ivas_stereo_psychlpc_com.c @@ -140,6 +140,7 @@ void InitPsychLPC( * *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void SetCurrentPsychParams( const int16_t core, const int16_t last_frame_was_concealed_cng, @@ -157,3 +158,22 @@ void SetCurrentPsychParams( return; } +#else +void SetCurrentPsychParams( + const Word16 core, + const Word16 last_frame_was_concealed_cng, + TCX_CONFIG_HANDLE hTcxCfg ) +{ + IF ( EQ_16(hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP) && EQ_16(last_frame_was_concealed_cng, 0) ) + { + assert( core == TCX_20_CORE ); + hTcxCfg->psychParamsCurrent = &hTcxCfg->psychParamsTCX20AfterACELP; + } + ELSE + { + hTcxCfg->psychParamsCurrent = ( EQ_16(core, TCX_10_CORE) ) ? &hTcxCfg->psychParamsTCX10 : &hTcxCfg->psychParamsTCX20; + } + + return; +} +#endif diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index a1a1888ba..077987876 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -3114,6 +3114,18 @@ Word16 ITF_Detect_fx(Word32 const pSpectrum[], Word16* curr_order, Word16 Q); +Word16 ITF_Detect_ivas_fx( + const Word32 pSpectrum[], + const Word16 startLine, + const Word16 stopLine, + const Word16 maxOrder, + Word16* A, + Word16* Q_A, + Word16* predictionGain, + Word16* curr_order, + Word16 Q +); + void ITF_Apply_fx(Word32 spectrum[], Word16 startLine, Word16 stopLine, const Word16* A, Word16 Q_A, diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index 225a614b8..500938994 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -468,7 +468,173 @@ Word16 ITF_Detect_fx( return 1; } +Word16 ITF_Detect_ivas_fx( + const Word32 pSpectrum[], + const Word16 startLine, + const Word16 stopLine, + const Word16 maxOrder, + Word16* A, + Word16* Q_A, + Word16* predictionGain, + Word16* curr_order, + Word16 Q +) +{ + + Word16 spectrumLength; + Word16 const nSubdivisions = MAX_SUBDIVISIONS; + Word16 iSubdivisions; + Word16 iStartLine; + Word16 iEndLine; + Word16 facs[MAX_SUBDIVISIONS]; + Word16 facs_e[MAX_SUBDIVISIONS]; /* exponents of facs[][] */ + Word16 shifts[MAX_SUBDIVISIONS]; + Word16 tmp, headroom, shift; + Word32 rxx[ITF_MAX_FILTER_ORDER+1]; + Word16 lag; + Word32 L_tmp, tmp32; + Word16 tmpbuf[325]; + Word16 n, i; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + move16(); + move16(); + move16(); + + if (maxOrder <= 0) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + tmp = sub(stopLine, startLine); + iStartLine = imult1616(tmp, iSubdivisions); + iEndLine = add(iStartLine, tmp); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, startLine); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, startLine); + headroom = getScaleFactor32(pSpectrum+iStartLine-IGF_START_MN, sub(iEndLine, iStartLine)); + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm(pSpectrum+iStartLine-IGF_START_MN, headroom, sub(iEndLine, iStartLine), &shift); + + /* Check threshold HLM_MIN_NRG */ + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + tmp32 = L_sub(L_shl_o(L_tmp, sub(shift, 24-Q), &Overflow), 4194304l/*HLM_MIN_NRG Q7*/); +#else /* BASOP_NOGLOB */ + tmp32 = L_sub(L_shl(L_tmp, sub(shift, 24-Q)), 4194304l/*HLM_MIN_NRG Q7*/); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + + /* get pre-shift for autocorrelation */ + tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */ + tmp = shr(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */ + shifts[iSubdivisions] = s_min(tmp, headroom); + move16(); + + /* calc normalization factor */ + facs[iSubdivisions] = 0; + move16(); + facs_e[iSubdivisions] = 0; + move16(); + + if (tmp32 > 0) + { + facs[iSubdivisions] = 0x7FFF; + move16(); /* normalization not needed for one subdivision */ + } + + test(); + IF ((tmp32 > 0) && (GT_16(nSubdivisions, 1))) + { + move16(); + facs_e[iSubdivisions] = shl(sub(tmp, shifts[iSubdivisions]), 1); + + tmp = sub(1, shl(tmp, 1)); /* exponent of autocorrelation */ + L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */ + + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + facs[iSubdivisions] = div_s(0x2000, round_fx_o(L_tmp, &Overflow)); /* L_tmp is >= 0x2000000 */ move16(); + } + + } + + /* Calculate normalized autocorrelation for spectrum subdivision and get filter parameters based on it */ + set32_fx(rxx, 0, ITF_MAX_FILTER_ORDER+1); + + spectrumLength = sub(stopLine, startLine); + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + IF ( facs[iSubdivisions] == 0 ) + { + BREAK; + } + + + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + iStartLine = imult1616(spectrumLength, iSubdivisions); + iEndLine = add(iStartLine, spectrumLength); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, startLine); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, startLine); + + + move16(); + shift = shifts[iSubdivisions]; + n = sub(iEndLine, iStartLine); + assert(n < (Word16)(sizeof(tmpbuf)/sizeof(Word16))); + FOR (i = 0; i < n; i++) + { + tmpbuf[i] = round_fx(L_shl(pSpectrum[iStartLine+i-IGF_START_MN], shift)); + } + + FOR (lag = 0; lag <= maxOrder; lag++) + { + n = sub(sub(iEndLine,lag), iStartLine); + + { + Word64 tmp64 = 0; + FOR (i = 0; i < n; i++) + { + tmp64 = W_mac0_16_16(tmp64, tmpbuf[i], tmpbuf[i+lag]); + } + L_tmp = W_sat_l(tmp64); + } + + L_tmp = Mpy_32_16_1(L_tmp, facs[iSubdivisions]); + L_tmp = L_shl(L_tmp, facs_e[iSubdivisions]); + + rxx[lag] = L_add(rxx[lag], L_tmp); + move32(); + } + + } + + IF ( EQ_16(iSubdivisions,nSubdivisions)) /* meaning there is no subdivision with low energy */ + { + /* Limit the maximum order to spectrum length/4 */ + ITF_GetFilterParameters_fx(rxx, s_min (maxOrder, shr(spectrumLength,2)), A, Q_A, predictionGain); + + *curr_order = maxOrder; + } + + return 1; +} /* Helper functions for Hufmann table coding */ diff --git a/lib_dec/core_dec_init.c b/lib_dec/core_dec_init.c index ab37c95d9..ab46aa571 100644 --- a/lib_dec/core_dec_init.c +++ b/lib_dec/core_dec_init.c @@ -845,7 +845,7 @@ void open_decoder_LPD_flt( st->hTonalMDCTConc->lastPitchLag_float = 0; FOR( i = 0; i < FDNS_NPTS; i++ ) { - st->hTonalMDCTConc->scaleFactorsBackground_flt[i] = fix16_to_float( st->hTonalMDCTConc->scaleFactorsBackground[i], 0 ); + st->hTonalMDCTConc->scaleFactorsBackground_flt[i] = fix16_to_float( st->hTonalMDCTConc->scaleFactorsBackground[i], 15 ); } st->hTonalMDCTConc->scf_fadeout_flt = 1.0f; st->hTonalMDCTConc->last_block_nrg_flt = 0.0f; diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c index 46cce6499..46ed2dd33 100644 --- a/lib_dec/dec_tcx.c +++ b/lib_dec/dec_tcx.c @@ -37,6 +37,7 @@ #include #include "prot.h" #include "ivas_prot.h" +#include "prot_fx2.h" #include #include "options.h" #include @@ -1625,6 +1626,105 @@ void decoder_tcx_tns( return; } +#ifdef IVAS_FLOAT_FIXED +void decoder_tcx_tns_fx( + Decoder_State *st, /* i/o: coder memory state */ + const Word16 L_frame_glob, /* i : frame length */ + const Word16 L_spec, + const Word16 L_frame, + const Word16 L_frameTCX, + Word32 x_fx[N_MAX], + const Word16 fUseTns, /* i : flag that is set if TNS data is present */ + STnsData *tnsData, + const Word16 bfi, /* i : Bad frame indicator */ + const Word16 frame_cnt, /* i : frame counter in the super frame */ + const Word16 whitenedDomain ) +{ + Word16 index, isTCX5, L; + TCX_CONFIG_HANDLE hTcxCfg = st->hTcxCfg; + + index = hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + move16(); + + isTCX5 = 0; + move16(); + L = L_frameTCX; + move16(); + + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && NE_16(st->tcxonly, 0) ) + { + IF ( NE_16(frame_cnt, 0) && EQ_16(bfi, 0) && NE_16(st->last_core, ACELP_CORE )) + { + /* fix sub-window overlap */ + hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; + move16(); + } + + IF ( ( NE_16(hTcxCfg->fIsTNSAllowed, 0) && NE_16(fUseTns, 0) && NE_16(bfi, 1) ) || GT_16( L_spec, L_frameTCX ) ) + { + L = L_spec; + move16(); + } + + IF ( ( EQ_16( bfi, 0 ) && ( NE_16( hTcxCfg->tcx_last_overlap_mode, FULL_OVERLAP ) || + ( EQ_16( hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) && EQ_16( frame_cnt, 0 ) && EQ_16( index, 0 ) ) ) ) || + ( NE_16( bfi, 0 ) && ( NE_16( hTcxCfg->tcx_last_overlap_mode, FULL_OVERLAP ) && + NE_16( hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) ) ) + { + isTCX5 = 1; + move16(); + + tcx5SpectrumDeinterleaving_fx( shr(L, 1), x_fx ); + } + } + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + + + IF ( NE_16(hTcxCfg->fIsTNSAllowed, 0) && NE_16(fUseTns, 0) && NE_16(bfi, 1) && EQ_16(tnsData->tnsOnWhitenedSpectra, whitenedDomain) ) + { + /* Apply TNS to get the reconstructed signal */ + SetTnsConfig( hTcxCfg, L_frame_glob == st->L_frame, ( st->last_core == ACELP_CORE ) && ( frame_cnt == 0 ) ); + + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && NE_16(st->tcxonly, 0) && NE_16(isTCX5, 0) ) + { + tcx5TnsGrouping_fx( shr(L, 1), shr(hTcxCfg->tnsConfig[0][0].iFilterBorders[0], 1), x_fx ); + + } + + ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, tnsData, x_fx, 0 ); + + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && NE_16(st->tcxonly, 0) && NE_16(isTCX5, 0) ) + { + IF ( EQ_16(st->element_mode, EVS_MONO) || LT_16(L_spec, L_frameTCX) ) /* todo: this is temporary to maintain EVS BE, this is a bug and should be fixed also for EVS (see issue 13) */ + { + tcx5TnsUngrouping_fx( shr(L_frameTCX, 1), shr(hTcxCfg->tnsConfig[0][0].iFilterBorders[0], 1), x_fx, DEC ); + } + ELSE + { + tcx5TnsUngrouping_fx( shr(L, 1), shr(hTcxCfg->tnsConfig[0][0].iFilterBorders[0], 1), x_fx, DEC ); + } + } + } + IF ( NE_16(whitenedDomain, 0) && NE_16(isTCX5, 0) ) + { + tcx5SpectrumInterleaving_fx( shr(L, 1), x_fx ); + } + + /* restore index */ + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && NE_16(st->tcxonly, 0) && NE_16(frame_cnt, 0) && EQ_16(bfi, 0) && NE_16(st->last_core, ACELP_CORE) ) + { + /* restore sub-window overlap */ + hTcxCfg->tcx_last_overlap_mode = index; + move16(); + } + + return; +} +#endif + /*-------------------------------------------------------------------* * decoder_tcx_imdct() @@ -1785,7 +1885,32 @@ void decoder_tcx_imdct( /* Generate additional comfort noise to mask potential coding artefacts */ if ( st->flag_cna && st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT && !st->cna_dirac_flag ) { +#ifdef IVAS_FLOAT_FIXED + Word32 x_fx[960]; + Word16 x_e; + float maxim = 0; + f2me_buf(x, x_fx, &x_e, L_frame); + FOR(Word16 ind = 0; ind < L_frame; ind++) x_fx[ind] = L_shr(x_fx[ind], 1); + x_e += 1; + maxim = 0; + FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + { + maxim = fmaxf(maxim, fabsf(st->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind])); + } + st->hFdCngDec->hFdCngCom->q_cngNoiseLevel = 31; + IF(L_abs((Word32)maxim)!=0) st->hFdCngDec->hFdCngCom->q_cngNoiseLevel = norm_l((Word32)maxim); + FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + { + st->hFdCngDec->hFdCngCom->cngNoiseLevel[ind] = (Word32)(st->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind] * (1LL<hFdCngDec->hFdCngCom->q_cngNoiseLevel)); + } + st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = float_to_fix16(st->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt, 15); + + generate_masking_noise_mdct( x_fx, &x_e, st->hFdCngDec->hFdCngCom, L_frame ); + + me2f_buf(x_fx, x_e, x, L_frame); +#else generate_masking_noise_mdct_flt( x, st->hFdCngDec->hFdCngCom ); +#endif } if ( st->element_mode == IVAS_CPE_DFT || sba_dirac_stereo_flag ) @@ -1849,6 +1974,420 @@ void decoder_tcx_imdct( return; } +#ifdef IVAS_FLOAT_FIXED +void decoder_tcx_imdct_fx( + Decoder_State *st, /* i/o: coder memory state */ + const int16_t L_frame_glob, /* i : frame length */ + const int16_t L_frameTCX_glob, + const int16_t L_spec, + const int16_t tcx_offset, + const int16_t tcx_offsetFB, + const int16_t L_frame, + const int16_t L_frameTCX, + const int16_t left_rect, + float x[N_MAX], + float xn_buf[], + const uint16_t kernelType, /* i : TCX transform kernel type */ + const int16_t fUseTns, /* i : flag that is set if TNS data is present */ + float synth[], /* i/o: synth[-M..L_frame] */ + float synthFB[], + const int16_t bfi, /* i : Bad frame indicator */ + const int16_t frame_cnt, /* i : frame counter in the super frame */ + const int16_t sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */ +) +{ + int16_t j, L, overlap, curr_order, startLine, endLine, isTCX5; + int16_t overlapFB; + float x_tmp[L_FRAME_PLUS]; + Word32 x_tmp_fx[L_FRAME_PLUS]; + float xn_bufFB[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + Word32 xn_bufFB_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + float acelp_zir[L_FRAME_MAX / 2]; + Word32 x_itf_fx[N_MAX_TCX - IGF_START_MN]; + float x_itf[N_MAX_TCX - IGF_START_MN]; + float A_itf[ITF_MAX_FILTER_ORDER + 1]; + float predictionGain; + int16_t index, proc; + TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec; + TCX_DEC_HANDLE hTcxDec = st->hTcxDec; + TCX_CONFIG_HANDLE hTcxCfg = st->hTcxCfg; + // + + Word16 A_itf_fx[ITF_MAX_FILTER_ORDER + 1], q_a_itf = 15; + Word32 x_fx[1200]; + Word16 x_e, predictionGain_fx = 0; + + /*x_e = 31; + IF(st->igf) FOR(Word16 i = 0; i < 1200; i++) if(abs((Word32) x[i])!=0) { + x_e = min(x_e, norm_l((Word32)x[i])); + } + IF(st->igf) FOR(Word16 i = 0; i < 1200; i++) { + x_fx[i] = (Word32)(x[i] * (1 << x_e)); + } + x_e = 31 - x_e;*/ + f2me_buf(x, x_fx, &x_e, s_min(s_max(s_max(L_frame, L_frameTCX), L_spec), 1200) ); + st->hIGFDec->virtualSpec_e = 31; + IF ( NE_16(st->igf, 0) ) + FOR(Word16 i = 0; i < s_min(st->hIGFDec->infoIGFStopLine - st->hIGFDec->infoIGFStartLine, 856); i++) if(abs((Word32) st->hIGFDec->virtualSpec_float[st->hIGFDec->infoIGFStartLine - IGF_START_MN + i])!=0) { + st->hIGFDec->virtualSpec_e = s_min(st->hIGFDec->virtualSpec_e, norm_l((Word32)st->hIGFDec->virtualSpec_float[st->hIGFDec->infoIGFStartLine - IGF_START_MN + i])); + } + IF ( NE_16(st->igf, 0) ) + FOR(Word16 i = 0; i < s_min(st->hIGFDec->infoIGFStopLine - st->hIGFDec->infoIGFStartLine, 856); i++) { + st->hIGFDec->virtualSpec_fx[st->hIGFDec->infoIGFStartLine - IGF_START_MN + i] = (Word32)(st->hIGFDec->virtualSpec_float[st->hIGFDec->infoIGFStartLine - IGF_START_MN + i] * (1 << st->hIGFDec->virtualSpec_e)); + } + st->hIGFDec->virtualSpec_e = 31 - st->hIGFDec->virtualSpec_e; + IF(st->hIGFDec->virtualSpec_e > x_e) { + FOR(Word16 i = 0; i < s_min(s_max(s_max(L_frame, L_frameTCX), L_spec), 1200); i++) x_fx[i] = L_shr(x_fx[i], st->hIGFDec->virtualSpec_e - x_e); + x_e = st->hIGFDec->virtualSpec_e; + } + // + +#ifdef IVAS_FLOAT_FIXED + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + /* Init lengths */ + overlap = hTcxCfg->tcx_mdct_window_length; + move16(); + overlapFB = hTcxCfg->tcx_mdct_window_lengthFB; + move16(); + + index = hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + move16(); + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && NE_16(st->tcxonly, 0) && NE_16(frame_cnt, 0) && EQ_16(bfi, 0) && NE_16(st->last_core, ACELP_CORE) ) + { + /* fix sub-window overlap */ + hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; + move16(); + } + + IF ( NE_16(st->igf, 0) ) + { + proc = st->hIGFDec->flatteningTrigger; + move16(); + + IF ( proc && fUseTns != 0 ) + { + proc = 0; + move16(); + } + + IF ( proc ) + { + + startLine = st->hIGFDec->infoIGFStartLine; + move16(); + endLine = st->hIGFDec->infoIGFStopLine; + move16(); + curr_order = 0; + move16(); + predictionGain_fx = 0; + move16(); + L = L_frameTCX; + move16(); + isTCX5 = 0; + move16(); + + /* interleave again for ITF */ + IF ( EQ_16( L_frame, shr(st->L_frame, 1) ) && st->tcxonly ) + { + IF ( ( hTcxCfg->fIsTNSAllowed && NE_16(fUseTns, 0) && NE_16(bfi, 1) ) || GT_16( L_spec, L_frameTCX ) ) + { + L = L_spec; + move16(); + } + + IF ( ( EQ_16( bfi, 0 ) && ( NE_16( hTcxCfg->tcx_last_overlap_mode, FULL_OVERLAP ) || + ( EQ_16( hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) && EQ_16( frame_cnt, 0 ) && EQ_16( index, 0 ) ) ) ) || + ( NE_16( bfi, 0 ) && ( NE_16( hTcxCfg->tcx_last_overlap_mode, FULL_OVERLAP ) && + NE_16( hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) ) ) + { + isTCX5 = 1; + move16(); + + tcx5SpectrumInterleaving_fx( shr(L, 1), x_fx ); + } + } + + FOR ( j = startLine; j < endLine; j++ ) + { + IF ( EQ_16(st->hIGFDec->flag_sparse[j - IGF_START_MN], 2) ) + { + x_itf_fx[j - IGF_START_MN] = x_fx[j]; + move32(); + x_fx[j] = L_shr(st->hIGFDec->virtualSpec_fx[j - IGF_START_MN], sub(x_e, st->hIGFDec->virtualSpec_e)); + } + } + + ITF_Detect_ivas_fx( x_fx + IGF_START_MN, startLine, endLine, 8 /*maxOrder*/, A_itf_fx, &q_a_itf, &predictionGain_fx, &curr_order,shl(x_e, 1) ); + + Word16 s = getScaleFactor32(x_fx, s_max(endLine, shr(L, 1))); + s = sub(s, 2); + FOR(j = 0; j < s_max(endLine, shr(L, 1)); j++) + { + x_fx[j] = L_shl(x_fx[j], s); + move32(); + } + x_e = sub(x_e, s); + + ITF_Apply_fx( x_fx, startLine, endLine, A_itf_fx, q_a_itf, curr_order ); + + FOR ( j = startLine; j < endLine; j++ ) + { + IF ( st->hIGFDec->flag_sparse[j - IGF_START_MN] == 2 ) + { + x_fx[j] = L_shl(x_itf_fx[j - IGF_START_MN], s); + } + } + + /* deinterleave */ + IF ( NE_16(isTCX5, 0) ) + { + tcx5SpectrumDeinterleaving_fx( shr(L, 1), x_fx ); + } + } + } + + /*-----------------------------------------------------------* + * Prepare OLA buffer after waveadjustment. * + * Compute inverse MDCT of x[]. * + *-----------------------------------------------------------*/ + + + IF ( EQ_16(st->element_mode, IVAS_CPE_MDCT) ) + { + set32_fx( x_tmp_fx, 0, L_FRAME_PLUS ); + mvl2l( x_fx, x_tmp_fx, s_min( L_FRAME48k, s_max( L_spec, s_max( L_frame, L_frameTCX ) ) ) ); + mvl2l( x_fx, xn_bufFB_fx, s_min( L_FRAME48k, s_max( L_spec, s_max( L_frame, L_frameTCX ) ) ) ); + } + ELSE IF ( EQ_16(st->element_mode, EVS_MONO) ) + { + mvl2l( x_fx, xn_bufFB_fx, s_max( L_spec, s_max( L_frame, L_frameTCX ) ) ); + } + ELSE + { + mvl2l( x_fx, x_tmp_fx, s_max( L_spec, s_max( L_frame, L_frameTCX ) ) ); + mvl2l( x_fx, xn_bufFB_fx, s_max( L_spec, s_max( L_frame, L_frameTCX ) ) ); + } + + IF ( NE_16(st->igf, 0) ) + { + set32_fx( xn_bufFB_fx + st->hIGFDec->infoIGFStartLine, 0, L_frameTCX - st->hIGFDec->infoIGFStartLine ); + } + + + fixedToFloat_arr(A_itf_fx, A_itf, 15, 17); + IF(st->igf && proc) me2f_buf(x_fx, x_e, x, s_max(st->hIGFDec->infoIGFStopLine, s_max(L_frameTCX, L_spec) ) ); + me2f_buf(x_tmp_fx, x_e, x_tmp, L_FRAME_PLUS ); + me2f_buf(xn_bufFB_fx, x_e, xn_bufFB, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); + predictionGain = fix16_to_float(predictionGain_fx, 15); +#else + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + /* Init lengths */ + overlap = hTcxCfg->tcx_mdct_window_length; + overlapFB = hTcxCfg->tcx_mdct_window_lengthFB; + + index = hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ + if ( ( L_frame == st->L_frame >> 1 ) && st->tcxonly && frame_cnt && !bfi && st->last_core != ACELP_CORE ) + { + /* fix sub-window overlap */ + hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode; + } + + if ( st->igf ) + { + proc = st->hIGFDec->flatteningTrigger; + + if ( proc && fUseTns != 0 ) + { + proc = 0; + } + + if ( proc ) + { + startLine = st->hIGFDec->infoIGFStartLine; + endLine = st->hIGFDec->infoIGFStopLine; + curr_order = 0; + predictionGain = 0; + L = L_frameTCX; + isTCX5 = 0; + + /* interleave again for ITF */ + if ( ( L_frame == st->L_frame >> 1 ) && st->tcxonly ) + { + if ( ( hTcxCfg->fIsTNSAllowed && fUseTns != 0 && bfi != 1 ) || ( L_spec > L_frameTCX ) ) + { + L = L_spec; + } + + if ( ( ( !bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) || + ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( index == 0 ) ) ) ) || + ( ( bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) && + !( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) ) ) + { + isTCX5 = 1; + + tcx5SpectrumInterleaving( L >> 1, x ); + } + } + + for ( j = startLine; j < endLine; j++ ) + { + if ( st->hIGFDec->flag_sparse[j - IGF_START_MN] == 2 ) + { + x_itf[j - IGF_START_MN] = x[j]; + x[j] = st->hIGFDec->virtualSpec_float[j - IGF_START_MN]; + } + } + + ITF_Detect( x + IGF_START_MN, startLine, endLine, 8 /*maxOrder*/, A_itf, &predictionGain, &curr_order ); + + ITF_Apply( x, startLine, endLine, A_itf, curr_order ); + + for ( j = startLine; j < endLine; j++ ) + { + if ( st->hIGFDec->flag_sparse[j - IGF_START_MN] == 2 ) + { + x[j] = x_itf[j - IGF_START_MN]; + } + } + + /* deinterleave */ + if ( isTCX5 ) + { + tcx5SpectrumDeinterleaving( L >> 1, x ); + } + } + } + + /*-----------------------------------------------------------* + * Prepare OLA buffer after waveadjustment. * + * Compute inverse MDCT of x[]. * + *-----------------------------------------------------------*/ + + + if ( st->element_mode == IVAS_CPE_MDCT ) + { + set_f( x_tmp, 0.0f, L_FRAME_PLUS ); + mvr2r( x, x_tmp, min( L_FRAME48k, max( L_spec, max( L_frame, L_frameTCX ) ) ) ); + mvr2r( x, xn_bufFB, min( L_FRAME48k, max( L_spec, max( L_frame, L_frameTCX ) ) ) ); + } + else if ( st->element_mode == EVS_MONO ) + { + mvr2r( x, xn_bufFB, max( L_spec, max( L_frame, L_frameTCX ) ) ); + } + else + { + mvr2r( x, x_tmp, max( L_spec, max( L_frame, L_frameTCX ) ) ); + mvr2r( x, xn_bufFB, max( L_spec, max( L_frame, L_frameTCX ) ) ); + } + + if ( st->igf ) + { + set_zero( xn_bufFB + st->hIGFDec->infoIGFStartLine, L_frameTCX - st->hIGFDec->infoIGFStartLine ); + } +#endif + if ( st->element_mode != IVAS_CPE_DFT && !sba_dirac_stereo_flag ) + { + + IMDCT_flt( xn_bufFB, hTcxDec->syn_Overl_float, hTcxDec->syn_Overl_TDAC_float, xn_buf, hTcxCfg->tcx_aldo_window_1_trunc_flt, hTcxCfg->tcx_aldo_window_2_flt, + hTcxCfg->tcx_mdct_window_half_flt, hTcxCfg->tcx_mdct_window_minimum_flt, hTcxCfg->tcx_mdct_window_trans_flt, hTcxCfg->tcx_mdct_window_half_length, hTcxCfg->tcx_mdct_window_min_length, index, + kernelType, left_rect, tcx_offset, overlap, L_frame, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frame_glob, frame_cnt, bfi, st->hHQ_core->old_outLB, 0, st, 0, acelp_zir ); + } + + /* Generate additional comfort noise to mask potential coding artefacts */ + if ( st->flag_cna && st->element_mode != IVAS_CPE_TD && st->element_mode != IVAS_CPE_DFT && !st->cna_dirac_flag ) + { +#ifdef IVAS_FLOAT_FIXED + float maxim = 0; + f2me_buf(x, x_fx, &x_e, L_frame); + maxim = 0; + FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + { + maxim = fmaxf(maxim, fabsf(st->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind])); + } + st->hFdCngDec->hFdCngCom->q_cngNoiseLevel = 31; + IF(L_abs((Word32)maxim)!=0) st->hFdCngDec->hFdCngCom->q_cngNoiseLevel = norm_l((Word32)maxim); + FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + { + st->hFdCngDec->hFdCngCom->cngNoiseLevel[ind] = (Word32)(st->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind] * (1LL<hFdCngDec->hFdCngCom->q_cngNoiseLevel)); + } + st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = float_to_fix16(st->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt, 15); + + generate_masking_noise_mdct( x_fx, &x_e, st->hFdCngDec->hFdCngCom, L_frame ); + + me2f_buf(x_fx, x_e, x, L_frame); +#else + generate_masking_noise_mdct_flt( x, st->hFdCngDec->hFdCngCom ); +#endif + } + + if ( st->element_mode == IVAS_CPE_DFT || sba_dirac_stereo_flag ) + { + mvr2r( x, xn_bufFB, max( L_spec, max( L_frame, L_frameTCX ) ) ); + + + IMDCT_flt( xn_bufFB, hTcxDec->syn_Overl_float, hTcxDec->syn_Overl_TDAC_float, xn_buf, hTcxCfg->tcx_aldo_window_1_trunc_flt, hTcxCfg->tcx_aldo_window_2_flt, hTcxCfg->tcx_mdct_window_half_flt, hTcxCfg->tcx_mdct_window_minimum_flt, hTcxCfg->tcx_mdct_window_trans_flt, hTcxCfg->tcx_mdct_window_half_length, hTcxCfg->tcx_mdct_window_min_length, index, + kernelType, left_rect, tcx_offset, overlap, L_frame, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frame_glob, frame_cnt, bfi, st->hHQ_core->old_outLB, 0, st, 0, acelp_zir ); + } + + if ( st->element_mode != EVS_MONO ) + { + + IMDCT_flt( x_tmp, hTcxDec->syn_OverlFB_float, hTcxDec->syn_Overl_TDACFB_float, xn_bufFB, hTcxCfg->tcx_aldo_window_1_FB_trunc_flt, hTcxCfg->tcx_aldo_window_2_FB_flt, + hTcxCfg->tcx_mdct_window_halfFB_flt, hTcxCfg->tcx_mdct_window_minimumFB_flt, hTcxCfg->tcx_mdct_window_transFB_flt, hTcxCfg->tcx_mdct_window_half_lengthFB, hTcxCfg->tcx_mdct_window_min_lengthFB, index, + kernelType, left_rect, tcx_offsetFB, overlapFB, L_frameTCX, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frameTCX_glob, frame_cnt, bfi, st->hHQ_core->old_out, 1, st, FSCALE_DENOM * L_frameTCX_glob / L_frame_glob, acelp_zir ); + } + else + { + + IMDCT_flt( x, hTcxDec->syn_OverlFB_float, hTcxDec->syn_Overl_TDACFB_float, xn_bufFB, hTcxCfg->tcx_aldo_window_1_FB_trunc_flt, hTcxCfg->tcx_aldo_window_2_FB_flt, hTcxCfg->tcx_mdct_window_halfFB_flt, hTcxCfg->tcx_mdct_window_minimumFB_flt, hTcxCfg->tcx_mdct_window_transFB_flt, hTcxCfg->tcx_mdct_window_half_lengthFB, hTcxCfg->tcx_mdct_window_min_lengthFB, index, + kernelType, left_rect, tcx_offsetFB, overlapFB, L_frameTCX, L_frameTCX, max( L_frameTCX, L_spec ) >> 1, L_frameTCX_glob, frame_cnt, bfi, st->hHQ_core->old_out, 1, st, FSCALE_DENOM * L_frameTCX_glob / L_frame_glob, acelp_zir ); + } + + /* PLC: [TCX: Tonal Concealment] */ + if ( !bfi ) + { + st->second_last_tns_active = st->last_tns_active; + st->last_tns_active = hTcxCfg->fIsTNSAllowed & fUseTns; + hTcxDec->tcxltp_third_last_pitch_float = hTcxDec->tcxltp_second_last_pitch_float; + hTcxDec->tcxltp_second_last_pitch_float = st->old_fpitch_float; + st->old_fpitch_float = hTcxLtpDec->tcxltp_pitch_int + hTcxLtpDec->tcxltp_pitch_fr / (float) st->pit_res_max; + + if ( st->element_mode == IVAS_CPE_MDCT ) + { + st->old_fpitch_float *= (float) L_frame_glob / (float) L_FRAME; + } + + if ( st->element_mode > EVS_MONO ) + { + st->old_fpitchFB_float = st->old_fpitch_float * (float) L_frameTCX_glob / (float) L_frame_glob; + } + else + { + st->old_fpitchFB_float = st->old_fpitch_float * (float) L_frameTCX / (float) L_frame; + } + } + + /* Update old_syn_overl */ + if ( !hTcxCfg->last_aldo ) + { + mvr2r( xn_buf + L_frame, hTcxDec->syn_Overl_float, overlap ); + mvr2r( xn_bufFB + L_frameTCX, hTcxDec->syn_OverlFB_float, overlapFB ); + } + + /* Output */ + mvr2r( xn_buf + ( overlap >> 1 ) - tcx_offset, synth, L_frame_glob ); + mvr2r( xn_bufFB + ( overlapFB >> 1 ) - tcx_offsetFB, synthFB, L_frameTCX_glob ); + + return; +} +#endif /*-------------------------------------------------------------------* * init_tcx_info() diff --git a/lib_dec/igf_dec.c b/lib_dec/igf_dec.c index b82bb2cab..893d6acda 100644 --- a/lib_dec/igf_dec.c +++ b/lib_dec/igf_dec.c @@ -1397,6 +1397,9 @@ void IGFDecSetMode_flt( hIGFDec->flag_sparse = &hIGFDec->flag_sparseBuf[0]; hIGFDec->infoTCXNoise = &hIGFDec->infoTCXNoiseBuf[0]; hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[0]; +#ifdef IVAS_FLOAT_FIXED + hIGFDec->virtualSpec_fx = &hIGFDec->virtualSpec[0]; +#endif hIGFDec->igfData.pSpecFlat_float = &hIGFDec->igfData.pSpecFlatBuf[0]; hIGFDec->igfData.igfInfo.nfSeed = &hIGFDec->igfData.igfInfo.nfSeedBuf[0]; @@ -1422,6 +1425,9 @@ void IGFDecUpdateInfo_flt( hIGFDec->flag_sparse = &hIGFDec->flag_sparseBuf[0]; hIGFDec->infoTCXNoise = &hIGFDec->infoTCXNoiseBuf[0]; hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[0]; +#ifdef IVAS_FLOAT_FIXED + hIGFDec->virtualSpec_fx = &hIGFDec->virtualSpec[0]; +#endif hIGFDec->igfData.pSpecFlat_float = &hIGFDec->igfData.pSpecFlatBuf[0]; hIGFDec->igfData.igfInfo.nfSeed = &hIGFDec->igfData.igfInfo.nfSeedBuf[0]; @@ -1554,6 +1560,9 @@ void IGFDecRestoreTCX10SubFrameData_flt( hIGFDec->flag_sparse = &hIGFDec->flag_sparseBuf[subFrameIdx * ( N_MAX_TCX - IGF_START_MN ) / 2]; hIGFDec->infoTCXNoise = &hIGFDec->infoTCXNoiseBuf[subFrameIdx * ( IGF_START_MX ) / 2]; hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[subFrameIdx * ( N_MAX_TCX - IGF_START_MN ) / 2]; +#ifdef IVAS_FLOAT_FIXED + hIGFDec->virtualSpec_fx = &hIGFDec->virtualSpec[0]; +#endif hIGFDec->igfData.pSpecFlat_float = &hIGFDec->igfData.pSpecFlatBuf[subFrameIdx * IGF_START_MX / 2]; hIGFDec->igfData.igfInfo.nfSeed = &hIGFDec->igfData.igfInfo.nfSeedBuf[subFrameIdx]; @@ -1579,6 +1588,9 @@ void init_igf_dec_flt( hIGFDec->flag_sparse = &hIGFDec->flag_sparseBuf[0]; hIGFDec->infoTCXNoise = &hIGFDec->infoTCXNoiseBuf[0]; hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[0]; +#ifdef IVAS_FLOAT_FIXED + hIGFDec->virtualSpec_fx = &hIGFDec->virtualSpec[0]; +#endif return; } diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 8f20e69fa..31b245c6d 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2069,10 +2069,13 @@ ivas_error ivas_init_decoder( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); } #ifdef IVAS_FLOAT_FIXED + set_zero(st_ivas->p_output_f[n], 48000 / FRAMES_PER_SEC); IF ( ( st_ivas->p_output_fx[n] = (Word32 *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); } + set32_fx(st_ivas->p_output_fx[n], 0, 48000 / FRAMES_PER_SEC); + #endif } diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 0bf43f369..4eaf61668 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -1290,7 +1290,6 @@ void ivas_mdct_core_invQ( return; } - /*-----------------------------------------------------------------* * ivas_mdct_core_reconstruct() * @@ -1364,9 +1363,17 @@ void ivas_mdct_core_reconstruct( if ( !skip_decoding ) { +#ifdef IVAS_FLOAT_FIXED + + decoder_tcx_imdct_fx( st, L_frame_global[ch], L_frame_globalTCX[ch], L_spec[ch], tcx_offset[ch], tcx_offsetFB[ch], L_frame[ch], L_frameTCX[ch], left_rect[ch], &x[ch][k][0], xn_buf, + ( ( hCPE->nchan_out == 1 && st->hTcxDec->kernel_type[k] == MDST_IV ) || st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ? MDCT_IV : st->hTcxDec->kernel_type[k], + fUseTns[ch][k], &synth[k * L_frame[ch]], &synthFB[k * L_frameTCX[ch]], bfi, k, 0 ); + +#else decoder_tcx_imdct( st, L_frame_global[ch], L_frame_globalTCX[ch], L_spec[ch], tcx_offset[ch], tcx_offsetFB[ch], L_frame[ch], L_frameTCX[ch], left_rect[ch], &x[ch][k][0], xn_buf, ( ( hCPE->nchan_out == 1 && st->hTcxDec->kernel_type[k] == MDST_IV ) || st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ? MDCT_IV : st->hTcxDec->kernel_type[k], fUseTns[ch][k], &synth[k * L_frame[ch]], &synthFB[k * L_frameTCX[ch]], bfi, k, 0 ); +#endif } else { @@ -1563,10 +1570,26 @@ void ivas_mdct_core_tns_ns( Word32 x_fx[N_MAX]; Word16 x_e, scf_fx[FDNS_NPTS], scf_e[FDNS_NPTS]; f2me_buf( x[ch][k], x_fx, &x_e, L_frameTCX[ch] ); - for ( int j = 0; j < st->hTonalMDCTConc->nScaleFactors; j++ ) + /*for ( int j = 0; j < st->hTonalMDCTConc->nScaleFactors; j++ ) { f2me_16( sns_int_scf[j], &scf_fx[j], &scf_e[j] ); + }*/ + Word16 q_shift; + FOR(Word16 ind = 0; ind < st->hTonalMDCTConc->nScaleFactors; ind++) { + q_shift = norm_l(sns_int_scf_fx[ind]); + scf_fx[ind] = extract_h(L_shl(sns_int_scf_fx[ind], q_shift)); + scf_e[ind] = 15 - q_shift; + } + /*float maxim = 0; + FOR(Word16 ind = 0; ind < L_frameTCX[ch]; ind++) { + maxim = fmaxf(maxim, fabsf(x[ch][k][ind])); } + if (maxim >= 1) q_x = norm_l((Word32)maxim); + FOR(Word16 ind = 0; ind < L_frameTCX[ch]; ind++) { + x_fx[ind] = (Word32)(x[ch][k][ind] * (1 << q_x)); + } + x_e = 31 - q_x;*/ + TonalMDCTConceal_SaveFreqSignal_ivas_fx( st->hTonalMDCTConc, x_fx, x_e, L_frameTCX[ch], L_frame[ch], &scf_fx[0], scf_e, 0, get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); st->hTonalMDCTConc->last_block_nrg_flt = me2f( st->hTonalMDCTConc->last_block_nrg, st->hTonalMDCTConc->last_block_nrg_exp ); #else @@ -1605,7 +1628,18 @@ void ivas_mdct_core_tns_ns( } } +#ifdef IVAS_FLOAT_FIXED + Word32 x_fx_[1200]; + Word16 q = 26; + float maximum = 0; + FOR(Word16 ind = 0; ind < st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]; ind++) maximum = fmaxf(maximum, fabsf(x[ch][k][ind])); + if(maximum>=1.f) q = norm_l((Word32)maximum) - 5; + FOR(Word16 ind = 0; ind < s_max(s_max(L_frameTCX[ch], L_spec[ch]), st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]); ind++) x_fx_[ind] = (Word32)(x[ch][k][ind] * (1 << q)); + decoder_tcx_tns_fx( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x_fx_, fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); + FOR(Word16 ind = 0; ind < s_max(s_max(L_frameTCX[ch], L_spec[ch]), st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0]); ind++) x[ch][k][ind] = (float)(x_fx_[ind]) / (float)(1 << q); +#else decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); +#endif #ifdef IVAS_FLOAT_FIXED Word32 x_fx[L_FRAME48k], sns_int_scf_fx[FDNS_NPTS]; @@ -1613,12 +1647,12 @@ void ivas_mdct_core_tns_ns( FOR( Word16 c = 0; c < L_FRAME16k; c++ ) { if ( abs( (Word32) x[ch][k][c] ) != 0 ) - q_x = s_min( q_x, norm_l( x[ch][k][c] ) ); + q_x = s_min( q_x, norm_l( (Word32)x[ch][k][c] ) ); } FOR( Word16 c = 0; c < FDNS_NPTS; c++ ) { if ( abs( (Word32) sns_int_scf[c] ) != 0 ) - q_sns_int_scf = s_min( q_sns_int_scf, norm_l( sns_int_scf[c] ) ); + q_sns_int_scf = s_min( q_sns_int_scf, norm_l( (Word32)sns_int_scf[c] ) ); } q_x -= 1; q_sns_int_scf -= 1; @@ -1707,3 +1741,145 @@ void ivas_mdct_core_tns_ns( return; } +#ifdef IVAS_FLOAT_FIXED +/* Has a missing dependency: TonalMDCTConceal_Apply. Currently not used anywhere and untested.*/ +void ivas_mdct_core_tns_ns_fx( + CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ + Word16 fUseTns[CPE_CHANNELS][NB_DIV], /* i : two entries for each channel in TCX10 */ + STnsData tnsData[CPE_CHANNELS][NB_DIV], /* o : TNS parameter */ + Word32 *x_fx[CPE_CHANNELS][NB_DIV], /* o : synthesis @internal_FS */ + Word32 Aq_fx[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )], /* o : LP coefficients */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + Word16 x_e[CPE_CHANNELS][NB_DIV] +) +{ + Word16 ch, k, bfi; + Decoder_State **sts, *st; + /* Framing */ + Word16 L_frame[CPE_CHANNELS], L_frameTCX[CPE_CHANNELS], nSubframes[CPE_CHANNELS]; + Word16 L_frame_global[CPE_CHANNELS], L_frameTCX_glob[CPE_CHANNELS]; + + /* TCX */ + Word32 xn_buf_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + Word16 tcx_offset[CPE_CHANNELS]; + Word16 tcx_offsetFB[CPE_CHANNELS]; + Word16 left_rect[CPE_CHANNELS]; + Word16 L_spec[CPE_CHANNELS]; + Word32 sns_int_scf_fx[FDNS_NPTS]; + Word16 exp; + + /* Initializations */ + sts = hCPE->hCoreCoder; + bfi = sts[0]->bfi; + move16(); + + set32_fx( xn_buf_fx, 0, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); + + + /* TNS, ITF, IMDCT and updates */ + FOR ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + nSubframes[ch] = EQ_16( st->core, TCX_20_CORE ) ? 1 : NB_DIV; + move16(); + + L_frame_global[ch] = BASOP_Util_Divide3216_Scale( st->L_frame, nSubframes[ch], &exp); + L_frame_global[ch] = shl( L_frame_global[ch], exp + 1 ); + + L_frameTCX_glob[ch] = BASOP_Util_Divide3216_Scale(st->hTcxDec->L_frameTCX, nSubframes[ch], &exp); + L_frameTCX_glob[ch] = shl(L_frameTCX_glob[ch], exp + 1); + + L_spec[ch] = BASOP_Util_Divide3216_Scale(st->hTcxCfg->tcx_coded_lines, nSubframes[ch], &exp); + L_spec[ch] = shl(L_spec[ch], exp + 1); + + IF ( ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) || ( NE_16(st->bfi, 0) && EQ_16(st->core, ACELP_CORE) ) ) /* indicates LFE with no content, or odd number of channels */ + { + IF ( st->hTonalMDCTConc != NULL ) + { + TonalMDCTConceal_UpdateState( st->hTonalMDCTConc, st->hTcxDec->L_frameTCX, 0, bfi, 0 ); + } + + /* nothing to do for missing LFE */ + continue; + } + + FOR ( k = 0; k < nSubframes[ch]; k++ ) + { + init_tcx_info_fx( st, L_frame_global[ch], L_frameTCX_glob[ch], k, bfi, &tcx_offset[ch], + &tcx_offsetFB[ch], &L_frame[ch], &L_frameTCX[ch], &left_rect[ch], &L_spec[ch] ); + + IF ( EQ_16(bfi, 0) ) + { + + sns_interpolate_scalefactors_fx( sns_int_scf_fx, &Aq_fx[ch][k * M], DEC ); + + IF ( NE_16(MCT_flag, 0) && st->hTonalMDCTConc != NULL && EQ_16( add( k, 1 ), nSubframes[ch] ) ) + { + Word16 scf_fx[FDNS_NPTS], scf_e[FDNS_NPTS]; + Word16 q_shift; + FOR(Word16 ind = 0; ind < st->hTonalMDCTConc->nScaleFactors; ind++) { + q_shift = norm_l(sns_int_scf_fx[ind]); + scf_fx[ind] = extract_h(L_shl(sns_int_scf_fx[ind], q_shift)); + scf_e[ind] = 15 - q_shift; + } + TonalMDCTConceal_SaveFreqSignal_ivas_fx( st->hTonalMDCTConc, x_fx[ch][k], x_e[ch][k], L_frameTCX[ch], L_frame[ch], &scf_fx[0], scf_e, 0, get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); + } + } + ELSE + { + IF ( st->hTonalMDCTConc != NULL ) + { + IF ( EQ_16(MCT_flag, 0) && LT_16(st->hTcxDec->cummulative_damping_tcx, 32440) ) + //if ( !MCT_flag && st->hTcxDec->cummulative_damping_tcx_float != 1.f ) + { + Word16 *scf_last_m, *scf_bg, *scf_last_e; + Word16 fade_in, fade_out; + + scf_last_m = &st->hTonalMDCTConc->lastBlockData.scaleFactors[0]; + scf_last_e = &st->hTonalMDCTConc->lastBlockData.scaleFactors_exp[0]; + scf_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0]; + + st->hTonalMDCTConc->scf_fadeout = mult(st->hTonalMDCTConc->scf_fadeout, 31130); // 0.95 in Q15 = 31130 + + fade_out = st->hTonalMDCTConc->scf_fadeout; + fade_in = 32767 - fade_out; + + FOR ( Word16 i = 0; i < st->hTonalMDCTConc->nScaleFactors; i++ ) + { + sns_int_scf_fx[i] = L_add(Mpy_32_16_1(L_shl(scf_last_m[i], 1 + scf_last_e[i]), fade_out), Mpy_32_16_1( L_shl(scf_bg[i], 1), fade_in)); + } + } + ELSE + { + st->hTonalMDCTConc->scf_fadeout = 32767; + FOR(Word16 i = 0; i < st->hTonalMDCTConc->nScaleFactors; i++) + { + sns_int_scf_fx[i] = L_shl(st->hTonalMDCTConc->lastBlockData.scaleFactors[i], 1 + st->hTonalMDCTConc->lastBlockData.scaleFactors_exp[i]); + } + } + } + } + Word16 q_x = 15 - x_e[ch][k]; + decoder_tcx_tns_fx( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], x_fx[ch][k], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); + sns_shape_spectrum_fx( x_fx[ch][k], &q_x, st->hTcxCfg->psychParamsCurrent, sns_int_scf_fx, 16, st->hTcxCfg->psychParamsCurrent->nBins ); + x_e[ch][k] = 15 - q_x; + v_multc_fixed( x_fx[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, sns_int_scf_fx[FDNS_NPTS - 1], x_fx[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, L_spec[ch] - st->hTcxCfg->psychParamsCurrent->nBins ); + + decoder_tcx_tns_fx( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x_fx[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 0 ); + } + + IF ( NE_16(bfi, 0) && NE_16(st->tonal_mdct_plc_active, 0) ) + { + TonalMDCTConceal_Apply( st->hTonalMDCTConc, x_fx[ch][0], &x_e[ch][0] ); + } + + IF ( ( bfi || MCT_flag ) && st->hTonalMDCTConc != NULL ) + { + TonalMDCTConceal_UpdateState( st->hTonalMDCTConc, L_frameTCX[ch], ( st->hTcxDec->tcxltp_last_gain_unmodified > 0 ) ? st->old_fpitch : 0, bfi, bfi && st->tonal_mdct_plc_active ); + } + } + + return; + +} +#endif diff --git a/lib_dec/ivas_stereo_mdct_core_dec.c b/lib_dec/ivas_stereo_mdct_core_dec.c index 38b5cc02b..bf0ac1cb4 100644 --- a/lib_dec/ivas_stereo_mdct_core_dec.c +++ b/lib_dec/ivas_stereo_mdct_core_dec.c @@ -227,6 +227,11 @@ void stereo_mdct_core_dec( int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV]; float signal_outFB_tmp[CPE_CHANNELS][L_FRAME_PLUS]; float signal_out_tmp[CPE_CHANNELS][L_FRAME_PLUS]; +#ifdef IVAS_FLOAT_FIXED + Word32 signal_out_tmp_fx[CPE_CHANNELS][L_FRAME_PLUS]; + Word32 *x_fx[CPE_CHANNELS][NB_DIV]; +#endif + push_wmops( "stereo_mdct_core_dec" ); /*--------------------------------------------------------------------------------* @@ -248,6 +253,11 @@ void stereo_mdct_core_dec( set_zero( signal_out_tmp[ch], L_FRAME_PLUS ); x[ch][0] = &signal_out_tmp[ch][0]; x[ch][1] = &signal_out_tmp[ch][0] + L_FRAME_PLUS / 2; +#ifdef IVAS_FLOAT_FIXED + set32_fx( signal_out_tmp_fx[ch], 0, L_FRAME_PLUS ); + x_fx[ch][0] = &signal_out_tmp_fx[ch][0]; + x_fx[ch][1] = &signal_out_tmp_fx[ch][0] + L_FRAME_PLUS / 2; +#endif set_zero( x_0_buf[ch], N_MAX ); x_0[ch][0] = &x_0_buf[ch][0]; @@ -385,14 +395,14 @@ void stereo_mdct_core_dec( if ( st->hTonalMDCTConc != NULL && ( ( k + 1 ) == nSubframes[ch] ) ) { #ifdef IVAS_FLOAT_FIXED - Word32 x_fx[N_MAX]; + Word32 x_fx_[N_MAX]; Word16 x_e, scf_fx[FDNS_NPTS], scf_e[FDNS_NPTS]; - f2me_buf( x[ch][k], x_fx, &x_e, L_frameTCX[ch] ); + f2me_buf( x[ch][k], x_fx_, &x_e, L_frameTCX[ch] ); for ( int j = 0; j < st->hTonalMDCTConc->nScaleFactors; j++ ) { f2me_16( sns_int_scf[j], &scf_fx[j], &scf_e[j] ); } - TonalMDCTConceal_SaveFreqSignal_ivas_fx( st->hTonalMDCTConc, x_fx, x_e, L_frameTCX[ch], L_frame[ch], &scf_fx[0], scf_e, 0, get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); + TonalMDCTConceal_SaveFreqSignal_ivas_fx( st->hTonalMDCTConc, x_fx_, x_e, L_frameTCX[ch], L_frame[ch], &scf_fx[0], scf_e, 0, get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) ); st->hTonalMDCTConc->last_block_nrg_flt = me2f( st->hTonalMDCTConc->last_block_nrg, st->hTonalMDCTConc->last_block_nrg_exp ); #else TonalMDCTConceal_SaveFreqSignal_ivas( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], get_igf_startline_flt( st, L_frame[ch], L_frameTCX[ch] ) ); @@ -412,7 +422,36 @@ void stereo_mdct_core_dec( stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], x[0], x[1], &hCPE->hStereoMdct->mdct_stereo_mode[0], sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], L_frameTCX[1], 0, sts[0]->last_core, sts[1]->last_core, 0 ); } +#ifdef IVAS_FLOAT_FIXED1 + Word32 Aq_fx[2][102]; + Word16 x_e[2][2]; + FOR(Word16 ind = 0; ind < 2; ind++) { + FOR(Word16 ind2 = 0; ind2 < 102; ind2++) { + Aq_fx[ind][ind2] = (Word32)(Aq[ind][ind2] * (ONE_IN_Q16)); + } + FOR(Word16 ind2 = 0; ind2 < 2; ind2++) { + f2me_buf( x[ind][ind2], x_fx[ind][ind2], &x_e[ind][ind2], L_frameTCX[ind] ); + } + } + st->hTcxDec->cummulative_damping_tcx = (Word16)(st->hTcxDec->cummulative_damping_tcx * (ONE_IN_Q15)); + FOR(Word16 ind = 0; ind < st->hTonalMDCTConc->nScaleFactors; ind++) { + f2me_16( st->hTonalMDCTConc->lastBlockData.scaleFactors_float[ind], &st->hTonalMDCTConc->lastBlockData.scaleFactors[ind], &st->hTonalMDCTConc->lastBlockData.scaleFactors_exp[ind] ); + } + FOR(Word16 ind = 0; ind < st->hTonalMDCTConc->nScaleFactors; ind++) { + f2me_16( st->hTonalMDCTConc->lastBlockData.scaleFactors_float[ind], &st->hTonalMDCTConc->lastBlockData.scaleFactors[ind], &st->hTonalMDCTConc->lastBlockData.scaleFactors_exp[ind] ); + } + FOR( Word16 i = 0; i < st->hTonalMDCTConc->nScaleFactors; i++ ) + { + st->hTonalMDCTConc->scaleFactorsBackground[i] = float_to_fix16( st->hTonalMDCTConc->scaleFactorsBackground_flt[i], 15 ); + } + st->hTonalMDCTConc->scf_fadeout = float_to_fix16(st->hTonalMDCTConc->scf_fadeout_flt, 15); + st->old_fpitch = float_to_fix(st->old_fpitch_float, 16); + st->hTcxDec->tcxltp_last_gain_unmodified = float_to_fix16(st->hTcxDec->tcxltp_last_gain_unmodified_float, 15); + + ivas_mdct_core_tns_ns_fx( hCPE, fUseTns, tnsData, x_fx, Aq_fx, 0 , x_e); +#else ivas_mdct_core_tns_ns( hCPE, fUseTns, tnsData, x, Aq, 0 ); +#endif if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO ) ) { -- GitLab