From 29d13627981dd0020d7d189df6b9b81049472e57 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 3 Jan 2024 11:38:46 +0530 Subject: [PATCH] dec_tcx and fd_cng changes [x] BASOP updates to dec_tcx files. [x] dec_tcx and fd_cng related functions converted to fixed point. --- lib_com/codec_tcx_common.c | 178 ++++++++ lib_com/ivas_prot_fx.h | 41 ++ lib_com/parameter_bitmaping.c | 50 +++ lib_com/prot_fx2.h | 74 +++ lib_com/tcx_utils_fx.c | 150 +++++++ lib_com/tns_base.c | 9 +- lib_com/tools_fx.c | 32 ++ lib_dec/dec_LPD.c | 9 + lib_dec/dec_tcx_fx.c | 825 ++++++++++++++++++++++++++++++++++ lib_dec/fd_cng_dec.c | 18 + lib_dec/igf_dec_fx.c | 134 ++++++ lib_dec/ivas_tcx_core_dec.c | 46 ++ lib_dec/stat_dec.h | 2 + lib_dec/tns_base_dec_fx.c | 52 +++ 14 files changed, 1615 insertions(+), 5 deletions(-) diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c index 82f246506..7304b1545 100644 --- a/lib_com/codec_tcx_common.c +++ b/lib_com/codec_tcx_common.c @@ -4,7 +4,9 @@ #include #include +#include #include "options.h" +#include "prot.h" #include "prot_fx2.h" #include "prot_fx1.h" #include "basop_util.h" @@ -215,6 +217,182 @@ void tcxFormantEnhancement( } +void tcxFormantEnhancement_with_shift( + Word16 xn_buf[], + Word16 *xn_buf_e_out, + const Word16 gainlpc[], + const Word16 gainlpc_e[], + Word32 spectrum[], + Word16 *spectrum_e, + const Word16 L_frame, + const Word16 L_frameTCX ) +{ + Word16 i, j, k, l, n; + Word16 fac, fac0, fac1, fac_e, d, tmp; + Word16 xn_buf_e, xn_one, m, e; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + k = shr( L_frame, 6 ); /* FDNS_NPTS = 64 */ + l = 0; + move16(); + + /* get exponent */ + xn_buf_e = 0; + move16(); + FOR( i = 0; i < FDNS_NPTS; i++ ) + { + xn_buf_e = s_max( xn_buf_e, gainlpc_e[i] ); + } + xn_buf_e = shr( add( xn_buf_e, 1 ), 1 ); /* max exponent after sqrt */ + xn_one = shr( 0x4000, sub( xn_buf_e, 1 ) ); /* 1.0 scaled to xn_buf_e */ + + /* Formant enhancement via square root of the LPC gains */ + e = gainlpc_e[0]; + move16(); + m = Sqrt16( gainlpc[0], &e ); + xn_buf[0] = shl( m, sub( e, xn_buf_e ) ); + move16(); + + e = gainlpc_e[1]; + move16(); + m = Sqrt16( gainlpc[1], &e ); + xn_buf[1] = shl( m, sub( e, xn_buf_e ) ); + move16(); + + fac0 = s_min( xn_buf[0], xn_buf[1] ); + fac_e = xn_buf_e; + move16(); + fac0 = Inv16( fac0, &fac_e ); + + FOR( i = 1; i < FDNS_NPTS - 1; i++ ) + { + e = gainlpc_e[i + 1]; + move16(); + m = Sqrt16( gainlpc[i + 1], &e ); + xn_buf[i + 1] = shl( m, sub( e, xn_buf_e ) ); + move16(); + + test(); + IF( ( LE_16( xn_buf[i - 1], xn_buf[i] ) ) && ( LE_16( xn_buf[i + 1], xn_buf[i] ) ) ) + { + m = s_max( xn_buf[i - 1], xn_buf[i + 1] ); + e = xn_buf_e; + move16(); + m = Inv16( m, &e ); + + fac1 = m; + move16(); + tmp = sub( e, fac_e ); + + IF( GT_16( tmp, 0 ) ) + { + fac0 = shr( fac0, tmp ); + } + IF ( LT_16( tmp, 0 ) ) + { + fac1 = shl( fac1, tmp ); + } + + IF ( GT_16( tmp, 0 ) ) + { + fac_e = e; + move16(); + } + + d = sub( fac1, fac0 ); + n = sub( i, l ); + assert( n <= 64 ); + + xn_buf[l] = xn_one; + move16(); + FOR( j = 1; j < n; j++ ) + { + fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) ); + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + xn_buf[l + j] = s_min( xn_one, shl_o( mult( xn_buf[l + j], fac ), fac_e, &Overflow ) ); +#else + xn_buf[l + j] = s_min( xn_one, shl( mult( xn_buf[l + j], fac ), fac_e ) ); +#endif + move16(); + BASOP_SATURATE_WARNING_ON_EVS; + } + + l = i; + move16(); + + fac0 = m; + move16(); + fac_e = e; + move16(); + } + } + /* i = FDNS_NPTS - 1; Completing changes to gains */ + m = s_min( xn_buf[i - 1], xn_buf[i] ); + e = xn_buf_e; + move16(); + m = Inv16( m, &e ); + + fac1 = m; + move16(); + tmp = sub( e, fac_e ); + + if ( tmp > 0 ) + fac0 = shr( fac0, tmp ); + if ( tmp < 0 ) + fac1 = shl( fac1, tmp ); + + if ( tmp > 0 ) + { + fac_e = e; + move16(); + } + + d = sub( fac1, fac0 ); + n = sub( i, l ); + assert( n <= 64 ); + + xn_buf[l] = xn_one; + move16(); + FOR( j = 1; j < n; j++ ) + { + fac = add( fac0, mult( d, extract_l( L_mult0( j, inv_int[n] ) ) ) ); + BASOP_SATURATE_WARNING_OFF_EVS; + xn_buf[l + j] = s_min( xn_one, shl( mult( xn_buf[l + j], fac ), fac_e ) ); + move16(); + BASOP_SATURATE_WARNING_ON_EVS; + } + + xn_buf[i] = xn_one; + move16(); + + /* Application of changed gains onto decoded MDCT lines */ + FOR( i = 0; i < L_frame; i += k ) + { + FOR( l = 0; l < k; l++ ) + { + *spectrum = Mpy_32_16_1( *spectrum, *xn_buf ); + move32(); + spectrum++; + } + xn_buf++; + } + + tmp = sub( L_frameTCX, L_frame ); + FOR( i = 0; i < tmp; i++ ) + { + spectrum[i] = L_shr( spectrum[i], xn_buf_e ); + move32(); + } + *spectrum_e = add( *spectrum_e, xn_buf_e ); + move16(); + + *xn_buf_e_out = xn_buf_e; + move16(); +} + void tcxInvertWindowGrouping( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word32 xn_buf[], diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index e56e13115..2c1098a16 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -157,4 +157,45 @@ void ECSQ_init_instance_fx( const Word16 config_index, void *ac_handle ); +void decoder_tcx_invQ_fx( + Decoder_State *st, /* i/o: coder memory state */ + Word16 prm[], /* i : parameters */ + Word16 A[], /* i : coefficients NxAz[M+1] */ + Word16 Aind[], /* i : frame-independent coefficients Az[M+1] */ + const Word16 L_spec, + const Word16 L_frame, + const Word16 L_frameTCX, + Word32 x_fx[], + Word16 *x_e, + Word16 gainlpc2[], + Word16 gainlpc2_e[], + Word16 xn_buf[], /* Q14 */ + Word16 *fUseTns, /* o : flag that is set if TNS data is present */ + STnsData *tnsData, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + const Word16 **prm_sqQ1, + Word16 *nf_seed, + const Word16 bfi, /* i : Bad frame indicator */ + const Word16 frame_cnt /* i : frame counter in the super frame */ +); + +void init_tcx_info_fx( + Decoder_State *st, /* i/o: coder memory state */ + const Word16 L_frame_glob, /* i : global frame length */ + const Word16 L_frameTCX_glob, /* i : FB global frame length */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + const Word16 bfi, /* i : bad frame indicator */ + Word16 *tcx_offset, /* o : folding point offset relative to the end of the previous frame */ + Word16 *tcx_offsetFB, /* o : FB folding point offset relative to the end of the previous frame*/ + Word16 *L_frame, /* o : frame length */ + Word16 *L_frameTCX, /* o : TCX frame length */ + Word16 *left_rect, /* o : left part is rectangular */ + Word16 *L_spec /* o : spectrum length */ +); + +void IGFDecReplicateTCX10State_fx( + IGF_DEC_INSTANCE_HANDLE hIGFDec /* i/o: instance handle of IGF Decoder */ +); + #endif \ No newline at end of file diff --git a/lib_com/parameter_bitmaping.c b/lib_com/parameter_bitmaping.c index 720324b1e..718d0966d 100644 --- a/lib_com/parameter_bitmaping.c +++ b/lib_com/parameter_bitmaping.c @@ -178,6 +178,56 @@ void SetParameters( return; } +void SetParameters_fx( + ParamsBitMap const *paramsBitMap, + const Word16 nArrayLength, + void *pParameter, + const Word16 **pStream, + Word16 *pnSize ) +{ + Word16 index; + Word16 iParam, nParams; + Word16 value; + void *pSubStruct; + void *pTmp; + assert( ( paramsBitMap != NULL ) && ( nArrayLength > 0 ) && ( pParameter != NULL ) && ( pStream != NULL ) && ( pnSize != NULL ) ); + nParams = paramsBitMap->nParams; + + FOR( index = 0; index < nArrayLength; index++ ) + { + FOR( iParam = 0; iParam < nParams; iParam++ ) + { + ParamBitMap const *param; + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + + move16(); + param = ¶msBitMap->params[iParam]; + + move16(); + value = 1; + if ( s_or( param->fZeroAllowed != 0, param->EncodeValue != NULL ) ) + { + move16(); + value = 0; + } + value = add( value, *( *pStream )++ ); + +#define WMC_TOOL_SKIP + pSubStruct = param->SetParamValue( pParameter, index, value ); +#undef WMC_TOOL_SKIP + move16(); + *pnSize = add( *pnSize, 1 ); + + IF( s_and( param->pSubParamBitMap != NULL, value > 0 ) ) + { + pTmp = pParameter; + if ( pSubStruct != NULL ) + pTmp = pSubStruct; + SetParameters( param->pSubParamBitMap, value, pTmp, pStream, pnSize ); + } + } + } +} void WriteToBitstream( ParamsBitMap const *paramsBitMap, diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 331e1d6c1..343cf3cd4 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -60,6 +60,17 @@ #define TCX_IMDCT_SCALE 15 #define TCX_IMDCT_HEADROOM 1 +/* conversion functions: */ + +// Float to Word32 +Word32 float_to_fix( float number, Word32 Q ); +// Word32 to Float +float fix_to_float( Word32 number, Word32 Q ); +// Float to Word16 +Word16 float_to_fix16( float number, Word16 Q ); +// Word16 to Float +float fix16_to_float( Word16 number, Word16 Q ); + Word32 Mult_32_16( Word32 a, Word16 b); @@ -3183,6 +3194,16 @@ void tcxFormantEnhancement( const Word16 L_frameTCX ); +void tcxFormantEnhancement_with_shift( + Word16 xn_buf[], + Word16 *xn_buf_e, + const Word16 gainlpc[], + const Word16 gainlpc_e[], + Word32 spectrum[], + Word16 *spectrum_e, + const Word16 L_frame, + const Word16 L_frameTCX ); + void tcxInvertWindowGrouping( TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word32 xn_buf[], @@ -3466,6 +3487,15 @@ void lpc2mdct( const Word16 noInverse ); +void lpc2mdct_2( + Word16 *lpcCoeffs, + const int16_t lpcOrder, + Word16 mdct_gains_fx[], + Word16 mdct_gains_e[], + Word16 mdct_inv_gains_fx[], + Word16 mdct_inv_gains_e[], + const int16_t length ); + void mdct_shaping( Word32 x[], const Word16 lg, @@ -7138,6 +7168,12 @@ Word16 DecodeTnsData(STnsConfig const * pTnsConfig, Word16 * pnSize, STnsData * pTnsData); +Word16 DecodeTnsData_ivas_fx( + STnsConfig const *pTnsConfig, + Word16 const *stream, + Word16 *pnSize, + STnsData *pTnsData ); + //parametr_bitmapping.c using ivas void GetParameters( ParamsBitMap const *paramsBitMap, @@ -7154,6 +7190,13 @@ void SetParameters( const int16_t **pStream, int16_t *pnSize); +void SetParameters_fx( + ParamsBitMap const *paramsBitMap, + const Word16 nArrayLength, + void *pParameter, + const Word16 **pStream, + Word16 *pnSize ); + void WriteToBitstream( ParamsBitMap const *paramsBitMap, const int16_t nParams, @@ -7203,12 +7246,25 @@ void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, const Word16 igfGridIdx /**< in: | IGF grid index */ ); +void IGFDecUpdateInfo_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 */ +); + void IGFDecCopyLPCFlatSpectrum(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ const Word32 *pSpectrumFlat, /**< in: Q31 | LPC flattend spectrum from TCX dec */ const Word16 pSpectrumFlat_exp, /**< in: | exponent of pSpectrumFlat */ const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ ); +void IGFDecCopyLPCFlatSpectrum_fx( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 *pSpectrumFlat, /**< in: Q31 | LPC flattend spectrum from TCX dec */ + const Word16 pSpectrumFlat_exp, /**< in: | exponent of pSpectrumFlat */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ +); + void IGFDecStoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ const Word16 subFrameIdx /**< in: Q0 | index of subframe */ ); @@ -7217,6 +7273,12 @@ void IGFDecRestoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, const Word16 subFrameIdx /**< in: Q0 | index of subframe */ ); +void IGFDecRestoreTCX10SubFrameData_fx( + const IGF_DEC_INSTANCE_HANDLE hIGFDec, /* o : instance handle of IGF Decoder */ + const Word16 subFrameIdx /* i : index of subframe */ +); + + void init_igf_dec( IGF_DEC_INSTANCE_HANDLE hIGFDec /* i/o: IGF decoder handle */ ); @@ -7460,6 +7522,18 @@ void decoder_tcx( Word16 stab_fac /* i : stability of isf */ ); +void decoder_tcx_fx( + Decoder_State *st, + Word16 prm[], + float A[], + Word16 Aind[], + float synth[], + float synthFB[], + const Word16 bfi, + const Word16 frame_cnt, + const Word16 sba_dirac_stereo_flag +); + void decoder_tcx_post(Decoder_State *st_fx, Word16 *synth, Word16 *synthFB, diff --git a/lib_com/tcx_utils_fx.c b/lib_com/tcx_utils_fx.c index 84b00dd9d..b3b192784 100644 --- a/lib_com/tcx_utils_fx.c +++ b/lib_com/tcx_utils_fx.c @@ -10,6 +10,7 @@ #include "rom_com.h" #include "rom_basop_util.h" #include "basop_util.h" +#include "prot.h" #define inv_int InvIntTable @@ -831,6 +832,155 @@ void lpc2mdct( } } } + +void lpc2mdct_2( + Word16 *lpcCoeffs, + const Word16 lpcOrder, + Word16 mdct_gains_fx[], + Word16 mdct_gains_e[], + Word16 mdct_inv_gains_fx[], + Word16 mdct_inv_gains_e[], + const Word16 length ) +{ + Word16 i, sizeN, j, k, step, scale, s, tmp16; + Word16 g, g_e, ig, ig_e; + Word32 tmp32; + Word32 RealData_fx[2 * FDNS_NPTS], ImagData_fx[2 * FDNS_NPTS]; + const PWord16 *ptwiddle; + + assert( length <= FDNS_NPTS ); + sizeN = shl( length, 1 ); + + BASOP_getTables( NULL, &ptwiddle, &step, sizeN ); + + /* ODFT */ + FOR ( i = 0; i < lpcOrder + 1; i++ ) + { + RealData_fx[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); + ImagData_fx[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); + ptwiddle += step; + } + + FOR ( ; i < sizeN; i++ ) + { + RealData_fx[i] = L_deposit_l( 0 ); + ImagData_fx[i] = L_deposit_l( 0 ); + } + + /* half length FFT */ + scale = add( norm_s( lpcCoeffs[0] ), 1 ); + BASOP_cfft_ivas( RealData_fx, ImagData_fx, 1, &scale ); + + /*Get amplitude*/ + j = FDNS_NPTS - 1; + k = 0; + move16(); + + FOR( i = 0; i < FDNS_NPTS / 2; i++ ) + { + s = sub( norm_l( L_max( L_abs( RealData_fx[i] ), L_abs( ImagData_fx[i] ) ) ), 1 ); + + tmp16 = extract_h( L_shl( RealData_fx[i], s ) ); + tmp32 = L_mult( tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( ImagData_fx[i], s ) ); + tmp16 = mac_r( tmp32, tmp16, tmp16 ); + + s = shl( sub( scale, s ), 1 ); + + if ( tmp16 == 0 ) + { + s = -16; + move16(); + } + if ( tmp16 == 0 ) + { + tmp16 = 1; + move16(); + } + + BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); + + if ( mdct_gains_fx != NULL ) + { + mdct_gains_fx[k] = g; + move16(); + } + + if ( mdct_gains_e != NULL ) + { + mdct_gains_e[k] = g_e; + move16(); + } + + if ( mdct_inv_gains_fx != NULL ) + { + mdct_inv_gains_fx[k] = ig; + move16(); + } + + if ( mdct_inv_gains_e != NULL ) + { + mdct_inv_gains_e[k] = ig_e; + move16(); + } + + k = add( k, 1 ); + + + s = sub( norm_l( L_max( L_abs( RealData_fx[j] ), L_abs( ImagData_fx[j] ) ) ), 1 ); + + tmp16 = extract_h( L_shl( RealData_fx[j], s ) ); + tmp32 = L_mult( tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( ImagData_fx[j], s ) ); + tmp16 = mac_r( tmp32, tmp16, tmp16 ); + + s = shl( sub( scale, s ), 1 ); + + if ( tmp16 == 0 ) + { + s = -16; + move16(); + } + if ( tmp16 == 0 ) + { + tmp16 = 1; + move16(); + } + + BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e ); + + if ( mdct_gains_fx != NULL ) + { + mdct_gains_fx[k] = g; + move16(); + } + + if ( mdct_gains_e != NULL ) + { + mdct_gains_e[k] = g_e; + move16(); + } + + if ( mdct_inv_gains_fx != NULL ) + { + mdct_inv_gains_fx[k] = ig; + move16(); + } + + if ( mdct_inv_gains_e != NULL ) + { + mdct_inv_gains_e[k] = ig_e; + move16(); + } + + j = sub( j, 1 ); + k = add( k, 1 ); + } + + return; +} /** * \brief Perform mdct shaping. In the floating point software there are two functions, * mdct_noiseShaping and mdct_preShaping, which are combined here into a single function. diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c index e9acf6af4..225a614b8 100644 --- a/lib_com/tns_base.c +++ b/lib_com/tns_base.c @@ -799,18 +799,17 @@ void ResetTnsData(STnsData * pTnsData) pTnsData->nFilters = 0; -#ifdef ADD_IVAS_TNS pTnsData->tnsOnWhitenedSpectra = 0; -#endif FOR (iFilter = 0; iFilter < (Word16) (sizeof(pTnsData->filter)/sizeof(pTnsData->filter[0])); iFilter++) { STnsFilter * const pTnsFilter = &pTnsData->filter[iFilter]; pTnsFilter->spectrumLength = 0; - pTnsFilter->predictionGain = 128/*1.0f Q7*/; + pTnsFilter->predictionGain = ONE_IN_Q7; pTnsFilter->avgSqrCoef = 0; -#ifdef ADD_IVAS_TNS + /* TODO: remove float _flt dependencies */ + pTnsFilter->predictionGain_flt = 1.0f; + pTnsFilter->avgSqrCoef_flt = 0; pTnsFilter->filterType = TNS_FILTER_OFF; -#endif ClearTnsFilterCoefficients(pTnsFilter); } diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 743a3406c..ad1869f4f 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -56,6 +56,38 @@ const Word16 b_hp400_fx[3] = { 3660, -7320, 3660 }; /* Q12 (/4) */ const Word16 a_hp400_fx[3] = { 16384, 29280, -14160 }; +// conversion functions: +Word32 float_to_fix( float number, Word32 Q ) +{ + assert( Q >= 0 ); + assert( fabs( number ) < pow( 2, 31 - Q ) ); + Word32 ret = (Word32) ( number * ( (UWord32) 1 << Q ) ); + return ret; +} + +float fix_to_float( Word32 number, Word32 Q ) +{ + assert( Q >= 0 ); + float ret = (float) number / ( (UWord32) 1 << Q ); + return ret; +} + +Word16 float_to_fix16( float number, Word16 Q ) +{ + assert( Q >= 0 ); + if ( number == 1.0f && Q == Q15 ) + return MAX16B; + assert( fabs( number ) < pow( 2, 15 - Q ) ); + Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) ); + return ret; +} + +float fix16_to_float( Word16 number, Word16 Q ) +{ + assert( Q >= 0 ); + float ret = (float) number / ( (UWord16) 1 << Q ); + return ret; +} int16_t norm_ul(uint32_t UL_var1) { diff --git a/lib_dec/dec_LPD.c b/lib_dec/dec_LPD.c index a6a5ee626..b17938d98 100644 --- a/lib_dec/dec_LPD.c +++ b/lib_dec/dec_LPD.c @@ -44,6 +44,7 @@ #include "basop_proto_func.h" #include "stat_com.h" #include "wmc_auto.h" +#include "prot_fx2.h" /*-------------------------------------------------------------------* @@ -588,7 +589,11 @@ void decoder_LPD_flt( } /* TCX decoder */ +#ifdef IVAS_FLOAT_FIXED + decoder_tcx_fx( st, prm, Aq, Aind, &synth[0], &synthFB[0], bfi, 0, 0 ); +#else decoder_tcx_flt( st, prm, Aq, Aind, &synth[0], &synthFB[0], bfi, 0, 0 ); +#endif } /*--------------------------------------------------------------------------------* @@ -614,7 +619,11 @@ void decoder_LPD_flt( IGFDecRestoreTCX10SubFrameData_flt( st->hIGFDec, k ); /* TCX decoder */ +#ifdef IVAS_FLOAT_FIXED + decoder_tcx_fx( st, prm, Aq, Aind, &synth[k * L_frame / 2], &synthFB[k * L_frameTCX / 2], bfi, k, 0 ); +#else decoder_tcx_flt( st, prm, Aq, Aind, &synth[k * L_frame / 2], &synthFB[k * L_frameTCX / 2], bfi, k, 0 ); +#endif } } diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index 278317290..f146843d2 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -10,6 +10,10 @@ #include "basop_util.h" #include "stl.h" #include "options.h" +#include "prot.h" +#include "math.h" +#include "ivas_prot.h" +#include "ivas_prot_fx.h" extern const Word16 T_DIV_L_Frame[];/*0Q15 * 2^-7 */ @@ -2383,3 +2387,824 @@ static void IMDCT(Word32 *x, Word16 x_e, } } +void init_tcx_info_fx( + Decoder_State *st, /* i/o: coder memory state */ + const Word16 L_frame_glob, /* i : global frame length */ + const Word16 L_frameTCX_glob, /* i : FB global frame length */ + const Word16 frame_cnt, /* i : frame counter in the super_frame */ + const Word16 bfi, /* i : bad frame indicator */ + Word16 *tcx_offset, /* o : folding point offset relative to the end of the previous frame */ + Word16 *tcx_offsetFB, /* o : FB folding point offset relative to the end of the previous frame*/ + Word16 *L_frame, /* o : frame length */ + Word16 *L_frameTCX, /* o : TCX frame length */ + Word16 *left_rect, /* o : left part is rectangular */ + Word16 *L_spec /* o : spectrum length */ +) +{ + TCX_DEC_HANDLE hTcxDec = st->hTcxDec; + TCX_CONFIG_HANDLE hTcxCfg = st->hTcxCfg; + + /* Init lengths */ + *tcx_offset = hTcxCfg->tcx_offset; + *tcx_offsetFB = hTcxCfg->tcx_offsetFB; + + IF( bfi ) + { + /* PLC: [TCX: Memory update] + * PLC: Init buffers */ + + assert( st->L_frame_past > 0 ); + *L_frame = st->L_frame_past; + move16(); + *L_frameTCX = st->L_frameTCX_past; + move16(); + + *left_rect = hTcxDec->prev_widow_left_rect; + move16(); + + IF( *left_rect ) + { + *tcx_offset = hTcxCfg->lfacNext; + move16(); + *tcx_offsetFB = hTcxCfg->lfacNextFB; + move16(); + *L_spec = add( *L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) ); + } + } + ELSE + { + test(); + IF( frame_cnt == 0 && st->last_core == ACELP_CORE ) + { + IF( !st->prev_bfi ) + { + hTcxCfg->last_aldo = 0; + move16(); + } + + /* if past frame is ACELP */ + *L_frame = add( L_frame_glob, *tcx_offset ); + *L_frameTCX = add( L_frameTCX_glob, *tcx_offsetFB ); + IF( EQ_16( st->last_core, st->last_core_from_bs ) ) + { + /* case: last frame was lost and concealed as CNG */ + /* using the longer transition spec length causes reading of uninitialized data */ + *L_spec = add( *L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) ); + } + + assert( hTcxCfg->lfacNext <= 0 ); + *L_frame = sub( *L_frame, hTcxCfg->lfacNext ); + *L_frameTCX = sub( *L_frameTCX, hTcxCfg->lfacNextFB ); + *tcx_offset = hTcxCfg->lfacNext; + move16(); + *tcx_offsetFB = hTcxCfg->lfacNextFB; + move16(); + + *left_rect = 1; + move16(); + hTcxDec->prev_widow_left_rect = 1; + move16(); + } + ELSE + { + *L_frame = L_frame_glob; + move16(); + *L_frameTCX = L_frameTCX_glob; + move16(); + *left_rect = 0; + move16(); + hTcxDec->prev_widow_left_rect = 0; + move16(); + } + + st->L_frame_past = *L_frame; + move16(); + st->L_frameTCX_past = *L_frameTCX; + move16(); + } + + test(); + IF( st->igf ) + { + if ( EQ_16( *L_frame, shr( st->L_frame, 1 ) ) && ( st->tcxonly ) ) + { + IGFDecUpdateInfo_fx( st->hIGFDec, frame_cnt, IGF_GRID_LB_SHORT ); + } + else + { + IGFDecUpdateInfo_fx( st->hIGFDec, frame_cnt, ( st->last_core == ACELP_CORE || ( *left_rect && st->bfi ) ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM ); + } + } +} + + +void decoder_tcx_fx( + Decoder_State *st, + Word16 prm[], + float A[], + Word16 Aind[], + float synth[], + float synthFB[], + const Word16 bfi, + const Word16 frame_cnt, + const Word16 sba_dirac_stereo_flag ) +{ + float x[N_MAX]; + Word32 x_fx[N_MAX]; + Word16 x_e; + float gainlpc2[FDNS_NPTS]; + Word16 gainlpc2_fx[FDNS_NPTS]; + Word16 gainlpc2_e[FDNS_NPTS]; + float gain_tcx = 0; + Word16 gain_tcx_e = 0, gain_tcx_fx = 0; + Word16 fUseTns, L_frame_glob, L_frameTCX_glob; + STnsData tnsData; + Word16 tcx_offset, tcx_offsetFB, L_frame, L_frameTCX; + Word16 left_rect, L_spec, tmp_concealment_method, nf_seed; + const Word16 *prm_sqQ; + float xn_buf[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + Word16 xn_buf_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* Q14 */ + + set_f( x, 0.0, N_MAX ); + set32_fx( x_fx, 0, N_MAX ); + set_f( gainlpc2, 0.0, FDNS_NPTS ); + set16_fx( gainlpc2_fx, 0, FDNS_NPTS ); + set16_fx( gainlpc2_e, 0, FDNS_NPTS ); + + L_spec = st->hTcxCfg->tcx_coded_lines; + L_frame_glob = st->L_frame; + L_frameTCX_glob = st->hTcxDec->L_frameTCX; + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + L_spec = shr( L_spec, 1 ); + L_frame_glob = shr( L_frame_glob, 1 ); + L_frameTCX_glob = shr( L_frameTCX_glob, 1 ); + } + + tmp_concealment_method = 0; + nf_seed = 0; + fUseTns = 0; /* flag that is set if TNS data is present */ + + set_f( xn_buf, 0, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); + + set16_fx( xn_buf_fx, 0, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); + + init_tcx_info_fx( st, L_frame_glob, L_frameTCX_glob, frame_cnt, bfi, &tcx_offset, &tcx_offsetFB, &L_frame, &L_frameTCX, &left_rect, &L_spec ); + +#ifdef IVAS_FLOAT_FIXED + Word16 A_fx[M + 1], A_q; + + double max_val = 0; + for ( int j = 0; j < M + 1; j++ ) + { + max_val = max( max_val, fabs( A[j] ) ); + } + if ( fabs( max_val ) < 1.0 ) + A_q = Q15; + else + A_q = norm_s( (Word16) max_val ); + + for ( int j = 0; j < M + 1; j++ ) + { + A_fx[j] = float_to_fix16( A[j], A_q ); + } + + /* TODO: Temporary inits. Remove float dependency */ + st->gamma = float_to_fix16( st->gamma_float, Q15 ); + st->preemph_fac = float_to_fix16( st->preemph_fac_float, Q15 ); + st->hTcxDec->cummulative_damping_tcx = float_to_fix16( st->hTcxDec->cummulative_damping_tcx_float, Q15 ); + st->Mode2_lp_gainp = float_to_fix( st->lp_gainp, Q16 ); + st->stab_fac_fx = float_to_fix16( st->stab_fac, Q15 ); + st->hTcxCfg->na_scale = float_to_fix16( st->hTcxCfg->na_scale_flt, Q15 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + st->hTcxLtpDec->tcxltp_gain = float_to_fix16( st->hTcxLtpDec->tcxltp_gain_float, Q15 ); + st->inv_gamma = FL2WORD16_SCALE( 1 / st->gamma_float, 1 ); + st->hTcxCfg->preemph_fac = FL2WORD16( st->hTcxCfg->preemph_fac_flt ); + + if ( (Word16) st->last_gain_syn_deemph_float == 0 ) + st->last_gain_syn_deemph_e = 0; + else + st->last_gain_syn_deemph_e = 15 - norm_s( (Word16) st->last_gain_syn_deemph_float ); + + if ( (Word16) st->last_concealed_gain_syn_deemph_float == 0 ) + st->last_concealed_gain_syn_deemph_e = 0; + else + st->last_concealed_gain_syn_deemph_e = 15 - norm_s( (Word16) st->last_concealed_gain_syn_deemph_float ); + + if ( (Word16) st->hTcxDec->old_gaintcx_bfi_float == 0 ) + st->hTcxDec->old_gaintcx_bfi_e = 0; + else + st->hTcxDec->old_gaintcx_bfi_e = 15 - norm_s( (Word16) st->hTcxDec->old_gaintcx_bfi_float ); + + st->last_gain_syn_deemph = float_to_fix16( st->last_gain_syn_deemph_float, 15 - st->last_gain_syn_deemph_e ); + st->last_concealed_gain_syn_deemph = float_to_fix16( st->last_concealed_gain_syn_deemph_float, 15 - st->last_concealed_gain_syn_deemph_e ); + st->hTcxDec->old_gaintcx_bfi = float_to_fix16( st->hTcxDec->old_gaintcx_bfi_float, 15 - st->hTcxDec->old_gaintcx_bfi_e ); + /* end temp init*/ + + decoder_tcx_invQ_fx( st, prm, A_fx, Aind, L_spec, L_frame, L_frameTCX, x_fx, &x_e, gainlpc2_fx, gainlpc2_e, &xn_buf_fx[0], &fUseTns, &tnsData, &gain_tcx_fx, &gain_tcx_e, &prm_sqQ, &nf_seed, bfi, frame_cnt ); + + /* TODO: remove float dependency */ + st->hTcxDec->stepCompensate_float = + (float) ( st->hTcxDec->stepCompensate * pow( 2, st->hTcxDec->stepCompensate_e - 15 ) ); + st->hTcxDec->gainHelper_float = + (float) ( st->hTcxDec->gainHelper * pow( 2, st->hTcxDec->gainHelper_e - 15 ) ); + st->last_concealed_gain_syn_deemph_float = + (float) ( st->last_concealed_gain_syn_deemph * pow( 2, st->last_concealed_gain_syn_deemph_e - 15 ) ); + st->last_gain_syn_deemph_float = + (float) ( st->last_gain_syn_deemph * pow( 2, st->last_gain_syn_deemph_e - 15 ) ); + st->hTcxDec->old_gaintcx_bfi_float = + (float) ( st->hTcxDec->old_gaintcx_bfi * pow( 2, st->hTcxDec->old_gaintcx_bfi_e - 15 ) ); + st->hTcxDec->cummulative_damping_tcx_float = + fix16_to_float( st->hTcxDec->cummulative_damping_tcx, Q15 ); + st->hTcxDec->damping_float = + fix16_to_float( st->hTcxDec->damping, Q14 ); + st->lp_gainp = fix_to_float( st->Mode2_lp_gainp, Q16 ); + + for ( int j = 0; j < L_frameTCX; j++ ) + { + x[j] = (float) ( x_fx[j] * pow( 2, x_e - 31 ) ); + } + gain_tcx = (float) ( gain_tcx_fx * pow( 2, gain_tcx_e - 15 ) ); + for ( int j = 0; j < FDNS_NPTS; j++ ) + { + gainlpc2[j] = (float) ( gainlpc2_fx[j] * pow( 2, gainlpc2_e[j] - 15 ) ); + } + for ( int i = 0; i < max( max( L_frame, L_spec ), L_frameTCX ); i++ ) + { + xn_buf[i] = fix16_to_float( xn_buf_fx[i], Q14 ); + } + +#if 0 + dbgwrite_txt(x, L_frameTCX, "logs\\dir\\Fixed_code_decoderTcxInvQ_x.txt", NULL); + dbgwrite_txt(xn_buf, max(max(L_frame, L_spec), L_frameTCX), "logs\\dir\\Fixed_code_decoderTcxInvQ_xnBuf.txt", NULL); + dbgwrite_txt(gainlpc2, FDNS_NPTS, "logs\\dir\\Fixed_code_decoderTcxInvQ_gainlpc2.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->stepCompensate_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_stepCompensate.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->gainHelper_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_gainHelper.txt", NULL); + dbgwrite_txt(&(st->last_concealed_gain_syn_deemph_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_lastConcealedGainSynDeemph.txt", NULL); + dbgwrite_txt(&(st->last_gain_syn_deemph_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_lastGainSynDeemph.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->old_gaintcx_bfi_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_oldGaintcxBfi.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->cummulative_damping_tcx_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_cummulativeDampingTcx.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->damping_float), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_dampingFact.txt", NULL); + dbgwrite_txt(&(st->lp_gainp), 1, "logs\\dir\\Fixed_code_decoderTcxInvQ_lpGainp.txt", NULL); +#endif +#else + decoder_tcx_invQ( st, prm, A, Aind, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &xn_buf[0], &fUseTns, &tnsData, &gain_tcx, &prm_sqQ, &nf_seed, bfi, frame_cnt ); +#if 0 + dbgwrite_txt(x, L_frameTCX, "logs\\dir\\Float_code_decoderTcxInvQ_x.txt", NULL); + dbgwrite_txt(xn_buf, max(max(L_frame, L_spec), L_frameTCX), "logs\\dir\\Float_code_decoderTcxInvQ_xnBuf.txt", NULL); + dbgwrite_txt(gainlpc2, FDNS_NPTS, "logs\\dir\\Float_code_decoderTcxInvQ_gainlpc2.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->stepCompensate_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_stepCompensate.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->gainHelper_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_gainHelper.txt", NULL); + dbgwrite_txt(&(st->last_concealed_gain_syn_deemph_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_lastConcealedGainSynDeemph.txt", NULL); + dbgwrite_txt(&(st->last_gain_syn_deemph_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_lastGainSynDeemph.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->old_gaintcx_bfi_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_oldGaintcxBfi.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->cummulative_damping_tcx_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_cummulativeDampingTcx.txt", NULL); + dbgwrite_txt(&(st->hTcxDec->damping_float), 1, "logs\\dir\\Float_code_decoderTcxInvQ_dampingFact.txt", NULL); + dbgwrite_txt(&(st->lp_gainp), 1, "logs\\dir\\Float_code_decoderTcxInvQ_lpGainp.txt", NULL); +#endif +#endif + + decoder_tcx_noisefilling( st, NULL, A, L_frameTCX_glob, L_spec, L_frame, L_frameTCX, &x[0], &gainlpc2[0], &tmp_concealment_method, gain_tcx, prm_sqQ, nf_seed, bfi, 0, frame_cnt ); + + decoder_tcx_noiseshaping_igf( st, L_spec, L_frame, L_frameTCX, left_rect, &x[0], &gainlpc2[0], &tmp_concealment_method, bfi ); + + decoder_tcx_tns( st, L_frame_glob, L_spec, L_frame, L_frameTCX, &x[0], fUseTns, &tnsData, bfi, frame_cnt, 0 ); + + decoder_tcx_imdct( st, L_frame_glob, L_frameTCX_glob, L_spec, tcx_offset, tcx_offsetFB, L_frame, L_frameTCX, left_rect, &x[0], &xn_buf[0], MDCT_IV, + fUseTns, &synth[0], &synthFB[0], bfi, frame_cnt, sba_dirac_stereo_flag ); +} + +/*-------------------------------------------------------------------* + * decoder_tcx_invQ_fx + * + * TCX: inverse quantization + *-------------------------------------------------------------------*/ +void decoder_tcx_invQ_fx( + Decoder_State *st, /* i/o: coder memory state */ + int16_t prm[], /* i : parameters */ + Word16 A[], /* i : coefficients NxAz[M+1] */ + Word16 Aind[], /* i : frame-independent coefficients Az[M+1] */ + const Word16 L_spec, + const Word16 L_frame, + const Word16 L_frameTCX, + Word32 x[], + Word16 *x_e, + Word16 gainlpc2[], + Word16 gainlpc2_e[], + Word16 xn_buf[], /* Q14 */ + Word16 *fUseTns, /* o : flag that is set if TNS data is present */ + STnsData *tnsData, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + const Word16 **prm_sqQ1, + Word16 *nf_seed, + const Word16 bfi, /* i : Bad frame indicator */ + const Word16 frame_cnt /* i : frame counter in the super frame */ +) +{ + Word16 i, index; + Word16 start_zeroing; + Word16 Ap[M + 2]; + + Word16 noiseFillingSize; + Word16 tnsSize; /* number of tns parameters put into prm */ + + Word16 gamma1; /* Q15 */ + Word16 gamma; /* Q15 */ + Word16 mem[M]; + Word16 gainCompensate = 0, gainCompensate_e = 0; + Word16 h1[L_SUBFR + 1]; + Word16 tmp1, tmp2; + Word32 tmp32; + Word16 s; + + Word16 arith_bits, signaling_bits; + Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_sqQ, *prm_target; + TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec; + TCX_DEC_HANDLE hTcxDec = st->hTcxDec; + TCX_CONFIG_HANDLE hTcxCfg = st->hTcxCfg; + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + tnsSize = 0; + prm_target = NULL; /* just to suppress MSVC warnigs */ + + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + /* Init lengths */ + gamma1 = st->gamma; + move16(); + + IF( hTcxDec->enableTcxLpc != 0 ) + { + gamma1 = MAX16B; + move16(); + } + + noiseFillingSize = L_spec; + move16(); + IF( st->igf != 0 ) + { + noiseFillingSize = st->hIGFDec->infoIGFStartLine; + move16(); + } + + prm_ltp = &prm[1 + NOISE_FILL_RANGES]; + move16(); + prm_tns = prm_ltp + LTPSIZE; + move16(); + + gainCompensate = ONE_IN_Q14; + move16(); + gainCompensate_e = 1; + move16(); + + /*-----------------------------------------------------------* + * Read TCX parameters * + *-----------------------------------------------------------*/ + + index = 0; + move16(); + + IF( !bfi ) + { + index = prm[0]; + move16(); + + /* read noise level (fac_ns) */ + st->hTcxDec->noise_filling_index[frame_cnt] = prm[1]; + move16(); + } + + /* read TNS data */ + IF( !bfi && hTcxCfg->fIsTNSAllowed ) + { + *fUseTns = DecodeTnsData_ivas_fx( hTcxCfg->pCurrentTnsConfig, prm_tns, &tnsSize, tnsData ); + move16(); + } + ELSE + { + *fUseTns = 0; + move16(); + } + + prm_hm = prm_tns + tnsSize; + move16(); + prm_sqQ = prm_hm + NPRM_CTX_HM; + move16(); + *prm_sqQ1 = prm_sqQ; + move16(); + + /*-----------------------------------------------------------* + * Spectrum data * + *-----------------------------------------------------------*/ + + IF( !bfi ) + { + /*-----------------------------------------------------------* + * Context HM * + *-----------------------------------------------------------*/ + + IF( hTcxCfg->ctx_hm && ( ( st->last_core_from_bs != ACELP_CORE ) || ( frame_cnt > 0 ) ) ) + { + st->last_ctx_hm_enabled = prm_hm[0]; + move16(); + + FOR( i = 0; i < L_spec; i++ ) + { + /* no context harmonic model, copy MDCT coefficients to x */ + x[i] = L_mult( prm_sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) ); + move32(); + } + *x_e = SPEC_EXP_DEC; + move16(); + } + ELSE /* hTcxCfg->ctx_hm == 0 */ + { + IF( hTcxDec->tcx_lpc_shaped_ari ) /* low rates: envelope based arithmetic coder */ + { + prm_target = prm_sqQ; + move16(); + prm_sqQ = prm_target + 1; + move16(); + + tcx_arith_decode_envelope_fx( st, x, x_e, L_frame, L_spec, Aind, *prm_target, prm_sqQ, st->last_core_from_bs != ACELP_CORE, prm_hm, /* HM parameter area */ hTcxDec->tcx_hm_LtpPitchLag, &arith_bits, &signaling_bits, ( st->bwidth > WB ) ? 1 : 0 ); + + hTcxDec->resQBits[frame_cnt] = *prm_target - arith_bits; + move16(); + + /* Noise filling seed */ + FOR( i = 0; i < noiseFillingSize; ++i ) + { + tmp32 = L_shr( x[i], 31 - *x_e ); + *nf_seed = add( *nf_seed, (Word16) abs( tmp32 ) * i * 2 ); + } + } + ELSE /* TCX-only: context based arithmetic coder */ + { + FOR( i = 0; i < L_spec; i++ ) + { + x[i] = L_mult( prm_sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) ); + move32(); + } + + set32_fx( x + L_spec, 0, sub( L_frameTCX, L_spec ) ); + + *x_e = SPEC_EXP_DEC; + move16(); + } + + } /* else of if hTcxCfg->ctx_hm */ + + start_zeroing = ( st->last_core != st->last_core_from_bs ) ? min( L_spec, L_frame ) : L_spec; + + IF( frame_cnt == 0 && st->last_core == ACELP_CORE && st->last_core_from_bs != ACELP_CORE ) + { + Word16 L_spec_con = L_spec + ( st->hTcxCfg->tcx_coded_lines >> 2 ); + + FOR( i = start_zeroing; i < L_spec_con; i++ ) + { + x[i] = 0; + } + + start_zeroing = L_spec_con; + } + + FOR( i = start_zeroing; i < max( L_frame, L_frameTCX ); i++ ) + { + x[i] = 0; + } + + /*-----------------------------------------------------------* + * adaptive low frequency deemphasis. * + *-----------------------------------------------------------*/ + + IF( st->element_mode != IVAS_CPE_MDCT ) + { + weight_a_fx( A, Ap, gamma1, M ); + lpc2mdct_2( Ap, M, NULL, NULL, gainlpc2, gainlpc2_e, FDNS_NPTS ); + } + + /* initialize LF deemphasis factors in xn_buf */ + IF( !st->tcxonly || ( hTcxCfg->resq && hTcxDec->tcx_lpc_shaped_ari ) ) + { + FOR( i = 0; i < max( L_spec, L_frameTCX ); i++ ) + { + xn_buf[i] = ONE_IN_Q14; + } + } + IF( !st->tcxonly ) + { + AdaptLowFreqDeemph( x, *x_e, hTcxDec->tcx_lpc_shaped_ari, gainlpc2, gainlpc2_e, L_frame, xn_buf /* LF deemphasis factors */ ); + } + } + + hTcxDec->damping = 0; + + IF( bfi == 0 ) + { + /*-----------------------------------------------------------* + * Compute global gain * + *-----------------------------------------------------------*/ + + tmp32 = L_shl( L_mult0( index, 0x797D ), 7 ); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + *gain_tcx_e = add( extract_l( L_shr( tmp32, 25 ) ), 1 ); /* get exponent */ + *gain_tcx = round_fx( BASOP_Util_InvLog2( L_or( tmp32, 0xFE000000 ) ) ); + +#ifdef BASOP_NOGLOB + tmp1 = mult_r( shl_sat( L_spec, 5 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); +#else + tmp1 = mult_r( shl( L_spec, 5 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); +#endif + s = 15 - 5 - 7; + IF( GE_16( L_spec, 1024 ) ) /*reduce precision for avoiding overflow*/ + { + tmp1 = mult_r( shl( L_spec, 4 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); + s = 15 - 4 - 7; + } + tmp1 = ISqrt16( tmp1, &s ); + + *gain_tcx = mult( *gain_tcx, tmp1 ); + *gain_tcx_e = add( *gain_tcx_e, s ); + + hTcxDec->old_gaintcx_bfi = *gain_tcx; + move16(); + hTcxDec->old_gaintcx_bfi_e = *gain_tcx_e; + move16(); + + hTcxDec->cummulative_damping_tcx = MAX16B; + move16(); + } + ELSE /* bfi = 1 */ + { + /* PLC: [TCX: Fade-out] + * derivation of damping factor */ + IF( st->use_partial_copy ) + { + IF( EQ_16( st->rf_frame_type, RF_TCXFD ) ) + { + tmp32 = L_shl( L_mult0( hTcxDec->old_gaintcx_bfi, 0x797D ), 7 ); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + *gain_tcx_e = add( extract_l( L_shr( tmp32, 25 ) ), 1 ); /* get exponent */ + *gain_tcx = round_fx( BASOP_Util_InvLog2( L_or( tmp32, 0xFE000000 ) ) ); + + tmp1 = mult_r( shl( L_spec, 5 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); + s = 15 - 5 - 7; + tmp1 = ISqrt16( tmp1, &s ); + + *gain_tcx = mult( *gain_tcx, tmp1 ); + *gain_tcx_e = add( *gain_tcx_e, s ); + + hTcxDec->old_gaintcx_bfi = *gain_tcx; + move16(); + hTcxDec->old_gaintcx_bfi_e = *gain_tcx_e; + move16(); + } + ELSE + { + *gain_tcx = hTcxDec->old_gaintcx_bfi; + move16(); + *gain_tcx_e = hTcxDec->old_gaintcx_bfi_e; + move16(); + } + + hTcxDec->damping = ONE_IN_Q14; + } + ELSE + { + *gain_tcx = hTcxDec->old_gaintcx_bfi; + move16(); + *gain_tcx_e = hTcxDec->old_gaintcx_bfi_e; + move16(); + + hTcxDec->damping = Damping_fact( st->coder_type, st->nbLostCmpt, st->last_good, + st->stab_fac_fx, + &st->Mode2_lp_gainp, + st->last_core ); + } + + hTcxDec->cummulative_damping_tcx = shl( mult( hTcxDec->cummulative_damping_tcx, hTcxDec->damping ), 1 ); /*shl(Q15*Q14,1)=shl(Q14,1) = Q15*/ + } + + IF( bfi ) + { + IF( hTcxDec->envWeighted ) + { + gamma = st->gamma; + move16(); + } + ELSE + { + gamma = gamma1; + move16(); + } + + /* PLC: [TCX: Fade-out] + * PLC: invert LPC weighting in case of PLC */ + + IF( hTcxDec->enableTcxLpc ) + { + gamma = add( mult_r( hTcxDec->cummulative_damping_tcx, sub( st->gamma, MAX16B ) ), MAX16B ); + } + ELSE + { + gamma = add( mult_r( hTcxDec->cummulative_damping_tcx, sub( gamma1, MAX16B ) ), MAX16B ); + } + + IF( st->element_mode != IVAS_CPE_MDCT ) + { + weight_a_fx( A, Ap, gamma, M ); + lpc2mdct_2( Ap, M, NULL, NULL, gainlpc2, gainlpc2_e, FDNS_NPTS ); + } + } + + IF( st->element_mode != IVAS_CPE_MDCT ) + { + set16_fx( h1, 0, L_SUBFR + 1 ); + set16_fx( mem, 0, M ); + h1[0] = ONE_IN_Q10; + move16(); + E_UTIL_synthesis( 0, Ap, h1, h1, L_SUBFR, mem, 0, M ); /* impulse response of LPC */ + + tmp2 = 0; + move16(); + deemph_fx( h1, st->preemph_fac, L_SUBFR, &tmp2 ); /* tmp2 in Q10 */ + } + + /* impulse response level = gain introduced by synthesis+deemphasis */ + IF( !bfi ) + { + IF( st->element_mode == IVAS_CPE_MDCT ) + { + st->last_gain_syn_deemph = 0; + move16(); + st->last_gain_syn_deemph_e = 0; + move16(); + } + ELSE + { + tmp32 = Dot_productSq16HQ( 0, h1, L_SUBFR, &st->last_gain_syn_deemph_e ) /*Q15, st->last_gain_syn_deemph_e*/; + st->last_gain_syn_deemph_e = add( st->last_gain_syn_deemph_e, 10 /*scaling of h1[0] and E_UTIL_synthesis * 2*/ ); + tmp32 = Sqrt32( tmp32, &st->last_gain_syn_deemph_e ); +#ifdef BASOP_NOGLOB + st->last_gain_syn_deemph = round_fx_o( tmp32, &Overflow ); +#else + last_gain_syn_deemph_fx = round_fx( tmp32 ); +#endif + } + + /*for avoiding compiler warnings*/ + hTcxDec->gainHelper = ONE_IN_Q14; + move16(); + hTcxDec->gainHelper_e = 1; + move16(); + hTcxDec->stepCompensate = 0; + move16(); + hTcxDec->stepCompensate_e = 0; + move16(); + } + /* not instrumenting the additional test() here seems to be common practice */ + ELSE IF( EQ_16( TCX_20_CORE, st->core ) || EQ_16( frame_cnt, 1 ) ) + { + IF( st->element_mode == IVAS_CPE_MDCT ) + { + gainCompensate = ONE_IN_Q14; + move16(); + gainCompensate_e = 1; + move16(); + } + ELSE + { + tmp32 = Dot_productSq16HQ( 0, h1, L_SUBFR, &gainCompensate_e ) /*Q15, gainCompensate_e*/; + gainCompensate_e = add( gainCompensate_e, 10 /*scaling of h1[0] and E_UTIL:synthesis*/ ); + gainCompensate = round_fx( Sqrt32( tmp32, &gainCompensate_e ) ) /*Q15, gainCompensate_e*/; + BASOP_Util_Divide_MantExp( st->last_gain_syn_deemph, + st->last_gain_syn_deemph_e, + gainCompensate, + gainCompensate_e, + &gainCompensate, + &gainCompensate_e ); + } + + tmp1 = T_DIV_L_Frame[L_shl( L_mac( -28000, st->L_frame, 95 ), 1 - 15 )]; /* indexing for lookup table */ + + IF( EQ_16( st->nbLostCmpt, 1 ) ) + { + hTcxDec->stepCompensate_e = BASOP_Util_Add_MantExp( + tmp1, + -7, + negate( mult( gainCompensate, tmp1 ) ), + add( -7, gainCompensate_e ), + &hTcxDec->stepCompensate ); + hTcxDec->gainHelper = ONE_IN_Q14; + move16(); + hTcxDec->gainHelper_e = 1; + move16(); + } + ELSE + { + hTcxDec->stepCompensate_e = BASOP_Util_Add_MantExp( + mult( tmp1, st->last_concealed_gain_syn_deemph ), + add( -7, st->last_concealed_gain_syn_deemph_e ), + negate( mult( tmp1, gainCompensate ) ), + add( -7, gainCompensate_e ), + &hTcxDec->stepCompensate ); + + hTcxDec->gainHelper = st->last_concealed_gain_syn_deemph; + move16(); + hTcxDec->gainHelper_e = st->last_concealed_gain_syn_deemph_e; + move16(); + } + + st->last_concealed_gain_syn_deemph = gainCompensate; + move16(); + st->last_concealed_gain_syn_deemph_e = gainCompensate_e; + move16(); + } + + /*-----------------------------------------------------------* + * Residual inv. Q. * + *-----------------------------------------------------------*/ + + IF( !bfi && hTcxCfg->resq ) + { + IF( hTcxDec->tcx_lpc_shaped_ari ) + { + /* envelope based arithmetic coder */ + const Word16 *prm_resq; + prm_resq = prm_sqQ + *prm_target /* = targetBits */ - hTcxDec->resQBits[frame_cnt]; + + i = tcx_ari_res_invQ_spec( x, *x_e, L_spec, + prm_resq, + hTcxDec->resQBits[frame_cnt], + 0, + hTcxCfg->sq_rounding, + xn_buf /* LF deemphasis factors */ ); + } + ELSE + { + /* context based arithmetic coder */ + i = tcx_res_invQ_gain( gain_tcx, gain_tcx_e, &prm_sqQ[L_spec], hTcxDec->resQBits[frame_cnt] ); + + Word16 *tmpP16 = xn_buf; + if ( st->tcxonly != 0 ) + tmpP16 = NULL; + tcx_res_invQ_spec( x, *x_e, L_spec, &prm_sqQ[L_spec], hTcxDec->resQBits[frame_cnt], i, hTcxCfg->sq_rounding, tmpP16 /* LF deemphasis factors */ ); + } + } + + + IF( !bfi && st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) + { + IF( hTcxLtpDec->tcxltp && GT_16( hTcxLtpDec->tcxltp_gain, 0 ) && !( *fUseTns ) ) + { + PsychAdaptLowFreqDeemph( x, gainlpc2, gainlpc2_e, NULL ); + } + } + + IF( !bfi && !st->tcxonly ) + { + /* Replication of ACELP formant enhancement for low rates */ + IF( st->total_brate < ACELP_13k20 ) + { + IF( st->element_mode == IVAS_CPE_MDCT ) + { + assert( !"Not adapted to warped scale" ); + } + + Word16 xn_buf_e; + tcxFormantEnhancement_with_shift( xn_buf, &xn_buf_e, gainlpc2, gainlpc2_e, x, x_e, L_frame, L_frameTCX ); + for ( i = 0; i < FDNS_NPTS; i++ ) + { + xn_buf[i] = shl( xn_buf[i], xn_buf_e - 1 ); + } + } + } + + /*-----------------------------------------------------------* + * Add gain to the lpc gains * + *-----------------------------------------------------------*/ + + IF( st->VAD == 0 ) + { + *gain_tcx = mult_r( *gain_tcx, hTcxCfg->na_scale ); + } + + IF( st->element_mode != IVAS_CPE_MDCT ) + { + i = norm_s( *gain_tcx ); + *gain_tcx = shl( *gain_tcx, i ); + *gain_tcx_e = sub( *gain_tcx_e, i ); + FOR( i = 0; i < FDNS_NPTS; i++ ) + { + gainlpc2[i] = mult( gainlpc2[i], *gain_tcx ); + move16(); + gainlpc2_e[i] = add( gainlpc2_e[i], *gain_tcx_e ); + } + } + + return; +} diff --git a/lib_dec/fd_cng_dec.c b/lib_dec/fd_cng_dec.c index 5bb24d727..6aa71b694 100644 --- a/lib_dec/fd_cng_dec.c +++ b/lib_dec/fd_cng_dec.c @@ -44,6 +44,7 @@ #include "wmc_auto.h" #include "ivas_prot.h" #include "ivas_rom_dec.h" +#include "prot_fx2.h" /*------------------------------------------------------------------- * Local constants @@ -939,7 +940,24 @@ static void perform_noise_estimation_dec_flt( DEC, element_mode ); /* Expand MS outputs */ +#ifdef IVAS_FLOAT_FIXED + Word16 logNoiseFx[NPART_SHAPING]; + Word32 noiseFx[NPART_SHAPING]; + Word16 q_out; + for (int ii = 0; ii < npart; ii++) + { + logNoiseFx[ii] = (Word16)(msLogNoiseEst[ii] * pow(2, Q9)); + } + expand_range(logNoiseFx, noiseFx, &q_out, npart); + + for (int ii = 0; ii < npart; ii++) + { + /* converting back to float. */ + msNoiseEst[ii] = (float)(noiseFx[ii] * pow(2, q_out - 31)); + } +#else expand_range_flt( msLogNoiseEst, msNoiseEst, npart ); +#endif } return; diff --git a/lib_dec/igf_dec_fx.c b/lib_dec/igf_dec_fx.c index 24502b083..268d35eca 100644 --- a/lib_dec/igf_dec_fx.c +++ b/lib_dec/igf_dec_fx.c @@ -8,6 +8,8 @@ #include #include "options.h" #include "stl.h" +#include "prot.h" +#include "ivas_prot.h" #include "prot_fx1.h" #include "prot_fx2.h" #include "cnst.h" @@ -1675,6 +1677,72 @@ void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, } } +/*-------------------------------------------------------------------* + * IGFDecUpdateInfo_fx() + * + * updates the start/stop frequency of IGF according to igfGridIdx + *-------------------------------------------------------------------*/ + +void IGFDecUpdateInfo_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 */ +) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + hIGFDec->flag_sparse = &hIGFDec->flag_sparseBuf[0]; + hIGFDec->infoTCXNoise = &hIGFDec->infoTCXNoiseBuf[0]; + + hIGFDec->virtualSpec_fx = &hIGFDec->virtualSpec[0]; + hIGFDec->igfData.pSpecFlat_fx = &hIGFDec->igfData.pSpecFlat[0]; + + /* TODO: remove float init */ + hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[0]; + hIGFDec->igfData.pSpecFlat_float = &hIGFDec->igfData.pSpecFlatBuf[0]; + + hIGFDec->igfData.igfInfo.nfSeed = &hIGFDec->igfData.igfInfo.nfSeedBuf[0]; + + IF ( EQ_16( igfGridIdx, IGF_GRID_LB_SHORT ) ) + { + IGFDecRestoreTCX10SubFrameData_fx( hIGFDec, subFrameIdx ); + } + + hPrivateData = &hIGFDec->igfData; + if ( hIGFDec->isIGFActive ) + { + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hIGFDec->infoIGFStartFreq = hGrid->startFrequency; + hIGFDec->infoIGFStopFreq = hGrid->stopFrequency; + hIGFDec->infoIGFStartLine = hGrid->startLine; + hIGFDec->infoIGFStopLine = hGrid->stopLine; + } + + return; +} + +void IGFDecReplicateTCX10State_fx( + IGF_DEC_INSTANCE_HANDLE hIGFDec /* i/o: instance handle of IGF Decoder */ +) +{ + Copy( &hIGFDec->flag_sparseBuf[( N_MAX_TCX - IGF_START_MN ) / 2], &hIGFDec->flag_sparseBuf[0], ( N_MAX_TCX - IGF_START_MN ) / 2 ); + mvc2c( &hIGFDec->infoTCXNoiseBuf[( IGF_START_MX ) / 2], &hIGFDec->infoTCXNoiseBuf[0], ( IGF_START_MX ) / 2 ); + + /* TODO: remove float dependency */ + mvr2r( &hIGFDec->virtualSpecBuf[( N_MAX_TCX - IGF_START_MN ) / 2], &hIGFDec->virtualSpecBuf[0], ( N_MAX_TCX - IGF_START_MN ) / 2 ); + mvr2r( &hIGFDec->igfData.pSpecFlatBuf[IGF_START_MX / 2], &hIGFDec->igfData.pSpecFlatBuf[0], IGF_START_MX / 2 ); + + Copy32( &hIGFDec->virtualSpec[( N_MAX_TCX - IGF_START_MN ) / 2], &hIGFDec->virtualSpec[0], ( N_MAX_TCX - IGF_START_MN ) / 2 ); + Copy32( &hIGFDec->igfData.pSpecFlat[IGF_START_MX / 2], &hIGFDec->igfData.pSpecFlat[0], IGF_START_MX / 2 ); + + hIGFDec->igfData.igfInfo.nfSeedBuf[0] = hIGFDec->igfData.igfInfo.nfSeedBuf[1]; + move16(); + + return; +} + + /**********************************************************************/ /* copy the LPC flat spectrum to IGF buffer **************************************************************************/ @@ -1703,6 +1771,37 @@ void IGFDecCopyLPCFlatSpectrum(const IGF_DEC_INSTANCE_HANDLE hInstance, } +void IGFDecCopyLPCFlatSpectrum_fx( + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 *pSpectrumFlat, /**< in: Q31 | LPC flattend spectrum from TCX dec */ + const Word16 pSpectrumFlat_exp, /**< in: | exponent of pSpectrumFlat */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ +) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + int16_t i; + + IF( hInstance ) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + + /* pSpectrumFlat_exp has to be multiplied with 1024 = 2^10 go achive proper gain values */ + hPrivateData->pSpecFlat_exp = add( pSpectrumFlat_exp, 10 ); + move16(); + + Copy32( pSpectrumFlat, hPrivateData->pSpecFlat, hGrid->startLine ); + + /* TODO: remove float dependency */ + for ( i = hGrid->minSrcSubband - IGF_MID_WHITENING_LEVEL2; i < hGrid->startLine; i++ ) + { + hPrivateData->pSpecFlat_float[i] = fix_to_float( hPrivateData->pSpecFlat[i], 31 - hPrivateData->pSpecFlat_exp ) * 1024.f; + } + } +} + /**********************************************************************/ /* store the IGF bitstream information for TCX10 subframes **************************************************************************/ @@ -1752,6 +1851,41 @@ void IGFDecRestoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, move16(); } + +void IGFDecRestoreTCX10SubFrameData_fx( + const IGF_DEC_INSTANCE_HANDLE hIGFDec, /* i/o: instance handle of IGF Decoder */ + const Word16 subFrameIdx /* i : index of subframe */ +) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hIGFDec->igfData; + + /* store igf energies for subframe*/ + Copy( hPrivateData->igf_curr_subframe[subFrameIdx][0], hPrivateData->igf_curr, IGF_MAX_SFB ); + Copy( hPrivateData->igf_prev_subframe[subFrameIdx], hPrivateData->igf_prev, IGF_MAX_SFB ); + + /* store spectral whitening information for current subframe */ + Copy( hPrivateData->currWhiteningLevel_subframe[subFrameIdx], hPrivateData->currWhiteningLevel, IGF_MAX_TILES ); + Copy( hPrivateData->prevWhiteningLevel_subframe[subFrameIdx], hPrivateData->prevWhiteningLevel, IGF_MAX_TILES ); + + /* restore flattening trigger for current subframe */ + hIGFDec->flatteningTrigger = hPrivateData->igf_flatteningTrigger_subframe[subFrameIdx]; + 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_fx = &hIGFDec->virtualSpec[subFrameIdx * ( N_MAX_TCX - IGF_START_MN ) / 2]; + hIGFDec->igfData.pSpecFlat_fx = &hIGFDec->igfData.pSpecFlat[subFrameIdx * IGF_START_MX / 2]; + + /* TODO: remove float init */ + hIGFDec->virtualSpec_float = &hIGFDec->virtualSpecBuf[subFrameIdx * ( N_MAX_TCX - IGF_START_MN ) / 2]; + hIGFDec->igfData.pSpecFlat_float = &hIGFDec->igfData.pSpecFlatBuf[subFrameIdx * IGF_START_MX / 2]; + + hIGFDec->igfData.igfInfo.nfSeed = &hIGFDec->igfData.igfInfo.nfSeedBuf[subFrameIdx]; + + return; +} + /*-----------------------------------------------------------------------* * init_igf_dec() * diff --git a/lib_dec/ivas_tcx_core_dec.c b/lib_dec/ivas_tcx_core_dec.c index c4205c353..4ef647a7f 100644 --- a/lib_dec/ivas_tcx_core_dec.c +++ b/lib_dec/ivas_tcx_core_dec.c @@ -35,12 +35,14 @@ #include "options.h" #include #include "prot.h" +#include "prot_fx2.h" #include "rom_com.h" #include "stat_dec.h" #include "wmc_auto.h" #include "basop_proto_func.h" #include "stat_com.h" #include "ivas_prot.h" +#include "prot_fx2.h" /*-------------------------------------------------------------* * Local prototypes @@ -475,7 +477,11 @@ void stereo_tcx_core_dec( } /* TCX decoder */ +#ifdef IVAS_FLOAT_FIXED + decoder_tcx_fx( st, prm, Aq, Aind, &synth[0], &synthFB[0], bfi, 0, sba_dirac_stereo_flag ); +#else decoder_tcx_flt( st, prm, Aq, Aind, &synth[0], &synthFB[0], bfi, 0, sba_dirac_stereo_flag ); +#endif } /*--------------------------------------------------------------------------------* @@ -503,7 +509,11 @@ void stereo_tcx_core_dec( } /* TCX decoder */ +#ifdef IVAS_FLOAT_FIXED + decoder_tcx_fx( st, prm, Aq, Aind, &synth[k * st->L_frame / 2], &synthFB[k * hTcxDec->L_frameTCX / 2], bfi, k, sba_dirac_stereo_flag ); +#else decoder_tcx_flt( st, prm, Aq, Aind, &synth[k * st->L_frame / 2], &synthFB[k * hTcxDec->L_frameTCX / 2], bfi, k, sba_dirac_stereo_flag ); +#endif } } @@ -586,7 +596,27 @@ void stereo_tcx_core_dec( if ( !bfi && st->clas_dec >= VOICED_TRANSITION && st->clas_dec < INACTIVE_CLAS ) { /* use latest LPC set */ +#ifdef IVAS_FLOAT_FIXED + Word16 Aq_fx[L_SUBFR]; + Word16 q_fac; + double max_val = 0; + for (int j = 0; j <= M; j++) + { + max_val = max(max_val, fabs(Aq[j])); + } + if (fabs(max_val) < 1.0f) + q_fac = Q15; + else + q_fac = norm_s((Word16)max_val); + for (int j = 0; j <= M; j++) + { + Aq_fx[j] = (Word16)(Aq[j] * pow(2, q_fac)); + } + Word16 old_enr_LP_fx = Enr_1_Az_fx(Aq_fx, L_SUBFR); + st->old_enr_LP_float = (float)(old_enr_LP_fx / pow(2, Q3)); +#else st->old_enr_LP_float = enr_1_Az( Aq, L_SUBFR ); +#endif } /* Update past buffers */ @@ -715,7 +745,23 @@ void stereo_tcx_core_dec( /* Clear memory for secondary channel CNA */ set_f( hStereoCng->olapBufferSynth22, 0.0f, st->hFdCngDec->hFdCngCom->frameSize / 2 ); } +#ifdef IVAS_FLOAT_FIXED + Word16 msPsd_fx[NPART_SHAPING]; + Word32 psd_part_fx[NPART_SHAPING]; + Word16 psd_part_q; + for (int ii = 0; ii < st->hFdCngDec->nFFTpart_shaping; ii++) + { + msPsd_fx[ii] = (Word16)(st->hFdCngDec->msPsd_float[ii] * pow(2, Q9)); + } + expand_range(msPsd_fx, psd_part_fx, &psd_part_q, st->hFdCngDec->nFFTpart_shaping); + for (int ii = 0; ii < st->hFdCngDec->nFFTpart_shaping; ii++) + { + /* converting back to float */ + st->hFdCngDec->msPsd_float[ii] = (float)(psd_part_fx[ii] * pow(2, psd_part_q - 31)); + } +#else expand_range_flt( st->hFdCngDec->msPsd_float, psd_part, st->hFdCngDec->nFFTpart_shaping ); +#endif scalebands_flt( psd_part, st->hFdCngDec->part_shaping, st->hFdCngDec->nFFTpart_shaping, st->hFdCngDec->midband_shaping, st->hFdCngDec->nFFTpart_shaping, st->hFdCngDec->hFdCngCom->stopFFTbin - st->hFdCngDec->hFdCngCom->startBand, psd, 1 ); generate_stereo_masking_noise( signal_out, st, hStereoTD, flag_sec_CNA, 0, hStereoCng, nchan_out ); } diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index ed67d2e3e..934e5727b 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -422,6 +422,7 @@ typedef struct igfdec_private_data_struct /* spectral whitening: */ float *pSpecFlat_float; float pSpecFlatBuf[IGF_START_MX]; + Word32 *pSpecFlat_fx; Word32 pSpecFlat[IGF_START_MX]; /* Q31 | MDCT spectrum before LPC shaping */ Word16 pSpecFlat_exp; @@ -469,6 +470,7 @@ typedef struct igfdec_instance_struct float *virtualSpec_float; float virtualSpecBuf[N_MAX_TCX - IGF_START_MN]; + Word32 *virtualSpec_fx; Word32 virtualSpec[N_MAX_TCX - IGF_START_MN]; /* Q31 | buffer for temp flattening */ Word16 virtualSpec_e; /* | exponent of virtualSpec */ diff --git a/lib_dec/tns_base_dec_fx.c b/lib_dec/tns_base_dec_fx.c index f86ea753a..2839b9b72 100644 --- a/lib_dec/tns_base_dec_fx.c +++ b/lib_dec/tns_base_dec_fx.c @@ -154,3 +154,55 @@ Word16 DecodeTnsData( return result; } +Word16 DecodeTnsData_ivas_fx( + STnsConfig const *pTnsConfig, + Word16 const *stream, + Word16 *pnSize, + STnsData *pTnsData ) +{ + Word16 result; + + ResetTnsData( pTnsData ); + + IF( GT_16( pTnsConfig->nMaxFilters, 1 ) ) + { + + IF( pTnsConfig->allowTnsOnWhite ) + { + IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) ) + { + SetParameters_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, pTnsData, &stream, pnSize ); + } + ELSE + { + SetParameters_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, pTnsData, &stream, pnSize ); + } + } + ELSE + { + IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) ) + { + SetParameters_fx( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize ); + } + ELSE + { + SetParameters_fx( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize ); + } + } + } + ELSE + { + SetParameters_fx( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize ); + } + + move16(); + result = FALSE; + IF( GT_16( pTnsData->nFilters, 0 ) ) + { + move16(); + result = TRUE; + } + + + return result; +} \ No newline at end of file -- GitLab