diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index 04b61751f69cd4a23646ee380127a863447f39a2..8aeb0435cf299e0af585bf7f3bb30c71930745b5 100644
--- a/Workspace_msvc/lib_dec.vcxproj
+++ b/Workspace_msvc/lib_dec.vcxproj
@@ -321,6 +321,7 @@
+
@@ -331,7 +332,9 @@
+
+
diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c
index 538c620cf347ea87d32bb48b8cc8437e0ce9298b..90b3e6a09bc7520dad794ca4adbb4f1989838d8a 100644
--- a/lib_com/basop_util.c
+++ b/lib_com/basop_util.c
@@ -516,6 +516,10 @@ Word32 Sqrt32( /*!< output mantissa */
{
Word16 preShift, e;
+ if (mantissa < 0)
+ {
+ mantissa = mantissa;
+ }
assert(mantissa >= 0);
/* normalize */
@@ -1237,6 +1241,35 @@ Word16 getCosWord16(Word16 theta)
return result;
}
+Word16 getSinWord16(Word16 theta)
+{
+ Word16 sine;
+ Word32 theta_new = L_sub(EVS_PI_BY_2_FX, theta);
+ Word16 l_theta;
+ IF(GT_32(theta_new, EVS_PI_FX))
+ {
+ l_theta = extract_l(L_sub(L_sub(theta_new, EVS_PI_FX), EVS_PI_FX ));
+ }
+ ELSE IF(LT_32(theta_new, -EVS_PI_FX))
+ {
+ l_theta = extract_l(L_add(L_add(theta_new, EVS_PI_FX), EVS_PI_FX));
+ }
+ ELSE
+ {
+ l_theta = extract_l(theta_new);
+ }
+ sine = getCosWord16(l_theta);
+ IF (EQ_16(sine, ONE_IN_Q14))
+ {
+ sine = MAX_16;
+ }
+ ELSE
+ {
+ sine = shl(sine, 1);
+ }
+ return sine;
+}
+
Word16 getCosWord16R2(
Word16 theta )
{
diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h
index f392a888f2623c94a85207ed56c5923a747d35d0..61b170af39e05cf657c5cfc8a228b35d6e2edad3 100644
--- a/lib_com/basop_util.h
+++ b/lib_com/basop_util.h
@@ -456,6 +456,7 @@ Word32 L_mult0_3216(Word32 x, /*!< : Multiplier */
/* Calculate sin/cos. Angle in 2Q13 format, result has exponent = 1 */
Word16 getCosWord16(Word16 theta);
+Word16 getSinWord16(Word16 theta);
Word32 getCosWord32(Word32 theta);
/**
* \brief calculate cosine of angle. Tuned for ISF domain.
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
index 2d831cbc39812c1f16a7861580507c2ddd5c5cc5..1717c8d7d70318912ceb4cc9663a527fcf075901 100644
--- a/lib_com/cnst.h
+++ b/lib_com/cnst.h
@@ -211,6 +211,9 @@ enum{
#define INV_LOG_2 1.442695040888963f /* 1/log(2) */
#define INV_SQRT_2 0.70710676908493f /* 1/sqrt(2) */
#define INV_SQRT_2_Q15 23170 /* 1/sqrt(2) in Q15 */
+#ifdef IVAS_FLOAT_FIXED
+#define INV_SQRT_2_FX (Word16)(0x5A82) /* 1/sqrt(2) */
+#endif
#define MAX_V_MULT_MAT 100 /* maximum array length for the function v_mult_mat() */
@@ -546,6 +549,10 @@ enum
*----------------------------------------------------------------------------------*/
#define FRAMES_PER_SEC 50
+#ifdef IVAS_FLOAT_FIXED
+#define ONE_BY_FRAMES_PER_SEC ((Word32)(0x028F5C29))
+#define FRAMES_PER_SEC_BY_2 (FRAMES_PER_SEC >> 1)
+#endif
#define INV_FRAME_PER_SEC_Q15 656
#define INV_FR_P_S_MX_PRM_SPL_SBFR_Q15 164
#define FRAME_SIZE_NS 20000000L
@@ -1669,6 +1676,10 @@ enum
#define OUTMAX_INV 0.000030517578125f /* 1/2^15 */
#define OUTMAX_INV_FX 65536 /* 1/2^15 (Q31) */
+#ifdef IVAS_FLOAT_FIXED
+#define ONE_BY_NS2A_8K_ST_DFT32MS_OVL_NS (Word16)(0x051E)
+#define OUTMAX_INV_FX_16 (Word16)(0x0001) /* 1/2^15 */
+#endif
#define OUTMAX_SQ 1073741824.f /* 2^30 */
#define OUTMAX_SQ_INV 0.00000000093132257461547852f /* 1/2^30 */
@@ -1970,6 +1981,9 @@ typedef enum _DCTTYPE
#define EPSILON 0.000000000000001f
#define EPSILON_FX 0
+#ifdef IVAS_FLOAT_FIXED
+#define EPSILON_FIX (1)
+#endif
#define MAX_SEGMENT_LENGTH 480
#define NUM_TIME_SWITCHING_BLOCKS 4
@@ -2928,6 +2942,9 @@ enum
#define EVS_PI 3.14159265358979323846264338327950288f
#define EVS_PI_FX 25736 /* pi in Q13 */
+#define EVS_2PI_FX 51472 /* 2 * pi in Q13 */
+#define EVS_PI_BY_2_FX (Word16)(0x3244)
+//#define EVS_PI_FX (Word16)(0x6488)
#define LG10 24660 /* 10*log10(2) in Q13 */
diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c
index cdb33684a1645ce2aa9ca1dfd116b994f5c8eb94..f584ad7aa6eda68749e0b0d984af57a59ef8438c 100644
--- a/lib_com/fd_cng_com.c
+++ b/lib_com/fd_cng_com.c
@@ -1213,6 +1213,28 @@ Word32 rand_gauss_fx(
return temp;
}
#endif
+#ifdef IVAS_FLOAT_FIXED
+/*-------------------------------------------------------------------
+ * rand_gauss_fix()
+ *
+ * Random generator with Gaussian distribution with mean 0 and std 1
+ *-------------------------------------------------------------------*/
+
+Word16 rand_gauss_fix(
+ Word16 *x,
+ Word16 *seed )
+{
+ Word32 temp;
+
+ temp = shr(own_random( seed ), Q2);
+ temp = L_add(temp, shr(own_random( seed ), Q2));
+ temp = L_add(temp, shr(own_random( seed ), Q2));
+
+ *x = (Word16)temp;
+
+ return (Word16)temp;
+}
+#endif
/*-------------------------------------------------------------------
* lpc_from_spectrum_flt()
diff --git a/lib_com/fft_fx.c b/lib_com/fft_fx.c
index f8fb4c139b644cedfbc80c92067e857823269fec..a6dd4eef319d6105b9e60dee572df8689a14fa25 100644
--- a/lib_com/fft_fx.c
+++ b/lib_com/fft_fx.c
@@ -5348,8 +5348,8 @@ void rfft_fx(
SWITCH( sizeOfFft2 )
{
case 80:
- s1 = 409;
- s2 = -409;
+ s1 = 410;
+ s2 = -410;
BREAK;
case 128:
s1 = 256;
diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h
index 12bbf80360060a36a95f5136a51122adb7489daf..5da108b96a6bed7ca60f267e16837329152b3205 100644
--- a/lib_com/ivas_cnst.h
+++ b/lib_com/ivas_cnst.h
@@ -633,6 +633,9 @@ typedef enum
#define SBA_DIRAC_NRG_SMOOTH_LONG 10
#define SBA_DIRAC_NRG_SMOOTH_SHORT 3
+#define SBA_DIRAC_NRG_SMOOTH_SHORT_BY_LONG_FX ((Word16)0x2666)
+#define SBA_DIRAC_NRG_SMOOTH_LONG_BY_LONG_SHORT_FX ((Word32)0x0000B6D8)
+
/* PLC for DFT Stereo residual */
#define STEREO_DFT_RES_N_PEAKS_MAX 15 /*Maximum number of peaks within residual signal in each frame (res_cod_band_max == 6 in 48kHz)*/
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index 826fbb1ae32a69f35d9ff55efc838849fb68cc89..12e75971c7099dcecf5e2a8ce2013188edaf542c 100644
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -3019,6 +3019,14 @@ int16_t check_bounds_s(
const int16_t high /* i : High limit */
);
+#ifdef IVAS_FLOAT_FIXED
+Word32 check_bounds_l(
+ const Word32 value, /* i : Input value */
+ const Word32 low, /* i : Low limit */
+ const Word32 high /* i : High limit */
+);
+#endif
+
ivas_error stereo_memory_enc(
CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */
const int32_t input_Fs, /* i : input sampling rate */
diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h
index b18dcbdd2eccb37db120e43dcf022a5cbf2c135c..330809a16c8e1901945074a3b8c7df214f401025 100644
--- a/lib_com/ivas_prot_fx.h
+++ b/lib_com/ivas_prot_fx.h
@@ -388,6 +388,51 @@ Word16 get_igf_startline(
const Word16 L_frameTCX /* i : full band frame length */
);
+#ifdef IVAS_FLOAT_FIXED
+void stereo_dft_dec_reset_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i/o: decoder DFT stereo handle */
+);
+
+void stereo_dft_dec_update_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 output_frame, /* i : output frame length */
+ const Word16 sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
+);
+void stereo_dft_res_ecu_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal */
+ Word32 *const DFT_PRED_RES, /* i/o: residual prediction signal */
+ const Word16 k, /* i : Subframe index */
+ const Word16 output_frame, /* i : Output frame length */
+ const Word16 prev_bfi, /* i : Previous BFI */
+ const Word32 dmx_nrg, /* i : Down-mix energy */
+ Word16 *num_plocs, /* i/o: Number of peak locations */
+ Word16 *plocs, /* i/o: Peak locations (bin) */
+ Word32 *plocsi, /* i/o: Peak locations (fractional) */
+ Word32 *input_mem /* o : Residual DFT buffer input mem */
+);
+void stereo_dft_res_subst_spec_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal */
+ const Word32 *const DFT_PRED_RES, /* i : residual prediction signal */
+ const Word16 time_offs, /* i : Time offset for phase adjustment*/
+ const Word16 L_res, /* i : bandwidth of residual signal */
+ const Word16 L_ana, /* i : Length of FFT analysis */
+ const Word16 k, /* i : Subframe index */
+ Word16 *num_plocs, /* i/o: Number of peak locations */
+ Word16 *plocs, /* i/o: Peak locations (bin) */
+ Word32 *plocsi, /* i/o: Peak locations (fractional) */
+ const Word16 analysis_flag /* i : Flag for running peak analysis */
+);
+void stereo_dft_res_ecu_burst_att_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal /att. residual */
+ const Word32 dmx_nrg, /* i : dmx energy of current frame */
+ const Word16 L_res, /* i : Bandwidth of residual */
+ const Word16 L_ana /* i : Length of FFT analysis */
+);
+#endif
+
void stereo_dft_dec_analyze_fx(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
const Word32 *input_fx, /* i : input signal */
@@ -408,6 +453,12 @@ void filter_with_allpass_fx(
basic_allpass_t *ap /* i/o: basic allpass structure */
);
+Word32 stereo_dft_dmx_swb_nrg_fx(
+ const Word32 *dmx_k0, /* i : first subframe spectrum */
+ const Word32 *dmx_k1, /* i : second subframe spectrum */
+ const int16_t frame_length /* i : frame lanegth */
+);
+
void stereo_dft_dec_core_switching_fx(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
Word32 output_fx[], /* i/o: synthesis @internal Fs */
@@ -899,6 +950,44 @@ void ivas_mono_downmix_render_passive_fx(
Word32 *output_f_fx[], /* i/o: synthesized core-coder transport channels/mono output */
const Word16 output_frame /* i : output frame length */
);
+void ivas_sba_dirac_stereo_smooth_parameters_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */
+ const Word16 cross_fade_start_offset, /* i : SPAR mixer delay compensation */
+ const Word32 output_Fs, /* i : Fs for delay calculation */
+ const Word16 num_md_sub_frames /* i : number of subframes in mixing matrix */
+);
+
+void stereo_dft_dec_synthesize_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i : DFT buffers */
+ const Word16 chan, /* i : channel number */
+ Word32 output[L_FRAME48k], /* o : output synthesis signal */
+ const Word16 output_frame /* i : output frame length */
+);
+
+void stereo_dft_dec_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ Decoder_State *st0, /* i/o: decoder state structure */
+ Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */
+ Word32 *input_mem, /* i/o: mem of buffer DFT analysis */
+ STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */
+ const Word16 sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */
+ const Word16 sba_mono_flag, /* i : signal mono output for SBA DirAC */
+ ivas_spar_md_dec_state_t *hMdDec, /* i : SPAR MD handle for upmixing */
+ const Word16 cross_fade_start_offset, /* i : SPAR mixer delay compensation */
+ const Word32 output_Fs, /* i : Fs for delay calculation */
+ const Word16 nchan_transport, /* i : number of transpor channels */
+ const Word16 num_md_sub_frames /* i : number of MD subframes */
+);
+
+void synchro_synthesis_fx(
+ const Word32 ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const Word16 output_frame, /* i : Number of samples */
+ const Word16 sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
+);
void ivas_ls_setup_conversion_fx(
Decoder_Struct *st_ivas, /* i : IVAS decoder structure */
@@ -1153,5 +1242,11 @@ void stereo_icBWE_dec_fx(
const Word16 output_frame, /* i : frame length */
Word16 *Q_syn
);
+void ivas_sba_dirac_stereo_dec_fx(
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ Word32 *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 mcmasa /* i : McMASA flag */
+);
#endif
diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c
index aca7348381578b7c49e774ed932d29b6c315490b..e10ce9db2a42dc1c97dbca5a247c2e362ecc3057 100644
--- a/lib_com/ivas_rom_com_fx.c
+++ b/lib_com/ivas_rom_com_fx.c
@@ -309,6 +309,179 @@ const Word16 gridEq_Table[NO_THETA16_MAX] = {
91, 85, 81, 75, 69, 64, 59, 53, 48, 43, 37, 32, 26, 21, 15, 10, 1
};
+const Word16 dft_res_cod_alpha_fx[STEREO_DFT_BAND_MAX] =
+{
+ SHC(0x6666), SHC(0x6666), SHC(0x4000), SHC(0x4000), SHC(0x2666), SHC(0x2666), SHC(0x199A), SHC(0x199A)
+};
+
+const Word32 dft_res_gains_q_fx[][2] = {
+ /* quantization points for joint quantization of prediction gain and residual energy */
+
+ /* column 1 (|ILD| = 0): */
+ { (Word32)( 0x00000000 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x0ef94420 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x1d0e0a80 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x2b9bd400 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x3b765780 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x4d733a80 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x635c2900 ) },
+ { (Word32)( 0x00000000 ), (Word32)( 0x7fffffff ) },
+
+
+ /* column 2 (|ILD| = 2): */
+ { (Word32)( 0x0eabf770 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x0edeb100 ), (Word32)( 0x0ec636b0 ) },
+ { (Word32)( 0x0f6ad710 ), (Word32)( 0x1ca758a0 ) },
+ { (Word32)( 0x10598e20 ), (Word32)( 0x2af85940 ) },
+ { (Word32)( 0x11c9a340 ), (Word32)( 0x3a83dbc0 ) },
+ { (Word32)( 0x13f290a0 ), (Word32)( 0x4c110a00 ) },
+ { (Word32)( 0x1753e700 ), (Word32)( 0x6148cb80 ) },
+ { (Word32)( 0x1cf68be0 ), (Word32)( 0x7cae2100 ) },
+
+ /* column 3 (|ILD| = 4): */
+ { (Word32)( 0x1cf68be0 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x1d56c0e0 ), (Word32)( 0x0e327670 ) },
+ { (Word32)( 0x1e600b00 ), (Word32)( 0x1b7ea1c0 ) },
+ { (Word32)( 0x20224680 ), (Word32)( 0x2921ab40 ) },
+ { (Word32)( 0x22d41b80 ), (Word32)( 0x37cd1c80 ) },
+ { (Word32)( 0x26d6c300 ), (Word32)( 0x4821ea00 ) },
+ { (Word32)( 0x2d06ab00 ), (Word32)( 0x5b738e80 ) },
+ { (Word32)( 0x371ad200 ), (Word32)( 0x73880100 ) },
+
+ /* column 4 (|ILD| = 6): */
+ { (Word32)( 0x2a881e40 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x2b0c77c0 ), (Word32)( 0x0d4ce3e0 ) },
+ { (Word32)( 0x2c785b40 ), (Word32)( 0x19b35b00 ) },
+ { (Word32)( 0x2ede2ac0 ), (Word32)( 0x264d8fc0 ) },
+ { (Word32)( 0x3281c300 ), (Word32)( 0x33aa8200 ) },
+ { (Word32)( 0x37d88c00 ), (Word32)( 0x4238d200 ) },
+ { (Word32)( 0x3fe87900 ), (Word32)( 0x52e04c00 ) },
+ { (Word32)( 0x4c9afe00 ), (Word32)( 0x668bb080 ) },
+
+ /* column 5 (|ILD| = 8): */
+ { (Word32)( 0x371ad200 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x37b7ae40 ), (Word32)( 0x0c2aed10 ) },
+ { (Word32)( 0x396555c0 ), (Word32)( 0x17722e20 ) },
+ { (Word32)( 0x3c34a880 ), (Word32)( 0x22c73ac0 ) },
+ { (Word32)( 0x406b8b80 ), (Word32)( 0x2e942d40 ) },
+ { (Word32)( 0x467f0200 ), (Word32)( 0x3b162b00 ) },
+ { (Word32)( 0x4f700480 ), (Word32)( 0x48d04600 ) },
+ { (Word32)( 0x5cfa3780 ), (Word32)( 0x57f90500 ) },
+
+ /* column 6 (|ILD| = 10): */
+ { (Word32)( 0x427ec780 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x43283900 ), (Word32)( 0x0ae47560 ) },
+ { (Word32)( 0x44f66200 ), (Word32)( 0x14ec3980 ) },
+ { (Word32)( 0x47f59480 ), (Word32)( 0x1edf6980 ) },
+ { (Word32)( 0x4c655a00 ), (Word32)( 0x29068980 ) },
+ { (Word32)( 0x52ac0800 ), (Word32)( 0x3376a300 ) },
+ { (Word32)( 0x5ba86100 ), (Word32)( 0x3e65f940 ) },
+ { (Word32)( 0x68ba3000 ), (Word32)( 0x49984a00 ) },
+
+
+ /* column 7 (|ILD| = 13): */
+ { (Word32)( 0x512c1700 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x51d52c00 ), (Word32)( 0x08e72540 ) },
+ { (Word32)( 0x539f3400 ), (Word32)( 0x11048160 ) },
+ { (Word32)( 0x568dc100 ), (Word32)( 0x18e88e00 ) },
+ { (Word32)( 0x5aceff00 ), (Word32)( 0x20b5d480 ) },
+ { (Word32)( 0x60a8b900 ), (Word32)( 0x285c4640 ) },
+ { (Word32)( 0x68b5bb00 ), (Word32)( 0x2fd0a680 ) },
+ { (Word32)( 0x73c83200 ), (Word32)( 0x369374c0 ) },
+
+ /* column 8 (|ILD| = 16): */
+ { (Word32)( 0x5cfa3780 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x5d92fb00 ), (Word32)( 0x0705b7d0 ) },
+ { (Word32)( 0x5f2e2f80 ), (Word32)( 0x0d5c7470 ) },
+ { (Word32)( 0x61c7ef00 ), (Word32)( 0x136909a0 ) },
+ { (Word32)( 0x657c8900 ), (Word32)( 0x19376500 ) },
+ { (Word32)( 0x6a742980 ), (Word32)( 0x1ea95000 ) },
+ { (Word32)( 0x710eb280 ), (Word32)( 0x239c9d40 ) },
+ { (Word32)( 0x79ba2380 ), (Word32)( 0x27944240 ) },
+
+
+ /* column 9 (|ILD| = 19): */
+ { (Word32)( 0x662c9080 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x66ad4f80 ), (Word32)( 0x0562c778 ) },
+ { (Word32)( 0x6805ff00 ), (Word32)( 0x0a34e330 ) },
+ { (Word32)( 0x6a2e3c80 ), (Word32)( 0x0ebb8800 ) },
+ { (Word32)( 0x6d350080 ), (Word32)( 0x12f75540 ) },
+ { (Word32)( 0x712ddc00 ), (Word32)( 0x16c8ffc0 ) },
+ { (Word32)( 0x76508b00 ), (Word32)( 0x1a0c7c00 ) },
+ { (Word32)( 0x7cd13980 ), (Word32)( 0x1c5dd900 ) },
+
+ /* column 10 (|ILD| = 22): */
+ { (Word32)( 0x6d295e80 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x6d909f00 ), (Word32)( 0x040afa30 ) },
+ { (Word32)( 0x6ea3ce80 ), (Word32)( 0x07a30120 ) },
+ { (Word32)( 0x70590800 ), (Word32)( 0x0af74470 ) },
+ { (Word32)( 0x72b6c780 ), (Word32)( 0x0e03d570 ) },
+ { (Word32)( 0x75c4a800 ), (Word32)( 0x10adbc60 ) },
+ { (Word32)( 0x79a1fd00 ), (Word32)( 0x12d6a9c0 ) },
+ { (Word32)( 0x7e651700 ), (Word32)( 0x14351580 ) },
+
+
+ /* column 11 (|ILD| = 25): */
+ { (Word32)( 0x725edd00 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x72aec080 ), (Word32)( 0x02fc829c ) },
+ { (Word32)( 0x7382fd80 ), (Word32)( 0x05a06a70 ) },
+ { (Word32)( 0x74d1f200 ), (Word32)( 0x080bfe40 ) },
+ { (Word32)( 0x769d9500 ), (Word32)( 0x0a3a1900 ) },
+ { (Word32)( 0x78e74f00 ), (Word32)( 0x0c1565c0 ) },
+ { (Word32)( 0x7bc08f80 ), (Word32)( 0x0d86b160 ) },
+ { (Word32)( 0x7f316600 ), (Word32)( 0x0e59c060 ) },
+
+ /* column 12 (|ILD| = 30): */
+ { (Word32)( 0x78271780 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x78588a00 ), (Word32)( 0x01c22ab2 ) },
+ { (Word32)( 0x78db4880 ), (Word32)( 0x034da4d0 ) },
+ { (Word32)( 0x79a80d00 ), (Word32)( 0x04b3c3e8 ) },
+ { (Word32)( 0x7abdfd00 ), (Word32)( 0x05f02c50 ) },
+ { (Word32)( 0x7c1b1980 ), (Word32)( 0x06f5c290 ) },
+ { (Word32)( 0x7dc60000 ), (Word32)( 0x07b6bb10 ) },
+ { (Word32)( 0x7fbe8780 ), (Word32)( 0x08165900 ) },
+
+ /* column 13 (|ILD| = 35): */
+ { (Word32)( 0x7b86f480 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x7ba44880 ), (Word32)( 0x0103ea70 ) },
+ { (Word32)( 0x7bf1b680 ), (Word32)( 0x01e75bc4 ) },
+ { (Word32)( 0x7c6a6600 ), (Word32)( 0x02b3cc4c ) },
+ { (Word32)( 0x7d0d1f80 ), (Word32)( 0x036659d0 ) },
+ { (Word32)( 0x7dd7d380 ), (Word32)( 0x03f748a0 ) },
+ { (Word32)( 0x7ecd1000 ), (Word32)( 0x045ecc40 ) },
+ { (Word32)( 0x7feb4a80 ), (Word32)( 0x048d0890 ) },
+
+ /* column 14 (|ILD| = 40): */
+ { (Word32)( 0x7d772100 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x7d882280 ), (Word32)( 0x00945f9e ) },
+ { (Word32)( 0x7db4f600 ), (Word32)( 0x0115e7c8 ) },
+ { (Word32)( 0x7dfaa880 ), (Word32)( 0x0189d6ae ) },
+ { (Word32)( 0x7e583e80 ), (Word32)( 0x01ee6752 ) },
+ { (Word32)( 0x7ecc3e00 ), (Word32)( 0x023f24d8 ) },
+ { (Word32)( 0x7f57c500 ), (Word32)( 0x0277b394 ) },
+ { (Word32)( 0x7ff97280 ), (Word32)( 0x028f4b60 ) },
+
+ /* column 15 (|ILD| = 45): */
+ { (Word32)( 0x7e918600 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x7e9b4100 ), (Word32)( 0x005425f2 ) },
+ { (Word32)( 0x7eb4e100 ), (Word32)( 0x009d840a ) },
+ { (Word32)( 0x7edca900 ), (Word32)( 0x00df04de ) },
+ { (Word32)( 0x7f11f100 ), (Word32)( 0x0117939a ) },
+ { (Word32)( 0x7f53d680 ), (Word32)( 0x0144c37e ) },
+ { (Word32)( 0x7fa2cf00 ), (Word32)( 0x0164063a ) },
+ { (Word32)( 0x7ffdef80 ), (Word32)( 0x0170824a ) },
+
+ /* column 16 (|ILD| = 50): */
+ { (Word32)( 0x7f316600 ), (Word32)( 0x00000000 ) },
+ { (Word32)( 0x7f36ef80 ), (Word32)( 0x002f8bde ) },
+ { (Word32)( 0x7f457c00 ), (Word32)( 0x0058f712 ) },
+ { (Word32)( 0x7f5c0780 ), (Word32)( 0x007de508 ) },
+ { (Word32)( 0x7f7a3580 ), (Word32)( 0x009db65f ) },
+ { (Word32)( 0x7f9f7700 ), (Word32)( 0x00b70ac4 ) },
+ { (Word32)( 0x7fcc0780 ), (Word32)( 0x00c8711d ) },
+ { (Word32)( 0x7fff5800 ), (Word32)( 0x00cf398f ) },
+
+};
const Word16 McMASA_LFEGain_vectors_fx_q13[64] = {
3112, 2703, 1556, 1638, -1310, -1802, -2867, -2785,
4096, 4096, 4096, 4096, -6553, -3276, 8355, 819,
@@ -373,3 +546,83 @@ const Word16 pow_10_q11[128] = {
};
/* clang-format on */
+const Word16 ivas_tan_panning_gain_dirac_tbl_fx[601] = {
+ SHC( 0x8000 ), SHC( 0x8001 ), SHC( 0x8002 ), SHC( 0x8003 ), SHC( 0x8005 ), SHC( 0x8007 ), SHC( 0x800a ), SHC( 0x800e ),
+ SHC( 0x8012 ), SHC( 0x8016 ), SHC( 0x801c ), SHC( 0x8021 ), SHC( 0x8028 ), SHC( 0x802f ), SHC( 0x8036 ), SHC( 0x803e ),
+ SHC( 0x8047 ), SHC( 0x8050 ), SHC( 0x805a ), SHC( 0x8064 ), SHC( 0x806f ), SHC( 0x807b ), SHC( 0x8087 ), SHC( 0x8094 ),
+ SHC( 0x80a1 ), SHC( 0x80af ), SHC( 0x80be ), SHC( 0x80cd ), SHC( 0x80dd ), SHC( 0x80ee ), SHC( 0x80ff ), SHC( 0x8110 ),
+ SHC( 0x8123 ), SHC( 0x8136 ), SHC( 0x814a ), SHC( 0x815e ), SHC( 0x8173 ), SHC( 0x8188 ), SHC( 0x819f ), SHC( 0x81b6 ),
+ SHC( 0x81cd ), SHC( 0x81e5 ), SHC( 0x81fe ), SHC( 0x8218 ), SHC( 0x8232 ), SHC( 0x824d ), SHC( 0x8269 ), SHC( 0x8285 ),
+ SHC( 0x82a2 ), SHC( 0x82c0 ), SHC( 0x82de ), SHC( 0x82fd ), SHC( 0x831d ), SHC( 0x833d ), SHC( 0x835f ), SHC( 0x8380 ),
+ SHC( 0x83a3 ), SHC( 0x83c6 ), SHC( 0x83ea ), SHC( 0x840f ), SHC( 0x8435 ), SHC( 0x845b ), SHC( 0x8482 ), SHC( 0x84a9 ),
+ SHC( 0x84d2 ), SHC( 0x84fb ), SHC( 0x8525 ), SHC( 0x854f ), SHC( 0x857b ), SHC( 0x85a7 ), SHC( 0x85d4 ), SHC( 0x8601 ),
+ SHC( 0x8630 ), SHC( 0x865f ), SHC( 0x868f ), SHC( 0x86c0 ), SHC( 0x86f1 ), SHC( 0x8723 ), SHC( 0x8756 ), SHC( 0x878a ),
+ SHC( 0x87bf ), SHC( 0x87f4 ), SHC( 0x882a ), SHC( 0x8861 ), SHC( 0x8899 ), SHC( 0x88d2 ), SHC( 0x890b ), SHC( 0x8945 ),
+ SHC( 0x8980 ), SHC( 0x89bc ), SHC( 0x89f9 ), SHC( 0x8a36 ), SHC( 0x8a74 ), SHC( 0x8ab3 ), SHC( 0x8af3 ), SHC( 0x8b34 ),
+ SHC( 0x8b75 ), SHC( 0x8bb8 ), SHC( 0x8bfb ), SHC( 0x8c3f ), SHC( 0x8c83 ), SHC( 0x8cc9 ), SHC( 0x8d10 ), SHC( 0x8d57 ),
+ SHC( 0x8d9f ), SHC( 0x8de8 ), SHC( 0x8e32 ), SHC( 0x8e7d ), SHC( 0x8ec8 ), SHC( 0x8f15 ), SHC( 0x8f62 ), SHC( 0x8fb0 ),
+ SHC( 0x8fff ), SHC( 0x904f ), SHC( 0x90a0 ), SHC( 0x90f1 ), SHC( 0x9143 ), SHC( 0x9197 ), SHC( 0x91eb ), SHC( 0x9240 ),
+ SHC( 0x9296 ), SHC( 0x92ed ), SHC( 0x9344 ), SHC( 0x939d ), SHC( 0x93f6 ), SHC( 0x9450 ), SHC( 0x94ab ), SHC( 0x9507 ),
+ SHC( 0x9564 ), SHC( 0x95c2 ), SHC( 0x9621 ), SHC( 0x9680 ), SHC( 0x96e1 ), SHC( 0x9742 ), SHC( 0x97a4 ), SHC( 0x9807 ),
+ SHC( 0x986b ), SHC( 0x98d0 ), SHC( 0x9936 ), SHC( 0x999c ), SHC( 0x9a04 ), SHC( 0x9a6c ), SHC( 0x9ad5 ), SHC( 0x9b40 ),
+ SHC( 0x9bab ), SHC( 0x9c16 ), SHC( 0x9c83 ), SHC( 0x9cf1 ), SHC( 0x9d60 ), SHC( 0x9dcf ), SHC( 0x9e3f ), SHC( 0x9eb1 ),
+ SHC( 0x9f23 ), SHC( 0x9f96 ), SHC( 0xa00a ), SHC( 0xa07e ), SHC( 0xa0f4 ), SHC( 0xa16a ), SHC( 0xa1e2 ), SHC( 0xa25a ),
+ SHC( 0xa2d3 ), SHC( 0xa34d ), SHC( 0xa3c8 ), SHC( 0xa444 ), SHC( 0xa4c1 ), SHC( 0xa53e ), SHC( 0xa5bd ), SHC( 0xa63c ),
+ SHC( 0xa6bc ), SHC( 0xa73d ), SHC( 0xa7bf ), SHC( 0xa842 ), SHC( 0xa8c5 ), SHC( 0xa94a ), SHC( 0xa9cf ), SHC( 0xaa55 ),
+ SHC( 0xaadc ), SHC( 0xab64 ), SHC( 0xabed ), SHC( 0xac76 ), SHC( 0xad01 ), SHC( 0xad8c ), SHC( 0xae18 ), SHC( 0xaea5 ),
+ SHC( 0xaf33 ), SHC( 0xafc1 ), SHC( 0xb051 ), SHC( 0xb0e1 ), SHC( 0xb172 ), SHC( 0xb204 ), SHC( 0xb296 ), SHC( 0xb32a ),
+ SHC( 0xb3be ), SHC( 0xb453 ), SHC( 0xb4e9 ), SHC( 0xb580 ), SHC( 0xb617 ), SHC( 0xb6b0 ), SHC( 0xb749 ), SHC( 0xb7e2 ),
+ SHC( 0xb87d ), SHC( 0xb918 ), SHC( 0xb9b4 ), SHC( 0xba51 ), SHC( 0xbaef ), SHC( 0xbb8d ), SHC( 0xbc2c ), SHC( 0xbccc ),
+ SHC( 0xbd6d ), SHC( 0xbe0e ), SHC( 0xbeb0 ), SHC( 0xbf53 ), SHC( 0xbff7 ), SHC( 0xc09b ), SHC( 0xc140 ), SHC( 0xc1e5 ),
+ SHC( 0xc28c ), SHC( 0xc333 ), SHC( 0xc3da ), SHC( 0xc483 ), SHC( 0xc52c ), SHC( 0xc5d6 ), SHC( 0xc680 ), SHC( 0xc72b ),
+ SHC( 0xc7d7 ), SHC( 0xc883 ), SHC( 0xc930 ), SHC( 0xc9de ), SHC( 0xca8c ), SHC( 0xcb3b ), SHC( 0xcbea ), SHC( 0xcc9a ),
+ SHC( 0xcd4b ), SHC( 0xcdfc ), SHC( 0xceae ), SHC( 0xcf60 ), SHC( 0xd013 ), SHC( 0xd0c7 ), SHC( 0xd17b ), SHC( 0xd22f ),
+ SHC( 0xd2e5 ), SHC( 0xd39a ), SHC( 0xd451 ), SHC( 0xd507 ), SHC( 0xd5bf ), SHC( 0xd676 ), SHC( 0xd72f ), SHC( 0xd7e7 ),
+ SHC( 0xd8a1 ), SHC( 0xd95a ), SHC( 0xda14 ), SHC( 0xdacf ), SHC( 0xdb8a ), SHC( 0xdc46 ), SHC( 0xdd02 ), SHC( 0xddbe ),
+ SHC( 0xde7b ), SHC( 0xdf38 ), SHC( 0xdff5 ), SHC( 0xe0b3 ), SHC( 0xe172 ), SHC( 0xe230 ), SHC( 0xe2f0 ), SHC( 0xe3af ),
+ SHC( 0xe46f ), SHC( 0xe52f ), SHC( 0xe5ef ), SHC( 0xe6b0 ), SHC( 0xe771 ), SHC( 0xe833 ), SHC( 0xe8f4 ), SHC( 0xe9b6 ),
+ SHC( 0xea78 ), SHC( 0xeb3b ), SHC( 0xebfe ), SHC( 0xecc1 ), SHC( 0xed84 ), SHC( 0xee47 ), SHC( 0xef0b ), SHC( 0xefcf ),
+ SHC( 0xf093 ), SHC( 0xf157 ), SHC( 0xf21c ), SHC( 0xf2e0 ), SHC( 0xf3a5 ), SHC( 0xf46a ), SHC( 0xf52f ), SHC( 0xf5f5 ),
+ SHC( 0xf6ba ), SHC( 0xf77f ), SHC( 0xf845 ), SHC( 0xf90b ), SHC( 0xf9d0 ), SHC( 0xfa96 ), SHC( 0xfb5c ), SHC( 0xfc22 ),
+ SHC( 0xfce8 ), SHC( 0xfdae ), SHC( 0xfe74 ), SHC( 0xff3a ), SHC( 0x0000 ), SHC( 0x00c6 ), SHC( 0x018c ), SHC( 0x0252 ),
+ SHC( 0x0318 ), SHC( 0x03de ), SHC( 0x04a4 ), SHC( 0x056a ), SHC( 0x0630 ), SHC( 0x06f5 ), SHC( 0x07bb ), SHC( 0x0881 ),
+ SHC( 0x0946 ), SHC( 0x0a0b ), SHC( 0x0ad1 ), SHC( 0x0b96 ), SHC( 0x0c5b ), SHC( 0x0d20 ), SHC( 0x0de4 ), SHC( 0x0ea9 ),
+ SHC( 0x0f6d ), SHC( 0x1031 ), SHC( 0x10f5 ), SHC( 0x11b9 ), SHC( 0x127c ), SHC( 0x133f ), SHC( 0x1402 ), SHC( 0x14c5 ),
+ SHC( 0x1588 ), SHC( 0x164a ), SHC( 0x170c ), SHC( 0x17cd ), SHC( 0x188f ), SHC( 0x1950 ), SHC( 0x1a11 ), SHC( 0x1ad1 ),
+ SHC( 0x1b91 ), SHC( 0x1c51 ), SHC( 0x1d10 ), SHC( 0x1dd0 ), SHC( 0x1e8e ), SHC( 0x1f4d ), SHC( 0x200b ), SHC( 0x20c8 ),
+ SHC( 0x2185 ), SHC( 0x2242 ), SHC( 0x22fe ), SHC( 0x23ba ), SHC( 0x2476 ), SHC( 0x2531 ), SHC( 0x25ec ), SHC( 0x26a6 ),
+ SHC( 0x275f ), SHC( 0x2819 ), SHC( 0x28d1 ), SHC( 0x298a ), SHC( 0x2a41 ), SHC( 0x2af9 ), SHC( 0x2baf ), SHC( 0x2c66 ),
+ SHC( 0x2d1b ), SHC( 0x2dd1 ), SHC( 0x2e85 ), SHC( 0x2f39 ), SHC( 0x2fed ), SHC( 0x30a0 ), SHC( 0x3152 ), SHC( 0x3204 ),
+ SHC( 0x32b5 ), SHC( 0x3366 ), SHC( 0x3416 ), SHC( 0x34c5 ), SHC( 0x3574 ), SHC( 0x3622 ), SHC( 0x36d0 ), SHC( 0x377d ),
+ SHC( 0x3829 ), SHC( 0x38d5 ), SHC( 0x3980 ), SHC( 0x3a2a ), SHC( 0x3ad4 ), SHC( 0x3b7d ), SHC( 0x3c26 ), SHC( 0x3ccd ),
+ SHC( 0x3d74 ), SHC( 0x3e1b ), SHC( 0x3ec0 ), SHC( 0x3f65 ), SHC( 0x4009 ), SHC( 0x40ad ), SHC( 0x4150 ), SHC( 0x41f2 ),
+ SHC( 0x4293 ), SHC( 0x4334 ), SHC( 0x43d4 ), SHC( 0x4473 ), SHC( 0x4511 ), SHC( 0x45af ), SHC( 0x464c ), SHC( 0x46e8 ),
+ SHC( 0x4783 ), SHC( 0x481e ), SHC( 0x48b7 ), SHC( 0x4950 ), SHC( 0x49e9 ), SHC( 0x4a80 ), SHC( 0x4b17 ), SHC( 0x4bad ),
+ SHC( 0x4c42 ), SHC( 0x4cd6 ), SHC( 0x4d6a ), SHC( 0x4dfc ), SHC( 0x4e8e ), SHC( 0x4f1f ), SHC( 0x4faf ), SHC( 0x503f ),
+ SHC( 0x50cd ), SHC( 0x515b ), SHC( 0x51e8 ), SHC( 0x5274 ), SHC( 0x52ff ), SHC( 0x538a ), SHC( 0x5413 ), SHC( 0x549c ),
+ SHC( 0x5524 ), SHC( 0x55ab ), SHC( 0x5631 ), SHC( 0x56b6 ), SHC( 0x573b ), SHC( 0x57be ), SHC( 0x5841 ), SHC( 0x58c3 ),
+ SHC( 0x5944 ), SHC( 0x59c4 ), SHC( 0x5a43 ), SHC( 0x5ac2 ), SHC( 0x5b3f ), SHC( 0x5bbc ), SHC( 0x5c38 ), SHC( 0x5cb3 ),
+ SHC( 0x5d2d ), SHC( 0x5da6 ), SHC( 0x5e1e ), SHC( 0x5e96 ), SHC( 0x5f0c ), SHC( 0x5f82 ), SHC( 0x5ff6 ), SHC( 0x606a ),
+ SHC( 0x60dd ), SHC( 0x614f ), SHC( 0x61c1 ), SHC( 0x6231 ), SHC( 0x62a0 ), SHC( 0x630f ), SHC( 0x637d ), SHC( 0x63ea ),
+ SHC( 0x6455 ), SHC( 0x64c0 ), SHC( 0x652b ), SHC( 0x6594 ), SHC( 0x65fc ), SHC( 0x6664 ), SHC( 0x66ca ), SHC( 0x6730 ),
+ SHC( 0x6795 ), SHC( 0x67f9 ), SHC( 0x685c ), SHC( 0x68be ), SHC( 0x691f ), SHC( 0x6980 ), SHC( 0x69df ), SHC( 0x6a3e ),
+ SHC( 0x6a9c ), SHC( 0x6af9 ), SHC( 0x6b55 ), SHC( 0x6bb0 ), SHC( 0x6c0a ), SHC( 0x6c63 ), SHC( 0x6cbc ), SHC( 0x6d13 ),
+ SHC( 0x6d6a ), SHC( 0x6dc0 ), SHC( 0x6e15 ), SHC( 0x6e69 ), SHC( 0x6ebd ), SHC( 0x6f0f ), SHC( 0x6f60 ), SHC( 0x6fb1 ),
+ SHC( 0x7001 ), SHC( 0x7050 ), SHC( 0x709e ), SHC( 0x70eb ), SHC( 0x7138 ), SHC( 0x7183 ), SHC( 0x71ce ), SHC( 0x7218 ),
+ SHC( 0x7261 ), SHC( 0x72a9 ), SHC( 0x72f0 ), SHC( 0x7337 ), SHC( 0x737d ), SHC( 0x73c1 ), SHC( 0x7405 ), SHC( 0x7448 ),
+ SHC( 0x748b ), SHC( 0x74cc ), SHC( 0x750d ), SHC( 0x754d ), SHC( 0x758c ), SHC( 0x75ca ), SHC( 0x7607 ), SHC( 0x7644 ),
+ SHC( 0x7680 ), SHC( 0x76bb ), SHC( 0x76f5 ), SHC( 0x772e ), SHC( 0x7767 ), SHC( 0x779f ), SHC( 0x77d6 ), SHC( 0x780c ),
+ SHC( 0x7841 ), SHC( 0x7876 ), SHC( 0x78aa ), SHC( 0x78dd ), SHC( 0x790f ), SHC( 0x7940 ), SHC( 0x7971 ), SHC( 0x79a1 ),
+ SHC( 0x79d0 ), SHC( 0x79ff ), SHC( 0x7a2c ), SHC( 0x7a59 ), SHC( 0x7a85 ), SHC( 0x7ab1 ), SHC( 0x7adb ), SHC( 0x7b05 ),
+ SHC( 0x7b2e ), SHC( 0x7b57 ), SHC( 0x7b7e ), SHC( 0x7ba5 ), SHC( 0x7bcb ), SHC( 0x7bf1 ), SHC( 0x7c16 ), SHC( 0x7c3a ),
+ SHC( 0x7c5d ), SHC( 0x7c80 ), SHC( 0x7ca1 ), SHC( 0x7cc3 ), SHC( 0x7ce3 ), SHC( 0x7d03 ), SHC( 0x7d22 ), SHC( 0x7d40 ),
+ SHC( 0x7d5e ), SHC( 0x7d7b ), SHC( 0x7d97 ), SHC( 0x7db3 ), SHC( 0x7dce ), SHC( 0x7de8 ), SHC( 0x7e02 ), SHC( 0x7e1b ),
+ SHC( 0x7e33 ), SHC( 0x7e4a ), SHC( 0x7e61 ), SHC( 0x7e78 ), SHC( 0x7e8d ), SHC( 0x7ea2 ), SHC( 0x7eb6 ), SHC( 0x7eca ),
+ SHC( 0x7edd ), SHC( 0x7ef0 ), SHC( 0x7f01 ), SHC( 0x7f12 ), SHC( 0x7f23 ), SHC( 0x7f33 ), SHC( 0x7f42 ), SHC( 0x7f51 ),
+ SHC( 0x7f5f ), SHC( 0x7f6c ), SHC( 0x7f79 ), SHC( 0x7f85 ), SHC( 0x7f91 ), SHC( 0x7f9c ), SHC( 0x7fa6 ), SHC( 0x7fb0 ),
+ SHC( 0x7fb9 ), SHC( 0x7fc2 ), SHC( 0x7fca ), SHC( 0x7fd1 ), SHC( 0x7fd8 ), SHC( 0x7fdf ), SHC( 0x7fe4 ), SHC( 0x7fea ),
+ SHC( 0x7fee ), SHC( 0x7ff2 ), SHC( 0x7ff6 ), SHC( 0x7ff9 ), SHC( 0x7ffb ), SHC( 0x7ffd ), SHC( 0x7ffe ), SHC( 0x7fff ),
+ SHC( 0x7fff ),
+};
+
+/* clang-format on */
diff --git a/lib_com/ivas_rom_com_fx.h b/lib_com/ivas_rom_com_fx.h
index 567c057e096d71913766592c28602577019fc0cf..165e148fe5ac9b496210dd0464779da16801abcd 100644
--- a/lib_com/ivas_rom_com_fx.h
+++ b/lib_com/ivas_rom_com_fx.h
@@ -49,6 +49,8 @@ extern const Word16 ivas_cos_twiddle_160_fx[ IVAS_160_PT_LEN >> 1 ];
extern const Word16 ivas_sin_twiddle_80_fx[ IVAS_80_PT_LEN >> 1 ];
extern const Word16 ivas_cos_twiddle_80_fx[ IVAS_80_PT_LEN >> 1 ];
extern const Word16 nf_tw_smoothing_coeffs_fx[N_LTP_GAIN_MEMS];
+extern const Word32 dft_res_gains_q_fx[][2];
+extern const Word16 dft_res_cod_alpha_fx[STEREO_DFT_BAND_MAX];
extern const Word16 dft_trigo_12k8_fx[STEREO_DFT_N_12k8_ENC / 4 + 1];
extern const Word16 dft_trigo_32k_fx[STEREO_DFT_N_32k_ENC / 4 + 1];
extern const Word16 dft_trigo_48k_fx[STEREO_DFT_N_MAX_ENC / 4 + 1];
@@ -77,4 +79,7 @@ extern const Word32 ls_azimuth_CICP19_fx[11];
extern const Word32 ls_elevation_CICP19_fx[11];
extern const Word16 pow_10_q11[128];
-#endif
\ No newline at end of file
+extern const Word16 ivas_sin_az_fx[ 361 ];
+extern const Word16 ivas_sine_panning_tbl_fx[601];
+extern const Word16 ivas_tan_panning_gain_dirac_tbl_fx[601];
+#endif
diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c
index b03cb1331f3e3db9b07f18002e7032fe88c2ac7c..aa27862010e6f153bb7cb19e50890285d8788f57 100644
--- a/lib_com/ivas_tools.c
+++ b/lib_com/ivas_tools.c
@@ -595,6 +595,26 @@ int16_t check_bounds_s(
return value_adj;
}
+/*-------------------------------------------------------------------*
+ * check_bounds_l()
+ *
+ * Ensure the input value is within the given limits
+ *-------------------------------------------------------------------*/
+
+/*! r: Adjusted value */
+Word32 check_bounds_l(
+ const Word32 value, /* i : Input value */
+ const Word32 low, /* i : Low limit */
+ const Word32 high /* i : High limit */
+)
+{
+ Word32 value_adj;
+
+ value_adj = min( max( value, low ), high );
+
+ return value_adj;
+}
+
/****************************************************************************/
/* matrix functions */
diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h
index a1a1888baec4d201072ff3b6e9c9fa2598cc49e4..36daae347c7cd1b666ea85a5654e66774231055c 100644
--- a/lib_com/prot_fx2.h
+++ b/lib_com/prot_fx2.h
@@ -2358,9 +2358,9 @@ void calc_normal_length_fx(
Word16 Q_syn
);
-Word32 calc_tilt_bwe_fx( /* o : Tilt in Q24 */
- const Word16 *sp0, /* i : i signal */
- const Word16 exp, /* i : Exp of inp signal */
+Word32 ivas_calc_tilt_bwe_fx( /* o : Tilt in Q24 */
+ const Word32 *sp, /* i : i signal */
+ const Word16 exp_sp, /* i : Exp of inp signal */
const Word16 N /* i : signal length */
);
@@ -4605,9 +4605,23 @@ void mhvals(
Word16* m /*, float * h*/
);
+Word32 sign_l(
+ const Word32 x /* i : input value of x */
+);
+
+void ivas_updt_dec_common_fx(
+ Decoder_State *st_fx, /* i/o: decoder state structure */
+ Word16 hq_core_type_fx, /* i : HQ core type */
+ const Word16 concealWholeFrameTmp, /* i : concealWholeFrameTmp flag */
+ const Word32 *synth, /* i : decoded synthesis */
+ const Word16 Qpostd /* i : Synthesis Q value */
+);
+
/* Random generator with Gaussian distribution with mean 0 and std 1 */
Word32 rand_gauss(Word16 *seed);
+Word16 rand_gauss_fix(Word16 *x, Word16 *seed);
+
void lpc_from_spectrum(
HANDLE_FD_CNG_COM hFdCngCom,
const Word16 start, /*i : start band*/
@@ -8283,6 +8297,13 @@ void v_add_fx(
const int16_t N /* i : Vector length */
);
+void v_shr(
+ const Word32 x[], /* i : Input vector */
+ const Word16 shift, /* i : Constant */
+ Word32 y[], /* o : Output vector that contains x >> shift */
+ const Word16 N /* i : Vector length */
+);
+
void cldfbAnalysis_ts_fx(
const Word32 *timeIn_fx, /* i : time buffer */
Word32 realBuffer_fx[CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */
diff --git a/lib_com/swb_bwe_com_fx.c b/lib_com/swb_bwe_com_fx.c
index 0727281c4d9f5f1551306386de44ffaae5d2d506..95c496818dc7f65591c90cbbfdec011580985bbb 100644
--- a/lib_com/swb_bwe_com_fx.c
+++ b/lib_com/swb_bwe_com_fx.c
@@ -716,6 +716,121 @@ Word32 calc_tilt_bwe_fx( /* o : Tilt in Q24 */
return L_temp;
}
+#ifdef IVAS_FLOAT_FIXED
+Word32 ivas_calc_tilt_bwe_fx( /* o : Tilt in Q24 */
+ const Word32 *sp, /* i : input signal */
+ const Word16 exp_sp, /* i : Exp of inp signal */
+ const Word16 N /* i : signal length */
+)
+{
+ Word16 i, j;
+ Word32 L_ener, L_ener_tot, L_temp;
+ Word32 tmp1, tmp2;
+ const Word32 *ptr;
+ Word16 exp2, tmp_exp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ BASOP_SATURATE_WARNING_OFF_EVS
+
+ /* this is required for adaptative precision energy summation loop, do not remove */
+ Overflow = 0;
+ move16();
+ exp2 = 0;
+ move16();
+
+ ptr = sp;
+ move16();
+ L_ener_tot = L_deposit_l(1);
+
+ /* Divide Frame Length by 32 */
+ FOR(j = shr(N, 5); j > 0; j--)
+ {
+#ifdef BASOP_NOGLOB /* Critical Overflow and all those below*/
+ tmp1 = mult_ro(*ptr++, 8192, &Overflow); /* Divide by 4 */
+#else
+ tmp1 = mult_r(*ptr++, 8192); /* Divide by 4 */
+#endif
+ L_ener = L_mult0(tmp1, tmp1);
+ /* With the shift by 4 and the L_mult0, no overflow possible for 32 samples */
+ FOR(i = 1; i < 32; i++)
+ {
+ tmp1 = L_mls_o(*ptr++, 8192, &Overflow); /* Divide by 4 */
+ L_ener = Madd_32_32(L_ener, tmp1, tmp1);
+ }
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ L_ener = L_shr_o(L_ener, exp2, &Overflow);
+ L_temp = L_add_o(L_ener_tot, L_ener, &Overflow);
+#else
+ L_ener = L_shr(L_ener, exp2);
+ L_temp = L_add(L_ener_tot, L_ener);
+#endif
+ IF(Overflow != 0)
+ {
+ L_ener_tot = L_shr(L_ener_tot, 1);
+ L_ener = L_shr(L_ener, 1);
+ exp2 = add(exp2, 1);
+ /* this is required, do not remove */
+ Overflow = 0;
+ move16();
+ }
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ L_ener_tot = L_add_o(L_ener_tot, L_ener, &Overflow);
+#else
+ L_ener_tot = L_add(L_ener_tot, L_ener);
+#endif
+ }
+#ifdef BASOP_NOGLOB
+ L_ener = (L_abs(L_sub_o(sp[1], sp[0], &Overflow)));
+#else
+ L_ener = L_deposit_l(abs_s(sub(sp[1], sp[0])));
+#endif
+ FOR(i = 2; i < N; i++)
+ {
+ /* Eq to (sp[i] - sp[i-1]) * (sp[i-1] - sp[i-2]) < 0 */
+#ifdef BASOP_NOGLOB
+ tmp1 = L_sub_o(sp[i], sp[i - 1], &Overflow);
+ tmp2 = L_sub_o(sp[i - 1], sp[i - 2], &Overflow);
+#else
+ tmp1 = sub(sp[i], sp[i - 1]);
+ tmp2 = sub(sp[i - 1], sp[i - 2]);
+#endif
+ tmp2 = mult(tmp1, tmp2);
+ tmp1 = abs_s(tmp1);
+ /* to Get either 0 or -1 in 'tmp2' */
+ tmp2 = shr(tmp2, 15);
+ /* this allows this code */
+ L_ener = L_msu0(L_ener, tmp2, tmp1);
+ /* instead of this one */
+ /* test(); */
+ /* if (tmp2 < 0) */
+ /* { */
+ /* L_ener = L_mac0(L_ener, 1, tmp1); */
+ /* } */
+ /* it saves one op */
+ }
+
+ tmp_exp = norm_l(L_ener_tot);
+ L_temp = L_shl(L_ener_tot, tmp_exp);
+ tmp1 = sub(add(31 + 4, exp2), add(tmp_exp, shl(exp_sp, 1)));
+ L_temp = Isqrt_lc(L_temp, &tmp_exp);
+
+ /* *tilt_flt = (float)(r1/sqrt(r0)); */
+ exp2 = norm_l(L_ener);
+ L_temp = Mult_32_16(L_temp, round_fx(L_shl(L_ener, exp2)));
+ exp2 = sub(exp2, tmp_exp);
+ exp2 = add(exp2, exp_sp);
+
+ /* Put in Q24 */
+ L_temp = L_shr(L_temp, sub(exp2, 24));
+
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ return L_temp;
+}
+#endif
+
/*-------------------------------------------------------------------*
* calc_norm_envelop()
*
diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c
index 2093c794190e43fd79151b515f2610ae1d0dc3df..dd3ab398033b41196d635c66b6b5d2a40be1ecd6 100644
--- a/lib_com/tools_fx.c
+++ b/lib_com/tools_fx.c
@@ -3485,6 +3485,23 @@ void v_add_fx(
return;
}
+
+void v_shr(
+ const Word32 x[], /* i : Input vector */
+ const Word16 shift, /* i : Constant */
+ Word32 y[], /* o : Output vector that contains x >> shift */
+ const Word16 N /* i : Vector length */
+)
+{
+ Word16 i;
+
+ for ( i = 0; i < N; i++ )
+ {
+ y[i] = L_shr(x[i], shift);
+ }
+
+ return;
+}
/*-------------------------------------------------------------------*
* delay_signal()
*
@@ -3507,3 +3524,23 @@ void delay_signal32(
return;
}
+
+/*---------------------------------------------------------------------
+ * sign()
+ *
+ *---------------------------------------------------------------------*/
+
+/*! r: sign of x (+1/-1) */
+Word32 sign_l(
+ const Word32 x /* i : input value of x */
+)
+{
+ IF ( LT_32(x , 0) )
+ {
+ return MIN_32;
+ }
+ ELSE
+ {
+ return MAX_32;
+ }
+}
\ No newline at end of file
diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c
index e6b27f44cf7a26640cfa5da35ec6d1642cce1539..8de531e5b775f0db87d831cd1cbe3c9e54fc018e 100644
--- a/lib_dec/ivas_corecoder_dec_reconfig.c
+++ b/lib_dec/ivas_corecoder_dec_reconfig.c
@@ -112,6 +112,13 @@ ivas_error ivas_corecoder_dec_reconfig(
free( st_ivas->hSCE[0]->save_hb_synth );
st_ivas->hSCE[0]->save_hb_synth = NULL;
+#ifdef IVAS_FLOAT_FIXED
+ free( st_ivas->hSCE[0]->save_synth_fx );
+ st_ivas->hSCE[0]->save_synth_fx = NULL;
+
+ free( st_ivas->hSCE[0]->save_hb_synth_fx );
+ st_ivas->hSCE[0]->save_hb_synth_fx = NULL;
+#endif
}
}
@@ -339,6 +346,13 @@ ivas_error ivas_corecoder_dec_reconfig(
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) );
}
set_zero( st_ivas->hSCE[0]->save_synth, output_frame );
+#ifdef IVAS_FLOAT_FIXED
+ if ( ( st_ivas->hSCE[0]->save_synth_fx = (Word32 *) malloc( sizeof( *(st_ivas->hSCE[0]->save_synth_fx)) * output_frame ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) );
+ }
+ set_l( st_ivas->hSCE[0]->save_synth_fx, 0, output_frame );
+#endif
}
if ( st_ivas->hSCE[0]->save_hb_synth == NULL )
@@ -348,6 +362,13 @@ ivas_error ivas_corecoder_dec_reconfig(
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) );
}
set_zero( st_ivas->hSCE[0]->save_hb_synth, output_frame );
+#ifdef IVAS_FLOAT_FIXED
+ if ( ( st_ivas->hSCE[0]->save_hb_synth_fx = (Word32 *) malloc( sizeof(*(st_ivas->hSCE[0]->save_hb_synth_fx)) * output_frame ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) );
+ }
+ set_l( st_ivas->hSCE[0]->save_hb_synth_fx, 0, output_frame );
+#endif
}
}
diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c
index 33694d018058b8fb8d40e80eb0259b8636330a44..3e337fa43b636ccd7cf904186ae141fa93230739 100644
--- a/lib_dec/ivas_cpe_dec.c
+++ b/lib_dec/ivas_cpe_dec.c
@@ -241,6 +241,9 @@ ivas_error ivas_cpe_dec(
{
/* Update DFT Stereo memories */
stereo_dft_dec_update( hCPE->hStereoDft, output_frame, 0 );
+#ifdef IVAS_FLOAT_FIXED
+ stereo_dft_dec_update_fx( hCPE->hStereoDft, output_frame, 0 );
+#endif
if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate <= IVAS_SID_5k2 )
{
@@ -489,6 +492,7 @@ ivas_error ivas_cpe_dec(
}
else
{
+ assert(0);
stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0, 0, 0, 0, 0, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
}
diff --git a/lib_dec/ivas_cpe_dec_fx.c b/lib_dec/ivas_cpe_dec_fx.c
index 6bd6c2730afcb6155ffcf108c29d8b8dbd1ae231..cc4da5182085b599680e55832dbe7a678e61bda5 100644
--- a/lib_dec/ivas_cpe_dec_fx.c
+++ b/lib_dec/ivas_cpe_dec_fx.c
@@ -233,6 +233,9 @@ ivas_error ivas_cpe_dec_fx(
{
/* Update DFT Stereo memories */
stereo_dft_dec_update( hCPE->hStereoDft, output_frame, 0 );
+#ifdef IVAS_FLOAT_FIXED
+ stereo_dft_dec_update_fx( hCPE->hStereoDft, output_frame, 0 );
+#endif
IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) && LE_32( ivas_total_brate, IVAS_SID_5k2 ) )
{
@@ -453,6 +456,7 @@ ivas_error ivas_cpe_dec_fx(
IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && !( EQ_16( hCPE->nchan_out, 1 ) && EQ_16( hCPE->hStereoDft->hConfig->res_cod_mode, STEREO_DFT_RES_COD_OFF ) ) )
{
float DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX];
+ Word32 DFT_fx[CPE_CHANNELS][STEREO_DFT_BUF_MAX];
set_f( DFT[0], 0.0f, STEREO_DFT_BUF_MAX );
set_f( DFT[1], 0.0f, STEREO_DFT_BUF_MAX );
@@ -481,13 +485,133 @@ ivas_error ivas_cpe_dec_fx(
}
ELSE
{
- stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0, 0, 0, 0, 0, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
+ float l_hb_nrg = 0.0, l_hb_nrg_subr = 0.0;
+ static int frame_counter = 0;
+ if (frame_counter >= 461)
+ frame_counter = frame_counter;
+ float max_val = 0.0;
+ int i_max_val = 0, i_max_val_psd;
+ {
+ for (int ii = 0; ii < sizeof(sts[0]->hFdCngDec->smoothed_psd) / sizeof(sts[0]->hFdCngDec->smoothed_psd[0]); ii++)
+ {
+ if (max_val < fabs(sts[0]->hFdCngDec->smoothed_psd[ii]))
+ {
+ max_val = (float)fabs(sts[0]->hFdCngDec->smoothed_psd[ii]);
+ }
+ }
+ i_max_val_psd = (int)max_val;
+ sts[0]->hFdCngDec->q_smoothed_psd = norm_l(i_max_val_psd) - Q9;
+ max_val = 0.0;
+ for (int ii = 0; ii < sizeof(DFT) / sizeof(DFT[0]); ii++)
+ {
+ for (int jj = 0; jj < sizeof(DFT[0]) / sizeof(DFT[0][0]); jj++)
+ {
+ if (max_val < fabs(DFT[ii][jj]))
+ {
+ max_val = (float)fabs(DFT[ii][jj]);
+ }
+ }
+ }
+ i_max_val = (int)max_val;
+ hCPE->hStereoDft->q_dft = norm_l(i_max_val) - 6;
+ IF (hCPE->hStereoDft->q_dft > Q15)
+ {
+ hCPE->hStereoDft->q_dft = Q15;
+ }
+ IF (EQ_16(hCPE->hStereoDft->first_frame, 1))
+ {
+ hCPE->hStereoDft->q_smoothed_nrg = hCPE->hStereoDft->q_dft;
+ hCPE->hStereoDft->q_past_dft = hCPE->hStereoDft->q_dft;
+ hCPE->hStereoDft->first_frame = 0;
+ }
+
+ sts[0]->stab_fac_fx = (Word16)floatToFixed(sts[0]->stab_fac, 15);
+ sts[0]->hFdCngDec->cna_rescale_fact_fx = (Word16)floatToFixed(sts[0]->hFdCngDec->cna_rescale_fact, 15);
+ sts[0]->hFdCngDec->cna_act_fact_fx = (Word16)floatToFixed(sts[0]->hFdCngDec->cna_act_fact, 15);
+ floatToFixed_arrL(&hCPE->hStereoDft->res_gains_ind[0][0], &hCPE->hStereoDft->res_gains_ind_fx[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->res_pred_gain[0], &hCPE->hStereoDft->res_pred_gain_fx[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->itd[0], &hCPE->hStereoDft->itd_fx[0], Q15, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0]));
+ floatToFixed_arrL(&sts[0]->hFdCngDec->smoothed_psd[0], &sts[0]->hFdCngDec->smoothed_psd_fx[0], sts[0]->hFdCngDec->q_smoothed_psd, sizeof(sts[0]->hFdCngDec->smoothed_psd_fx) / sizeof(sts[0]->hFdCngDec->smoothed_psd_fx[0]));
+ floatToFixed_arrL(&DFT[0][0], &DFT_fx[0][0], hCPE->hStereoDft->q_dft , sizeof(DFT) / sizeof(DFT[0][0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->res_cod_mem[0], &hCPE->hStereoDft->res_cod_mem_fx[0], hCPE->hStereoDft->q_dft, sizeof(hCPE->hStereoDft->res_cod_mem_fx) / sizeof(hCPE->hStereoDft->res_cod_mem_fx[0]));
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ if (l_hb_nrg_subr < hCPE->hStereoDft->hb_nrg_subr[ii])
+ {
+ l_hb_nrg_subr = hCPE->hStereoDft->hb_nrg_subr[ii];
+ }
+ }
+ hCPE->hStereoDft->q_hb_nrg_subr = 0;
+ if (l_hb_nrg_subr > (float)MAX_32)
+ {
+ int quotient = (int) ceil(l_hb_nrg_subr / (float)MAX_32);
+ hCPE->hStereoDft->q_hb_nrg_subr = Q31 - norm_l(quotient);
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_subr_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg_subr[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr)));
+ }
+
+
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ if (l_hb_nrg < hCPE->hStereoDft->hb_nrg[ii])
+ {
+ l_hb_nrg = hCPE->hStereoDft->hb_nrg[ii];
+ }
+ }
+ hCPE->hStereoDft->q_hb_nrg = 0;
+ if (l_hb_nrg > (float)MAX_32)
+ {
+ int quotient = (int) ceil(l_hb_nrg / (float)MAX_32);
+ hCPE->hStereoDft->q_hb_nrg = Q31 - norm_l(quotient);
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg)));
+ }
+
+ floatToFixed_arrL(&hCPE->hStereoDft->side_gain[0], &hCPE->hStereoDft->side_gain_fx[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->gipd[0], &hCPE->hStereoDft->gipd_fx[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0]));
+ floatToFixed_arr(&hCPE->hStereoDft->g_state[0], &hCPE->hStereoDft->g_state_fx[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0]));
+ floatToFixed_arr(&sts[0]->hFdCngDec->cna_cm[0], &sts[0]->hFdCngDec->cna_cm_fx[0], Q15, sizeof(sts[0]->hFdCngDec->cna_cm_fx) / sizeof(sts[0]->hFdCngDec->cna_cm_fx[0]));
+ floatToFixed_arr(&hCPE->hStereoCng->cm[0], &hCPE->hStereoCng->cm_fx[0], Q15, sizeof(hCPE->hStereoCng->cm_fx) / sizeof(hCPE->hStereoCng->cm_fx[0]));
+ floatToFixed_arr(&sts[0]->hFdCngDec->cna_g_state[0], &sts[0]->hFdCngDec->cna_g_state_fx[0], Q15, sizeof(sts[0]->hFdCngDec->cna_g_state_fx) / sizeof(sts[0]->hFdCngDec->cna_g_state_fx[0]));
+ }
+ stereo_dft_dec_fx( hCPE->hStereoDft, sts[0], DFT_fx, hCPE->input_mem_fx[1], hCPE->hStereoCng, 0, 0, 0, 0, 0, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
+ {
+ sts[0]->hFdCngDec->cna_rescale_fact = fixedToFloat(sts[0]->hFdCngDec->cna_rescale_fact_fx, 15);
+ sts[0]->hFdCngDec->cna_act_fact = fixedToFloat(sts[0]->hFdCngDec->cna_act_fact_fx, 15);
+ fixedToFloat_arrL(&hCPE->hStereoDft->res_gains_ind_fx[0][0], &hCPE->hStereoDft->res_gains_ind[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->res_pred_gain_fx[0], &hCPE->hStereoDft->res_pred_gain[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->itd_fx[0], &hCPE->hStereoDft->itd[0], Q15, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0]));
+ fixedToFloat_arrL(&sts[0]->hFdCngDec->smoothed_psd_fx[0], &sts[0]->hFdCngDec->smoothed_psd[0], sts[0]->hFdCngDec->q_smoothed_psd, sizeof(sts[0]->hFdCngDec->smoothed_psd_fx) / sizeof(sts[0]->hFdCngDec->smoothed_psd_fx[0]));
+ fixedToFloat_arrL(&DFT_fx[0][0], &DFT[0][0], hCPE->hStereoDft->q_dft , sizeof(DFT) / sizeof(DFT[0][0]));
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_subr[0] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[0] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr)));
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg[ii] = ((float)hCPE->hStereoDft->hb_nrg_fx[ii] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg)));
+ }
+ fixedToFloat_arrL(&hCPE->hStereoDft->side_gain_fx[0], &hCPE->hStereoDft->side_gain[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->gipd_fx[0], &hCPE->hStereoDft->gipd[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0]));
+ fixedToFloat_arr(&hCPE->hStereoDft->g_state_fx[0], &hCPE->hStereoDft->g_state[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0]));
+ fixedToFloat_arr(&sts[0]->hFdCngDec->cna_cm_fx[0], &sts[0]->hFdCngDec->cna_cm[0], Q15, sizeof(sts[0]->hFdCngDec->cna_cm_fx) / sizeof(sts[0]->hFdCngDec->cna_cm_fx[0]));
+ fixedToFloat_arr(&hCPE->hStereoCng->cm_fx[0], &hCPE->hStereoCng->cm[0], Q15, sizeof(hCPE->hStereoCng->cm_fx) / sizeof(hCPE->hStereoCng->cm_fx[0]));
+ fixedToFloat_arr(&sts[0]->hFdCngDec->cna_g_state_fx[0], &sts[0]->hFdCngDec->cna_g_state[0], Q15, sizeof(sts[0]->hFdCngDec->cna_g_state_fx) / sizeof(sts[0]->hFdCngDec->cna_g_state_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q15, sizeof(hCPE->hStereoDft->td_gain_fx) / sizeof(hCPE->hStereoDft->td_gain_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->res_cod_mem_fx[0], &hCPE->hStereoDft->res_cod_mem[0], hCPE->hStereoDft->q_dft, sizeof(hCPE->hStereoDft->res_cod_mem_fx) / sizeof(hCPE->hStereoDft->res_cod_mem_fx[0]));
+ }
+ frame_counter++;
+ //printf("frame_counter = [%d]\n", frame_counter);
}
/* synthesis iFFT */
FOR( n = 0; n < hCPE->nchan_out; n++ )
{
- stereo_dft_dec_synthesize( hCPE, DFT, n, output_flt[n], output_frame );
+ stereo_dft_dec_synthesize( hCPE, &DFT[0], n, output_flt[n], output_frame );
}
}
ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c
index 8726f63d4e1ad5d93e42e67772f08a84cb946a8d..551e55fde5214fa7deee00d2f71c74239c34e4b7 100644
--- a/lib_dec/ivas_jbm_dec.c
+++ b/lib_dec/ivas_jbm_dec.c
@@ -80,6 +80,9 @@ ivas_error ivas_jbm_dec_tc(
int16_t n, output_frame, nchan_out;
Decoder_State *st; /* used for bitstream handling */
float *p_output[MAX_TRANSPORT_CHANNELS]; /* 'float' buffer for output synthesis */
+#ifdef IVAS_FLOAT_FIXED
+ Word32 *p_output_fix[MAX_TRANSPORT_CHANNELS]; /* 'float' buffer for output synthesis */
+#endif
int16_t nchan_remapped;
int16_t nb_bits_metadata[MAX_SCE + 1];
int32_t output_Fs, ivas_total_brate;
@@ -108,6 +111,13 @@ ivas_error ivas_jbm_dec_tc(
{
set_zero( p_output[n], L_FRAME48k );
}
+#ifdef IVAS_FLOAT_FIXED
+ p_output_fix[n] = st_ivas->p_output_fx[n];
+ if ( p_output_fix[n] != NULL )
+ {
+ set_l( p_output_fix[n], 0, L_FRAME48k );
+ }
+#endif
}
if ( !st_ivas->hDecoderConfig->Opt_tsm )
@@ -132,6 +142,13 @@ ivas_error ivas_jbm_dec_tc(
{
set_f( p_output[n], 0.0f, output_frame );
}
+#ifdef IVAS_FLOAT_FIXED
+ /* zero output when first frame(s) is lost */
+ for ( n = 0; n < nchan_out; n++ )
+ {
+ set_l( p_output_fix[n], 0, output_frame );
+ }
+#endif
}
else if ( st_ivas->ivas_format == STEREO_FORMAT )
{
@@ -640,7 +657,169 @@ ivas_error ivas_jbm_dec_tc(
ivas_spar_dec_gen_umx_mat( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, ivas_total_brate, st_ivas->last_active_ivas_total_brate ) );
}
+#ifndef IVAS_FLOAT_FIXED_
ivas_sba_dirac_stereo_dec( st_ivas, p_output, output_frame, st_ivas->ivas_format == MC_FORMAT );
+#else
+ {
+ float l_hb_nrg = 0.0, l_hb_nrg_subr = 0.0;
+ static int frame_counter = 0;
+ if (frame_counter >= 200)
+ frame_counter = frame_counter;
+ float max_val = 0.0;
+ int i_max_val_psd, i_max_val_op;
+ CPE_DEC_HANDLE hCPE = st_ivas->hCPE[0];
+ SCE_DEC_HANDLE hSCE = st_ivas->hSCE[0];
+ for (int ii = 0; ii < sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0]); ii++)
+ {
+ if (max_val < fabs(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii]))
+ {
+ max_val = (float)fabs(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii]);
+ }
+ }
+ i_max_val_psd = (int)max_val;
+ for (int ii = 0; ii < 2; ii++)
+ {
+ for (int jj = 0; jj < (48000 / FRAMES_PER_SEC); jj++)
+ {
+ if (max_val < fabs(p_output[ii][jj]))
+ {
+ max_val = (float)fabs(p_output[ii][jj]);
+ }
+ }
+ }
+ i_max_val_op = (int)max_val;
+ hCPE->hStereoDft->q_dft = norm_l(i_max_val_op) - Q10;
+ st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd = norm_l(i_max_val_psd) - Q9;
+ IF (EQ_16(hCPE->hStereoDft->first_frame, 1))
+ {
+ hCPE->hStereoDft->q_smoothed_nrg = hCPE->hStereoDft->q_dft;
+ hCPE->hStereoDft->first_frame = 0;
+ }
+
+ st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac, 15);
+ st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact, 15);
+ st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact, 15);
+ floatToFixed_arrL(&hCPE->hStereoDft->res_gains_ind[0][0], &hCPE->hStereoDft->res_gains_ind_fx[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->res_pred_gain[0], &hCPE->hStereoDft->res_pred_gain_fx[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->itd[0], &hCPE->hStereoDft->itd_fx[0], Q1, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0]));
+ floatToFixed_arrL(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0]));
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ if (l_hb_nrg_subr < hCPE->hStereoDft->hb_nrg_subr[ii])
+ {
+ l_hb_nrg_subr = hCPE->hStereoDft->hb_nrg_subr[ii];
+ }
+ }
+ hCPE->hStereoDft->q_hb_nrg_subr = 0;
+ if (l_hb_nrg_subr > (float)MAX_32)
+ {
+ int quotient = (int) ceil(l_hb_nrg_subr / (float)MAX_32);
+ hCPE->hStereoDft->q_hb_nrg_subr = Q31 - norm_l(quotient);
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_subr_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg_subr[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr)));
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ if (l_hb_nrg < hCPE->hStereoDft->hb_nrg[ii])
+ {
+ l_hb_nrg = hCPE->hStereoDft->hb_nrg[ii];
+ }
+ }
+ hCPE->hStereoDft->q_hb_nrg = 0;
+ if (l_hb_nrg > (float)MAX_32)
+ {
+ int quotient = (int) ceil(l_hb_nrg / (float)MAX_32);
+ hCPE->hStereoDft->q_hb_nrg = Q31 - norm_l(quotient);
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg)));
+ }
+
+ floatToFixed_arrL(&hCPE->hStereoDft->side_gain[0], &hCPE->hStereoDft->side_gain_fx[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0]));
+ floatToFixed_arrL(&hCPE->hStereoDft->gipd[0], &hCPE->hStereoDft->gipd_fx[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0]));
+ floatToFixed_arr(&hCPE->hStereoDft->g_state[0], &hCPE->hStereoDft->g_state_fx[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0]));
+ floatToFixed_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0]));
+ IF (hCPE->hStereoCng != NULL)
+ {
+ floatToFixed_arr(&hCPE->hStereoCng->cm[0], &hCPE->hStereoCng->cm_fx[0], Q15, sizeof(hCPE->hStereoCng->cm_fx) / sizeof(hCPE->hStereoCng->cm_fx[0]));
+ }
+ floatToFixed_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0]));
+ for (int ii = 0; ii < 2; ii++)
+ {
+ floatToFixed_arrL(&p_output[ii][0], &p_output_fix[ii][0], hCPE->hStereoDft->q_dft , (48000 / FRAMES_PER_SEC));
+ }
+
+ Word16 q = 11;
+ IF( hCPE->hCoreCoder[0] != NULL )
+ floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], q, L_FRAME32k);
+ IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) )
+ floatToFixed_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], q, L_FRAME16k);
+ floatToFixed_arrL(&hCPE->input_mem_BPF[0][0], &hCPE->input_mem_BPF_fx[0][0], q, STEREO_DFT32MS_OVL_16k);
+ floatToFixed_arrL(&hCPE->input_mem[0][0], &hCPE->input_mem_fx[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ));
+ floatToFixed_arrL(&hCPE->input_mem_LB[0][0], &hCPE->input_mem_LB_fx[0][0], q, STEREO_DFT32MS_OVL_16k);
+ floatToFixed_arrL(&hCPE->input_mem[1][0], &hCPE->input_mem_fx[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ));
+ floatToFixed_arrL(&hCPE->input_mem_LB[1][0], &hCPE->input_mem_LB_fx[1][0], q, STEREO_DFT32MS_OVL_16k);
+ IF( hCPE->hStereoDft != NULL )
+ floatToFixed_arrL(&hCPE->hStereoDft->ap_delay_mem[0], &hCPE->hStereoDft->ap_delay_mem_fx[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS ));
+ floatToFixed_arrL(&hSCE->save_synth[0], &hSCE->save_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC));
+ floatToFixed_arrL(&hSCE->save_hb_synth[0], &hSCE->save_hb_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC));
+ IF( hCPE->hCoreCoder[0] != NULL )
+ floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_out[0], &hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], q, L_FRAME48k);
+ IF( hCPE->hStereoDft != NULL )
+ floatToFixed_arrL(&hCPE->hStereoDft->buff_LBTCX_mem[0], &hCPE->hStereoDft->buff_LBTCX_mem_fx[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS ));
+
+ ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fix, output_frame, st_ivas->ivas_format == MC_FORMAT );
+
+ st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact = fixedToFloat(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx, 15);
+ st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact = fixedToFloat(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx, 15);
+ fixedToFloat_arrL(&hCPE->hStereoDft->res_gains_ind_fx[0][0], &hCPE->hStereoDft->res_gains_ind[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->res_pred_gain_fx[0], &hCPE->hStereoDft->res_pred_gain[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->itd_fx[0], &hCPE->hStereoDft->itd[0], Q1, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0]));
+ fixedToFloat_arrL(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0]));
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg_subr[0] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[0] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr)));
+ }
+ for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_fx) / sizeof(hCPE->hStereoDft->hb_nrg_fx[0]); ii++)
+ {
+ hCPE->hStereoDft->hb_nrg[ii] = ((float)hCPE->hStereoDft->hb_nrg_fx[ii] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg)));
+ }
+ fixedToFloat_arrL(&hCPE->hStereoDft->side_gain_fx[0], &hCPE->hStereoDft->side_gain[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->gipd_fx[0], &hCPE->hStereoDft->gipd[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0]));
+ fixedToFloat_arr(&hCPE->hStereoDft->g_state_fx[0], &hCPE->hStereoDft->g_state[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0]));
+ fixedToFloat_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0]));
+ IF (hCPE->hStereoCng != NULL)
+ {
+ fixedToFloat_arr(&hCPE->hStereoCng->cm_fx[0], &hCPE->hStereoCng->cm[0], Q15, sizeof(hCPE->hStereoCng->cm_fx) / sizeof(hCPE->hStereoCng->cm_fx[0]));
+ }
+ fixedToFloat_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0]));
+ fixedToFloat_arrL(&hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q15, sizeof(hCPE->hStereoDft->td_gain_fx) / sizeof(hCPE->hStereoDft->td_gain_fx[0]));
+ for (int ii = 0; ii < 2; ii++)
+ {
+ fixedToFloat_arrL(&p_output_fix[ii][0], &p_output[ii][0], hCPE->hStereoDft->q_dft, (48000 / FRAMES_PER_SEC));
+ }
+ IF( hCPE->hCoreCoder[0] != NULL )
+ fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], q, L_FRAME32k);
+ IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) )
+ fixedToFloat_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], q, L_FRAME16k);
+ fixedToFloat_arrL(&hCPE->input_mem_BPF_fx[0][0], &hCPE->input_mem_BPF[0][0], q, STEREO_DFT32MS_OVL_16k);
+ fixedToFloat_arrL(&hCPE->input_mem_fx[0][0], &hCPE->input_mem[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ));
+ fixedToFloat_arrL(&hCPE->input_mem_LB_fx[0][0], &hCPE->input_mem_LB[0][0], q, STEREO_DFT32MS_OVL_16k);
+ fixedToFloat_arrL(&hCPE->input_mem_fx[1][0], &hCPE->input_mem[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS ));
+ fixedToFloat_arrL(&hCPE->input_mem_LB_fx[1][0], &hCPE->input_mem_LB[1][0], q, STEREO_DFT32MS_OVL_16k);
+ IF( hCPE->hStereoDft != NULL )
+ fixedToFloat_arrL(&hCPE->hStereoDft->ap_delay_mem_fx[0], &hCPE->hStereoDft->ap_delay_mem[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS ));
+ fixedToFloat_arrL(&hSCE->save_synth_fx[0], &hSCE->save_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC));
+ fixedToFloat_arrL(&hSCE->save_hb_synth_fx[0], &hSCE->save_hb_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC));
+ IF( hCPE->hCoreCoder[0] != NULL )
+ fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_out[0], q, L_FRAME48k);
+ IF( hCPE->hStereoDft != NULL )
+ fixedToFloat_arrL(&hCPE->hStereoDft->buff_LBTCX_mem_fx[0], &hCPE->hStereoDft->buff_LBTCX_mem[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS ));
+ }
+#endif
}
else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) )
{
diff --git a/lib_dec/ivas_post_proc.c b/lib_dec/ivas_post_proc.c
index cae6e5488253b7cb8dafc9af22dcb4d672d91ccb..ef2e1f5a28f3222bc5f5580442acc23cf88bf371 100644
--- a/lib_dec/ivas_post_proc.c
+++ b/lib_dec/ivas_post_proc.c
@@ -250,12 +250,12 @@ void ivas_post_proc_fx(
#endif // IVAS_FLOAT_FIXED
+#ifdef IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------------
- * stereo_dft_dec_core_switching()
+ * stereo_dft_dec_core_switching_fx()
*
* core switching in DFT stereo
*-------------------------------------------------------------------------*/
-#ifdef IVAS_FLOAT_FIXED
void stereo_dft_dec_core_switching_fx(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
Word32 output_fx[], /* i/o: synthesis @internal Fs */
diff --git a/lib_dec/ivas_rom_dec.c b/lib_dec/ivas_rom_dec.c
index 9ad8ead53d1f6f91490c7a3dd52469fa2fe21084..01f446dfba8236263a61ad43fbb318bfb5084c2a 100644
--- a/lib_dec/ivas_rom_dec.c
+++ b/lib_dec/ivas_rom_dec.c
@@ -94,6 +94,45 @@ const float dft_ap_gains[5][3] =
};
#ifdef IVAS_FLOAT_FIXED
+const Word16 dft_alpha_s_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x599A), (Word16)(0x3333), (Word16)(0x2000), (Word16)(0x199A),
+ (Word16)(0x1334), (Word16)(0x0CCD), (Word16)(0x0CCD), (Word16)(0x0CCD),
+ (Word16)(0x0CCD), (Word16)(0x0CCD), (Word16)(0x0CCD), (Word16)(0x0CCD),
+ (Word16)(0x0CCD)
+};
+
+const Word16 dft_alpha_w_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666)
+};
+
+const Word16 dft_alpha_s2_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x599A), (Word16)(0x4CCD), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666)
+};
+const Word16 dft_alpha_s_b2_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x599A), (Word16)(0x2666), (Word16)(0x1334), (Word16) 0x0CCD,
+ (Word16)(0x0CCD), (Word16)(0x0CCD), (Word16)(0x0CCD)
+};
+
+const Word16 dft_alpha_w_b2_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666)
+};
+const Word16 dft_alpha_s2_b2_fx[STEREO_DFT_BAND_MAX] =
+{
+ (Word16)(0x599A), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666),
+ (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666)
+};
const Word32 dft_bpf_weights_fx[] =
{
1073784832, 1068033792, 1050938752, 1022962432, 984855360, 937628928, 882514816, 820918592, 754369152,
@@ -126,6 +165,15 @@ const float dft_res_pred_weights[][STEREO_DFT_BAND_MAX] =
{ 1.f, .5f, .4f, .4f }
};
+#ifdef IVAS_FLOAT_FIXED
+const Word16 dft_res_pred_weights_fx[][STEREO_DFT_BAND_MAX] =
+{
+ { MAX_16, ONE_IN_Q14 + ONE_IN_Q13, ONE_IN_Q14, (Word16)(0x3333), (Word16)(0x3333) },
+ { MAX_16, MAX_16, MAX_16, MAX_16, 0},
+ { MAX_16, ONE_IN_Q14, (Word16)(0x3333), (Word16)(0x3333) }
+};
+#endif
+
const float dft_win232ms_8k[75] =
{
@@ -342,6 +390,34 @@ const float min_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS] =
0.5f, 0.5f, 0.5, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.3f, 0.3f, 0.3f
};
+#ifdef IVAS_FLOAT_FIXED
+const Word16 max_smooth_gains1_fx[SBA_DIRAC_STEREO_NUM_BANDS] =
+{
+ (Word16)(0x7D71), (Word16)(0x7C29), (Word16)(0x799A), (Word16)(0x7333),
+ (Word16)(0x7333), (Word16)(0x7333), (Word16)(0x7333), (Word16)(0x7333),
+ (Word16)(0x7333), (Word16)(0x7333), (Word16)(0x7333), (Word16)(0x7333)
+};
+
+const Word16 min_smooth_gains1_fx[SBA_DIRAC_STEREO_NUM_BANDS] =
+{
+ (Word16)(0x0000), (Word16)(0x0000), (Word16)(0x6000), (Word16)(0x6000),
+ (Word16)(0x0000), (Word16)(0x0000), (Word16)(0x0000), (Word16)(0x0000),
+ (Word16)(0x0000), (Word16)(0x0000), (Word16)(0x0000), (Word16)(0x0000)
+};
+const Word16 max_smooth_gains2_fx[SBA_DIRAC_STEREO_NUM_BANDS] =
+{
+ (Word16)(0x6000), (Word16)(0x6000), (Word16)(0x6000), (Word16)(0x6000),
+ (Word16)(0x6000), (Word16)(0x6000), (Word16)(0x6000), (Word16)(0x6000),
+ (Word16)(0x6000), (Word16)(0x7333), (Word16)(0x7333), (Word16)(0x7333)};
+
+const Word16 min_smooth_gains2_fx[SBA_DIRAC_STEREO_NUM_BANDS] =
+{
+ (Word16)(0x4000), (Word16)(0x4000), (Word16)(0x4000), (Word16)(0x4000),
+ (Word16)(0x4000), (Word16)(0x4000), (Word16)(0x4000), (Word16)(0x4000),
+ (Word16)(0x4000), (Word16)(0x2666), (Word16)(0x2666), (Word16)(0x2666)
+};
+#endif
+
/*-------------------------------------------------------------------------
* ECLVQ Stereo ROM tables
*------------------------------------------------------------------------*/
diff --git a/lib_dec/ivas_rom_dec.h b/lib_dec/ivas_rom_dec.h
index 32b7c95911d1bc6f30b9e76f1f6281e7dc0d047b..165b7f3eec653a935206a8f624192360fd6525db 100644
--- a/lib_dec/ivas_rom_dec.h
+++ b/lib_dec/ivas_rom_dec.h
@@ -49,6 +49,12 @@ extern const float dft_alpha_s_b2[STEREO_DFT_BAND_MAX];
extern const float dft_alpha_s2_b2[STEREO_DFT_BAND_MAX];
extern const float dft_bpf_weights[];
#ifdef IVAS_FLOAT_FIXED
+extern const Word16 dft_alpha_s_fx[STEREO_DFT_BAND_MAX];
+extern const Word16 dft_alpha_w_fx[STEREO_DFT_BAND_MAX];
+extern const Word16 dft_alpha_s2_fx[STEREO_DFT_BAND_MAX];
+extern const Word16 dft_alpha_s_b2_fx[STEREO_DFT_BAND_MAX];
+extern const Word16 dft_alpha_w_b2_fx[STEREO_DFT_BAND_MAX];
+extern const Word16 dft_alpha_s2_b2_fx[STEREO_DFT_BAND_MAX];
extern const Word32 dft_bpf_weights_fx[];
extern const Word32 dft_ap_gains_fx[5][3];
#endif
@@ -74,6 +80,8 @@ extern const Word16 dft_win232ms_12k8_fx[120];
extern const Word16 dft_win232ms_16k_fx[150];
extern const Word16 dft_win232ms_32k_fx[300];
extern const Word16 dft_win232ms_48k_fx[450];
+extern const Word16 dft_res_pred_weights_fx[][STEREO_DFT_BAND_MAX];
+extern const Word16 dft_win_8k_fx[70];
#endif
extern const float dft_win_8k[70];
@@ -85,6 +93,12 @@ extern const float max_smooth_gains1[SBA_DIRAC_STEREO_NUM_BANDS];
extern const float min_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS];
extern const float max_smooth_gains2[SBA_DIRAC_STEREO_NUM_BANDS];
+#ifdef IVAS_FLOAT_FIXED
+extern const Word16 min_smooth_gains1_fx[SBA_DIRAC_STEREO_NUM_BANDS];
+extern const Word16 max_smooth_gains1_fx[SBA_DIRAC_STEREO_NUM_BANDS];
+extern const Word16 min_smooth_gains2_fx[SBA_DIRAC_STEREO_NUM_BANDS];
+extern const Word16 max_smooth_gains2_fx[SBA_DIRAC_STEREO_NUM_BANDS];
+#endif
/*----------------------------------------------------------------------------------*
* ECLVQ Stereo ROM tables
diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c
index 1a67a1aecb82d61f764e843b4cde593b4af3ebae..f8bdb85ec9b4b801acdceafd0b92192e7553a05b 100644
--- a/lib_dec/ivas_sba_dirac_stereo_dec.c
+++ b/lib_dec/ivas_sba_dirac_stereo_dec.c
@@ -43,6 +43,7 @@
#include "wmc_auto.h"
+#ifndef IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------*
* ivas_get_sba_dirac_stereo_flag()
*
@@ -114,6 +115,7 @@ void ivas_sba_dirac_stereo_config(
return;
}
+#endif
/*-------------------------------------------------------------------*
@@ -848,6 +850,9 @@ void ivas_sba_dirac_stereo_dec(
ivas_sba_dirac_stereo_config( hStereoDft->hConfig );
hStereoDft->nbands = ivas_sba_dirac_stereo_band_config( hStereoDft->band_limits, st_ivas->hDecoderConfig->output_Fs, hStereoDft->NFFT, ( ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT ) && !mcmasa ) );
stereo_dft_dec_update( hStereoDft, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
+#ifdef IVAS_FLOAT_FIXED
+ stereo_dft_dec_update_fx( hCPE->hStereoDft, output_frame, 0 );
+#endif
if ( st_ivas->nchan_transport > 1 )
{
stereo_dft_dec_analyze( hCPE, output[0], DFT, 0, output_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0 );
diff --git a/lib_dec/ivas_sba_dirac_stereo_dec_fx.c b/lib_dec/ivas_sba_dirac_stereo_dec_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..887fd3a277502e2e9b0eebc62ac444e30b5e1981
--- /dev/null
+++ b/lib_dec/ivas_sba_dirac_stereo_dec_fx.c
@@ -0,0 +1,1229 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "ivas_cnst.h"
+#include "prot_fx2.h"
+#include "ivas_prot.h"
+#include "ivas_prot_fx.h"
+#include "ivas_rom_com.h"
+#include "ivas_rom_com_fx.h"
+#include "ivas_rom_dec.h"
+#include "wmc_auto.h"
+
+#ifdef IVAS_FLOAT_FIXED
+#define SIN_NEG_30_DEGREES_Q15 ((Word16)0xC000)
+#define SIN_30_DEGREES_Q15 ((Word16)0x4000)
+
+/*-------------------------------------------------------------------*
+ * ivas_get_sba_dirac_stereo_flag()
+ *
+ * Set sba_dirac_stereo_flag
+ *-------------------------------------------------------------------*/
+
+Word16 ivas_get_sba_dirac_stereo_flag(
+ Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
+)
+{
+ Word16 sba_dirac_stereo_flag;
+ AUDIO_CONFIG output_config;
+
+ sba_dirac_stereo_flag = 0;
+ move16();
+ output_config = st_ivas->hDecoderConfig->output_config;
+ move16();
+
+ IF ( EQ_16(st_ivas->ivas_format, SBA_FORMAT) || (EQ_16( st_ivas->ivas_format, MC_FORMAT) && EQ_16(st_ivas->mc_mode, MC_MODE_MCMASA )) )
+ {
+ IF ( EQ_16(st_ivas->ivas_format, SBA_FORMAT ))
+ {
+ IF ( EQ_16(output_config, IVAS_AUDIO_CONFIG_STEREO) || ( EQ_16(output_config, IVAS_AUDIO_CONFIG_MONO) && EQ_16(st_ivas->nchan_transport, 1) ) )
+ {
+ sba_dirac_stereo_flag = 1;
+ move16();
+ }
+ }
+ ELSE
+ {
+ IF ( EQ_16(st_ivas->nchan_transport, 1) && EQ_16(output_config, IVAS_AUDIO_CONFIG_STEREO) )
+ {
+ sba_dirac_stereo_flag = 1;
+ move16();
+ }
+ }
+ }
+ ELSE IF ( EQ_16(st_ivas->ivas_format, SBA_ISM_FORMAT) )
+ {
+ IF ( EQ_16(output_config, IVAS_AUDIO_CONFIG_STEREO) )
+ {
+ sba_dirac_stereo_flag = 1;
+ move16();
+ }
+ }
+
+ return sba_dirac_stereo_flag;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_config()
+ *
+ * DFT Stereo Configuration for SBA DirAC stereo output
+ *-------------------------------------------------------------------*/
+
+void ivas_sba_dirac_stereo_config(
+ STEREO_DFT_CONFIG_DATA_HANDLE hConfig /* o : DFT stereo configuration */
+)
+{
+ IF ( hConfig != NULL )
+ {
+ hConfig->dmx_active = STEREO_DFT_DMX_ACTIVE;
+ move16();
+ hConfig->band_res = STEREO_DFT_BAND_RES_HIGH;
+ move16();
+ hConfig->prm_res = 2;
+ move16();
+
+ hConfig->res_pred_mode = STEREO_DFT_RESPRED_ESF;
+ move16();
+
+ hConfig->res_cod_mode = STEREO_DFT_RES_COD_OFF;
+ move16();
+ hConfig->ada_wb_res_cod_mode = 0;
+ move16();
+
+ hConfig->hybrid_itd_flag = 0;
+ move16();
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_band_config()
+ *
+ * Band Configuration for SBA DirAC stereo output
+ *-------------------------------------------------------------------*/
+
+static Word16 ivas_sba_dirac_stereo_band_config(
+ Word16 *band_limits, /* o : DFT band limits */
+ const Word32 output_Fs, /* i : output sampling rate */
+ const Word16 NFFT, /* i : analysis/synthesis window length */
+ const Word16 spar_flag /* i : SPAR or DirAC band grouping */
+)
+{
+ Word16 i;
+ Word16 bins_per_cldfb_band;
+ Word16 nbands, num_cldfb_bands;
+
+ nbands = SBA_DIRAC_STEREO_NUM_BANDS;
+ move16();
+
+ IF ( spar_flag )
+ {
+ nbands = IVAS_MAX_NUM_BANDS;
+ move16();
+ }
+ ELSE
+ {
+ nbands = 5;
+ move16();
+ }
+
+ SWITCH (output_Fs)
+ {
+ case 8000:
+ num_cldfb_bands = 10;
+ move16();
+ BREAK;
+ case 16000:
+ num_cldfb_bands = 20;
+ move16();
+ BREAK;
+ case 32000:
+ num_cldfb_bands = 40;
+ move16();
+ BREAK;
+ case 48000:
+ num_cldfb_bands = 60;
+ move16();
+ BREAK;
+ default:
+ num_cldfb_bands = 60;
+ move16();
+ assert(0);
+ }
+
+ bins_per_cldfb_band = (NFFT / ( 2 * num_cldfb_bands ));
+ move16();
+ band_limits[0] = 1;
+ move16();
+ FOR ( i = 1; i < nbands; i++ )
+ {
+ IF ( spar_flag )
+ {
+ band_limits[i] = i_mult(DirAC_band_grouping_12[i], bins_per_cldfb_band);
+ move16();
+ }
+ ELSE
+ {
+ band_limits[i] = i_mult(DirAC_band_grouping_5[i], bins_per_cldfb_band);
+ move16();
+ }
+ IF ( GE_16(band_limits[i], shr(NFFT, 1) ) )
+ {
+ nbands = i;
+ move16();
+ BREAK;
+ }
+ }
+ band_limits[nbands] = shr(NFFT, 1);
+ move16();
+
+ return nbands;
+}
+
+static Word16 get_panning_tangent_gain(
+ const Word16 sinAngleMapped)
+{
+ Word16 tbl_len = sizeof(ivas_sine_panning_tbl_fx) / sizeof(ivas_sine_panning_tbl_fx[0]); move16();
+ Word16 idx = shr(tbl_len, 1); move16();
+ const Word16 *ptr_sin = &ivas_sine_panning_tbl_fx[0];
+ const Word16 *ptr_tan = &ivas_tan_panning_gain_dirac_tbl_fx[0];
+ Word16 lim_l = 0;
+ move16();
+ Word16 lim_r = tbl_len;
+ move16();
+ WHILE (1)
+ {
+ idx = shr( add( lim_l, lim_r ), 1 );
+ IF (GE_16(idx, tbl_len))
+ {
+ return ptr_tan[tbl_len - 1];
+ }
+ ELSE IF (LE_16(idx, 0))
+ {
+ return ptr_tan[0];
+ }
+ ELSE IF ( LE_16(sinAngleMapped, ptr_sin[idx + 1]) && GE_16(sinAngleMapped, ptr_sin[idx]))
+ {
+ IF (EQ_16(sinAngleMapped, ptr_sin[idx + 1]))
+ {
+ return ptr_tan[idx + 1];
+ }
+ ELSE IF(EQ_16(sinAngleMapped, ptr_sin[idx]))
+ {
+ return ptr_tan[idx];
+ }
+ ELSE
+ {
+ Word16 mid = add(shr( ptr_sin[idx], 1 ), shr(ptr_sin[idx + 1], 1));
+ move16();
+ IF( LE_16( sinAngleMapped, mid ) )
+ {
+ return ptr_tan[idx];
+ }
+ ELSE
+ {
+ return ptr_tan[idx + 1];
+ }
+ }
+ }
+ ELSE IF (GT_16( sinAngleMapped, ptr_sin[idx] ))
+ {
+ lim_l = add( idx, 1 );
+ move16();
+ }
+ ELSE IF (LT_16(sinAngleMapped, ptr_sin[idx]))
+ {
+ lim_r = sub( idx, 1 );
+ move16();
+ }
+ }
+}
+
+static Word16 get_panning(
+ const Word16 aziDeg,
+ const Word16 eleDeg )
+{
+ Word16 panning = 0; move16();
+ Word16 azAddEl = aziDeg + eleDeg; move16();
+ Word16 azSubEl = aziDeg - eleDeg; move16();
+ const Word16 *ptr_sin_az = &ivas_sin_az_fx[180];
+ while (azAddEl > 180)
+ {
+ azAddEl = azAddEl - 360;
+ move16();
+ }
+ while (azAddEl < -180)
+ {
+ azAddEl = azAddEl + 360;
+ move16();
+ }
+ while (azSubEl > 180)
+ {
+ azSubEl = azSubEl - 360;
+ move16();
+ }
+ while (azSubEl < -180)
+ {
+ azSubEl = azSubEl + 360;
+ move16();
+ }
+ /*sin(az)cos(el) = 0.5 * (sin(az + el) + sin(az - el)) */
+ Word16 sin_az_cos_el = add(shr(ptr_sin_az[azAddEl], 1), shr(ptr_sin_az[azSubEl], 1));
+ move16();
+ IF (GE_32(sin_az_cos_el, SIN_30_DEGREES_Q15))
+ { /* Left side */
+ panning = (Word16)0x7fff;
+ move16();
+ }
+ ELSE IF (LE_32(sin_az_cos_el, SIN_NEG_30_DEGREES_Q15))
+ { /* Right side */
+ panning = (Word16)0x8000;
+ move16();
+ }
+ ELSE
+ { /* Tangent panning law */
+ panning = get_panning_tangent_gain(sin_az_cos_el);
+ }
+ return panning;
+}
+
+
+/*-------------------------------------------------------------------*
+ * map_params_dirac_to_stereo()
+ *
+ * Compute DFT Stereo parameters from DirAC parameters
+ *-------------------------------------------------------------------*/
+
+static void map_params_dirac_to_stereo(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const IVAS_QMETADATA_HANDLE hQMetaData, /* i : frame of MASA q_metadata */
+ Word32 synth[], /* i : decoded downmix signal */
+ Word32 DFT[STEREO_DFT_BUF_MAX], /* i/o: DFT buffer */
+ const UWord8 b_wide_panning, /* i : flag indicating wider panning */
+ const Word16 L_frame, /* i : core signal length */
+ const Word16 mcmasa, /* i : McMASA flag */
+ Word16 q_dft
+)
+{
+ Word16 i, b, k;
+ Word16 k_offset;
+ Word16 nbands, nBlocks;
+ Word16 block;
+ Word16 block_len;
+ Word16 azimuth[MAX_PARAM_SPATIAL_SUBFRAMES][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word16 elevation[MAX_PARAM_SPATIAL_SUBFRAMES][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word32 diffuseness[SBA_DIRAC_STEREO_NUM_BANDS];
+ Word32 block_nrg[MAX_PARAM_SPATIAL_SUBFRAMES];
+ Word32 nrg_norm1, nrg_norm2;
+ Word32 *pSynth;
+ Word32 surrCoh[SBA_DIRAC_STEREO_NUM_BANDS];
+ Word32 *pDFT;
+ Word32 subframe_band_nrg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word16 q_nrg;
+ Word32 smooth_long_avg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word32 smooth_short_avg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word32 *side_gain, *res_pred_gain;
+ IVAS_QDIRECTION *q_direction;
+ Word16 q_div, q_sqrt;
+ const Word16 *ptr_sin_az = &ivas_sin_az_fx[180];
+ const Word16 *ptr_cos_el = &ivas_sin_az_fx[270];
+
+ nBlocks = MAX_PARAM_SPATIAL_SUBFRAMES;
+ move16();
+ nbands = hStereoDft->nbands;
+ move16();
+ k_offset = STEREO_DFT_OFFSET;
+ move16();
+ side_gain = hStereoDft->side_gain_fx + i_mult(k_offset, STEREO_DFT_BAND_MAX);
+ res_pred_gain = hStereoDft->res_pred_gain_fx + i_mult(k_offset, STEREO_DFT_BAND_MAX);
+ q_direction = &( hQMetaData->q_direction[0] );
+
+ /* gain smoothing factor */
+ pDFT = DFT;
+ q_nrg = q_dft;
+ move16();
+ FOR ( k = 0; k < NB_DIV; k++ )
+ {
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ /* calculate band-wise subframe energies */
+ subframe_band_nrg[k][b] = 0;
+ move32();
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ subframe_band_nrg[k][b] = L_add(subframe_band_nrg[k][b],
+ Madd_32_32(Mpy_32_32(pDFT[2 * i], pDFT[2 * i]),
+ pDFT[2 * i + 1], pDFT[2 * i + 1]));
+ move32();
+ }
+ subframe_band_nrg[k][b] = Sqrt32( subframe_band_nrg[k][b], &q_nrg );
+ move32();
+ hStereoDft->smooth_buf_fx[b][NB_DIV - 1 - k] = subframe_band_nrg[k][b];
+ move32();
+
+ /* calculate short and long energy averages */
+ smooth_short_avg[k][b] = EPSILON_FIX;
+ move32();
+ FOR ( i = sub(NB_DIV - 1, k); i < add(SBA_DIRAC_NRG_SMOOTH_SHORT + NB_DIV - 1, k); i++ )
+ {
+ smooth_short_avg[k][b] = L_add(smooth_short_avg[k][b], hStereoDft->smooth_buf_fx[b][i]);
+ move32();
+ }
+
+ smooth_long_avg[k][b] = smooth_short_avg[k][b];
+ move32();
+ FOR ( i = sub(NB_DIV - 1 + SBA_DIRAC_NRG_SMOOTH_SHORT, k) ; i < sub(SBA_DIRAC_NRG_SMOOTH_LONG + NB_DIV - 1, k); i++ )
+ {
+ smooth_long_avg[k][b] = L_add(smooth_long_avg[k][b], hStereoDft->smooth_buf_fx[b][i]);
+ move32();
+ }
+ smooth_short_avg[k][b] = Mpy_32_16_1(smooth_short_avg[k][b], (Word16)0x2AAB); /* 1/ 3 in Q15*/
+ move32();
+ smooth_long_avg[k][b] = Mpy_32_16_1(smooth_long_avg[k][b], (Word16)0x0CCD); /* 1/ 10 in Q15*/
+ move32();
+
+ /* calculate smoothing factor based on energy averages */
+ /* reduce factor for higher short-term energy */
+ hStereoDft->smooth_fac_fx[k][b] = extract_l(s_min( MAX_16, BASOP_Util_Divide3232_Scale(smooth_long_avg[k][b] , smooth_short_avg[k][b], &q_div) ));
+ move32();
+ IF (GT_16(q_div, 0))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ hStereoDft->smooth_fac_fx[k][b] = shl(hStereoDft->smooth_fac_fx[k][b], q_div);
+ q_div = 0;
+ }
+ /* map factor to range [0;1] */
+ hStereoDft->smooth_fac_fx[k][b] = extract_l(Mpy_32_16_1(SBA_DIRAC_NRG_SMOOTH_LONG_BY_LONG_SHORT_FX, s_max( 0, sub(hStereoDft->smooth_fac_fx[k][b] , SBA_DIRAC_NRG_SMOOTH_SHORT_BY_LONG_FX))));
+ move16();
+ /* compress factor (higher compression in lowest bands) */
+ IF ( LT_16(b, 2) )
+ {
+ hStereoDft->smooth_fac_fx[k][b] = Sqrt16(Sqrt16( hStereoDft->smooth_fac_fx[k][b], &q_sqrt), &q_sqrt);
+ move16();
+ }
+ ELSE
+ {
+ hStereoDft->smooth_fac_fx[k][b] = Sqrt16( hStereoDft->smooth_fac_fx[k][b], &q_sqrt );
+ move16();
+ }
+
+ /* apply upper bounds depending on band */
+ hStereoDft->smooth_fac_fx[0][b] = s_max( hStereoDft->min_smooth_gains_fx[b], s_min( hStereoDft->max_smooth_gains_fx[b], hStereoDft->smooth_fac_fx[0][b] ) );
+ move16();
+ hStereoDft->smooth_fac_fx[1][b] = s_max( hStereoDft->min_smooth_gains_fx[b], s_min( hStereoDft->max_smooth_gains_fx[b], hStereoDft->smooth_fac_fx[1][b] ) );
+ move16();
+ }
+ pDFT += STEREO_DFT32MS_N_MAX;
+ }
+
+ IF ( mcmasa )
+ {
+ /* calculate block energies for side gain weighting (combine angles of 2 DirAC blocks to side gain for 1 DFT Stereo subframe; 4 blocks and 2 subframes overall) */
+ pSynth = synth;
+ block_len = L_frame / nBlocks;
+ FOR ( block = 0; block < nBlocks; block++ )
+ {
+ block_nrg[block] = 0;
+ FOR ( i = 0; i < block_len; i++ )
+ {
+ block_nrg[block] = Madd_32_32(block_nrg[block], pSynth[i] , pSynth[i]);
+ move32();
+ }
+ block_nrg[block] = Sqrt32( block_nrg[block], 0);
+ move32();
+ pSynth += block_len;
+ }
+ nrg_norm1 = L_deposit_l(BASOP_Util_Divide3232_Scale(MAX_32, L_add(block_nrg[0] , L_add(block_nrg[1] , EPSILON_FIX) ), &q_div));
+ IF (NE_16(q_div, 0))
+ {
+ assert(0);
+ }
+ nrg_norm2 = L_deposit_l(BASOP_Util_Divide3232_Scale(MAX_32, L_add(block_nrg[2] , L_add(block_nrg[3] , EPSILON_FIX) ), &q_div));
+ IF (NE_16(q_div, 0))
+ {
+ assert(0);
+ }
+
+ /* extract DirAC parameters from metadata */
+ FOR ( b = 0; b < nbands; b++ )
+ {
+ diffuseness[b] = L_sub(MAX_32 , q_direction->band_data[b].energy_ratio_fx[0]);
+ move32();
+ IF ( hQMetaData->surcoh_band_data != NULL )
+ {
+ surrCoh[b] = L_shr(Mpy_32_16_1(hQMetaData->surcoh_band_data[b].surround_coherence[0], (Word16)0x0101), 1);
+ move32();
+ }
+ ELSE
+ {
+ surrCoh[b] = 0;
+ move32();
+ }
+
+ FOR ( block = 0; block < nBlocks; block++ )
+ {
+ Word16 block_metadata;
+
+ IF ( hQMetaData->useLowerRes )
+ {
+ block_metadata = 0;
+ move16();
+ }
+ ELSE
+ {
+ block_metadata = block;
+ move16();
+ }
+ IF ( LT_32(q_direction->band_data[b].azimuth_fx[block_metadata], 0) )
+ {
+ q_direction->band_data[b].azimuth_fx[block_metadata] = L_add(360, q_direction->band_data[b].azimuth_fx[block_metadata]);
+ move16();
+ }
+ azimuth[block][b] = (Word16)q_direction->band_data[b].azimuth_fx[block_metadata];
+ move16();
+ elevation[block][b] = (Word16)q_direction->band_data[b].elevation_fx[block_metadata];
+ move16();
+ }
+ }
+
+ /* map angles (azi, ele), surround coherence, and diffuseness to DFT Stereo side and prediction gains */
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ /* combine angles of first 2 blocks to side gain of first subframe */
+ side_gain[b] = 0;
+ move32();
+ FOR ( block = 0; block < nBlocks / 2; block++ )
+ {
+ IF ( EQ_16(b_wide_panning, 1) )
+ {
+ /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */
+ side_gain[b] = Madd_32_32(side_gain[b], nrg_norm1, Mpy_32_16_1(block_nrg[block] , get_panning( azimuth[block][b], elevation[block][b]) ));
+ move32();
+ }
+ ELSE
+ {
+ side_gain[b] = Madd_32_32(side_gain[b], nrg_norm1, Mpy_32_16_1(block_nrg[block] , mult(ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]])));
+ move32();
+ }
+ }
+
+ /* combine angles of last 2 blocks to side gain of second subframe */
+ side_gain[b + STEREO_DFT_BAND_MAX] = 0;
+ move32();
+ FOR ( block = nBlocks / 2; block < nBlocks; block++ )
+ {
+ IF ( EQ_16(b_wide_panning, 1) )
+ {
+ /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */
+ side_gain[b + STEREO_DFT_BAND_MAX] = Madd_32_32(side_gain[b + STEREO_DFT_BAND_MAX], nrg_norm2 , Mpy_32_16_1(block_nrg[block] , get_panning( azimuth[block][b], elevation[block][b])));
+ move32();
+ }
+ ELSE
+ {
+ side_gain[b + STEREO_DFT_BAND_MAX] = Madd_32_32(side_gain[b + STEREO_DFT_BAND_MAX], nrg_norm2 , Mpy_32_16_1(block_nrg[block] , mult( ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]])));
+ move32();
+ }
+ }
+
+ side_gain[b] = Mpy_32_32(side_gain[b], Sqrt32(L_sub((Word32)0x7FFFFFFF, diffuseness[b]), &q_sqrt));
+ move32();
+ IF (NE_16(q_sqrt, 0))
+ {
+ assert(0);
+ }
+ side_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_32(side_gain[b + STEREO_DFT_BAND_MAX], Sqrt32(L_sub((Word32)0x7FFFFFFF, diffuseness[b]), &q_sqrt));
+ move32();
+ IF (NE_16(q_sqrt, 0))
+ {
+ assert(0);
+ }
+ res_pred_gain[b] = Mpy_32_32(diffuseness[b], L_sub((Word32)0x7FFFFFFF, surrCoh[b] ));
+ move32();
+ res_pred_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_32(diffuseness[b], L_sub((Word32)0x7FFFFFFF, surrCoh[b]) );
+ move32();
+ }
+ }
+
+ hStereoDft->frame_nodata = 0;
+ move16();
+ hStereoDft->frame_sid_nodata = 0;
+ move16();
+ hStereoDft->frame_sid = 0;
+ move16();
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_compute_td_stefi_nrgs()
+ *
+ * Compute energies for TD stereo filling
+ *-------------------------------------------------------------------*/
+
+static void ivas_sba_dirac_stereo_compute_td_stefi_nrgs(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word32 hb_synth[L_FRAME48k], /* i : HB signal */
+ const Word16 core, /* i : core decision */
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 fd_cng_flag /* i : FD-CNG indicator */
+)
+{
+ Word16 i;
+ Word32 hb_nrg = EPSILON_FIX; move32();
+ Word32 hb_nrg2 = EPSILON_FIX; move32();
+
+ IF ( ( EQ_16(core, ACELP_CORE) && EQ_16(fd_cng_flag, 0) ) || EQ_16(hStereoDft->core_hist[1], ACELP_CORE) )
+ {
+ FOR ( i = 0; i < shr(output_frame, 2); i++ )
+ {
+ hb_nrg2 = Madd_32_32(hb_nrg2, hb_synth[i], hb_synth[i]);
+ }
+
+ hStereoDft->hb_nrg_subr_fx[0] = hb_nrg2;
+ move32();
+ hb_nrg = L_add(hb_nrg, hb_nrg2);
+ hb_nrg2 = EPSILON_FIX;
+ move32();
+
+ FOR ( ; i < output_frame; i++ )
+ {
+ hb_nrg2 = Madd_32_32(hb_nrg2, hb_synth[i], hb_synth[i]);
+ }
+
+ hStereoDft->hb_nrg_subr_fx[1] = hb_nrg2;
+ move32();
+ hb_nrg = L_add(hb_nrg, hb_nrg2);
+
+ Copy32( hb_synth, hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, output_frame );
+ }
+ ELSE
+ {
+ set_val_Word32( hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, 0, output_frame);
+ }
+ hStereoDft->hb_nrg_subr_fx[0] = (hStereoDft->hb_nrg_subr_fx[0] * shr(hStereoDft->NFFT, 1));
+ move32();
+ hStereoDft->hb_nrg_subr_fx[1] = (hStereoDft->hb_nrg_subr_fx[1] * shr(hStereoDft->NFFT, 1));
+ move32();
+ IF (LE_32(hStereoDft->hb_nrg_subr_fx[0] , 0) || LE_32(hStereoDft->hb_nrg_subr_fx[1] , 0))
+ {
+ assert(0);
+ }
+ hStereoDft->hb_nrg_fx[0] = hb_nrg;
+ move32();
+ hStereoDft->td_gain_fx[0] = 0;
+ move32();
+ hStereoDft->core_hist[0] = ( fd_cng_flag ) ? TCX_20_CORE : core; /* full signal available for DTX with FD-CNG, thus apply stereo filling on full spectrum like in TCX */
+ move16();
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_compute_hb_gain()
+ *
+ * Compute HB gains
+ *-------------------------------------------------------------------*/
+
+static void ivas_sba_dirac_stereo_compute_hb_gain(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ Word32 hb_gain[NB_DIV] /* o : side gains for HB signal */
+)
+{
+ Word16 k_offset;
+
+ k_offset = STEREO_DFT_OFFSET;
+ move16();
+
+ /* last band covers whole HB range, no averaging needed */
+ hb_gain[0] = hStereoDft->side_gain_fx[k_offset * STEREO_DFT_BAND_MAX + hStereoDft->nbands - 1];
+ move32();
+ hb_gain[1] = hStereoDft->side_gain_fx[( k_offset + 1 ) * STEREO_DFT_BAND_MAX + hStereoDft->nbands - 1];
+ move32();
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_upmix_hb()
+ *
+ * Apply panning to HB signal
+ *-------------------------------------------------------------------*/
+
+static void ivas_sba_dirac_stereo_upmix_hb(
+ Word32 hb_stereo_synth[CPE_CHANNELS][L_FRAME48k], /* i/o: stereo HB synthesis signal */
+ Word32 hb_synth[L_FRAME48k], /* i : HB signal */
+ Word32 hb_gain[NB_DIV], /* i : side gains for HB signal */
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 mcmasa, /* i : McMASA flag */
+ const Word16 sba_mono_flag, /* i : flag for mono output */
+ const Word16 bwidth, /* i : bandwidth of signal */
+ const STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i : Stereo DFT handle for mixing matrix */
+)
+{
+ Word16 i;
+ Word32 gp, gm;
+ Word32 gain_fac;
+
+ IF ( EQ_16(mcmasa, 0) )
+ {
+ gain_fac = ( bwidth == FB ) ? (Word32)0x20000000 : (Word32)0x2A3D70A4; /* last matrix element not used for SWB, divide by 3 instead of 4*/
+ IF ( sba_mono_flag )
+ {
+ gp = L_add(hStereoDft->mixer_mat_smooth_fx[0][0][8],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][9],
+ hStereoDft->mixer_mat_smooth_fx[0][0][10]));
+ IF ( EQ_16(bwidth, FB) )
+ {
+ gp = L_add(gp, hStereoDft->mixer_mat_smooth_fx[0][0][11]);
+ }
+ FOR ( i = 0; i < shr(output_frame, 1); i++ )
+ {
+ hb_stereo_synth[0][i] = Mpy_32_32(hb_synth[i] , Mpy_32_32( gain_fac , gp));
+ move32();
+ }
+ gp = L_add(hStereoDft->mixer_mat_smooth_fx[0][0][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][9 + IVAS_MAX_NUM_BANDS],
+ hStereoDft->mixer_mat_smooth_fx[0][0][10 + IVAS_MAX_NUM_BANDS]));
+ IF ( EQ_16(bwidth, FB) )
+ {
+ gp = L_add(gp, hStereoDft->mixer_mat_smooth_fx[0][0][11 + IVAS_MAX_NUM_BANDS]);
+ }
+ FOR ( i = shr(output_frame , 1); i < output_frame; i++ )
+ {
+ hb_stereo_synth[0][i] = Mpy_32_32(Mpy_32_32(hb_synth[i] , gain_fac), gp);
+ }
+ }
+ ELSE
+ {
+ gp = L_add(hStereoDft->mixer_mat_smooth_fx[0][0][8] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][0][8] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][9] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][0][9] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][10] ,
+ hStereoDft->mixer_mat_smooth_fx[1][0][10])))));
+ IF ( EQ_32(bwidth , FB) )
+ {
+ gp = L_add(gp, L_add(hStereoDft->mixer_mat_smooth_fx[0][0][11] , hStereoDft->mixer_mat_smooth_fx[1][0][11]));
+ }
+
+ gm = L_add(L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][8] , hStereoDft->mixer_mat_smooth_fx[1][0][8]) ,
+ L_add(L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][9] , hStereoDft->mixer_mat_smooth_fx[1][0][9]) ,
+ L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][10] , hStereoDft->mixer_mat_smooth_fx[1][0][10])));
+ IF ( EQ_32(bwidth , FB) )
+ {
+ gm = L_add(gm, L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][11] , hStereoDft->mixer_mat_smooth_fx[1][0][11]));
+ }
+
+ FOR ( i = 0; i < output_frame / 2; i++ )
+ {
+ hb_stereo_synth[0][i] = L_shr(Mpy_32_32(Mpy_32_32(hb_synth[i] , gain_fac) , gp), 1);
+ move32();
+ hb_stereo_synth[1][i] = L_shr(Mpy_32_32(Mpy_32_32(hb_synth[i] , gain_fac) , gm), 1);
+ move32();
+ }
+
+ gp = L_add(hStereoDft->mixer_mat_smooth_fx[0][0][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][0][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][0][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][0][10 + IVAS_MAX_NUM_BANDS],
+ hStereoDft->mixer_mat_smooth_fx[1][0][10 + IVAS_MAX_NUM_BANDS])))));
+ IF ( EQ_32(bwidth , FB) )
+ {
+ gp = L_add(gp, L_add(hStereoDft->mixer_mat_smooth_fx[0][0][11 + IVAS_MAX_NUM_BANDS] , hStereoDft->mixer_mat_smooth_fx[1][0][11 + IVAS_MAX_NUM_BANDS]));
+ }
+
+ gm = L_add(L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][8 + IVAS_MAX_NUM_BANDS] , hStereoDft->mixer_mat_smooth_fx[1][0][8 + IVAS_MAX_NUM_BANDS]),
+ L_add(L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][9 + IVAS_MAX_NUM_BANDS] , hStereoDft->mixer_mat_smooth_fx[1][0][9 + IVAS_MAX_NUM_BANDS]),
+ L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][10 + IVAS_MAX_NUM_BANDS] , hStereoDft->mixer_mat_smooth_fx[1][0][10 + IVAS_MAX_NUM_BANDS])));
+ IF ( EQ_32(bwidth , FB) )
+ {
+ gm = L_add(gm, L_sub(hStereoDft->mixer_mat_smooth_fx[0][0][11 + IVAS_MAX_NUM_BANDS] , hStereoDft->mixer_mat_smooth_fx[1][0][11 + IVAS_MAX_NUM_BANDS]));
+ }
+
+ FOR ( i = shr(output_frame , 1); i < output_frame; i++ )
+ {
+ hb_stereo_synth[0][i] = L_shr(Mpy_32_32(hb_synth[i] , Mpy_32_32(gain_fac , gp)), 1);
+ move32();
+ hb_stereo_synth[1][i] = L_shr(Mpy_32_32(hb_synth[i] , Mpy_32_32(gain_fac , gm)), 1);
+ move32();
+ }
+ }
+ }
+ ELSE
+ {
+ FOR ( i = 0; i < L_shr(output_frame , 1); i++ )
+ {
+ hb_stereo_synth[0][i] = L_add(L_shr(hb_synth[i], 1) , L_shr(Mpy_32_32(hb_gain[0] , hb_synth[i]), 1));
+ move32();
+ hb_stereo_synth[1][i] = L_sub(L_shr(hb_synth[i], 1) , L_shr(Mpy_32_32(hb_gain[0] , hb_synth[i]), 1));
+ move32();
+ }
+
+ FOR ( i = shr(output_frame, 1); i < output_frame; i++ )
+ {
+ hb_stereo_synth[0][i] = L_add(L_shr(hb_synth[i], 1) , L_shr(Mpy_32_32(hb_gain[1] , hb_synth[i]), 1));
+ move32();
+ hb_stereo_synth[1][i] = L_sub(L_shr(hb_synth[i], 1) , L_shr(Mpy_32_32(hb_gain[1] , hb_synth[i]), 1));
+ move32();
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_apply_td_stefi()
+ *
+ * Apply TD stereo filling for ACELP HB
+ *-------------------------------------------------------------------*/
+
+static void ivas_sba_dirac_stereo_apply_td_stefi(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ Word32 *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 spar_flag /* i : SPAR flag */
+)
+{
+ Word16 i;
+ Word16 dftOvlLen;
+ Word16 win_in, win_out;
+ Word32 tmp;
+ const Word16 *win_dft;
+
+ IF ( spar_flag )
+ {
+ win_dft = hStereoDft->win32ms_fx;
+ dftOvlLen = hStereoDft->dft32ms_ovl;
+
+ Word32 g_W_1, g_Y_1;
+ Word32 g_W_2, g_Y_2;
+ Word32 g_L, g_R;
+ Word32 stefi_L, stefi_R;
+
+ g_W_1 = L_add(hStereoDft->mixer_mat_smooth_fx[0][1][8],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][8] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][3][8] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][1][9] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][9],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][3][9],
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][1][10],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][10],
+ hStereoDft->mixer_mat_smooth_fx[0][3][10])
+ )))))));
+
+ g_Y_1 = L_add( hStereoDft->mixer_mat_smooth_fx[1][1][8],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][8],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][3][8],
+ L_add( hStereoDft->mixer_mat_smooth_fx[1][1][9],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][9],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][3][9],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][1][10],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][10],
+ hStereoDft->mixer_mat_smooth_fx[1][3][10])
+ )))))));
+
+ g_W_2 = L_add(hStereoDft->mixer_mat_smooth_fx[0][1][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][3][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][1][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][3][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][1][10 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][10 + IVAS_MAX_NUM_BANDS],
+ hStereoDft->mixer_mat_smooth_fx[0][3][10 + IVAS_MAX_NUM_BANDS])
+ )))))));
+
+ g_Y_2 = L_add(hStereoDft->mixer_mat_smooth_fx[1][1][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][3][8 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][1][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][3][9 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][1][10 + IVAS_MAX_NUM_BANDS],
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][10 + IVAS_MAX_NUM_BANDS],
+ hStereoDft->mixer_mat_smooth_fx[1][3][10 + IVAS_MAX_NUM_BANDS])
+ )))))));
+
+ g_L = Mpy_32_16_1(L_sub( L_add(g_W_1 , g_W_2) , L_add(g_Y_1 , g_Y_2) ), 0x147B); /* 0x147B = 0.16 in Q15 */
+ g_R = Mpy_32_16_1(L_add( L_add(g_W_1 , g_W_2) , L_add(g_Y_1 , g_Y_2) ), 0x147B); /* 0x147B = 0.16 in Q15 */
+
+ FOR ( i = 0; i < dftOvlLen; i++ )
+ {
+ win_in = mult_r(win_dft[STEREO_DFT32MS_STEP * i], win_dft[STEREO_DFT32MS_STEP * i]);
+ win_out = sub(MAX_16, win_in);
+
+ stefi_L = L_shr(Mpy_32_32( Madd_32_16(Mpy_32_32(win_out , hStereoDft->g_L_prev_fx) , g_L , win_in ) , hStereoDft->hb_stefi_sig_fx[i]), 1);
+ stefi_R = L_shr(Mpy_32_32( Madd_32_16(Mpy_32_32(win_out , hStereoDft->g_R_prev_fx) , g_R , win_in ) , hStereoDft->hb_stefi_sig_fx[i]), 1);
+
+ output[0][i] = L_add(output[0][i], stefi_L);
+ move32();
+ output[1][i] = L_add(output[1][i], stefi_R);
+ move32();
+ }
+ FOR ( i = dftOvlLen; i < output_frame; i++ )
+ {
+
+ stefi_L = L_shr(Mpy_32_32(g_L , hStereoDft->hb_stefi_sig_fx[i]), 1);
+ stefi_R = L_shr(Mpy_32_32(g_R , hStereoDft->hb_stefi_sig_fx[i]), 1);
+
+ output[0][i] = L_add(output[0][i], stefi_L);
+ move32();
+ output[1][i] = L_add(output[1][i], stefi_R);
+ move32();
+ }
+ hStereoDft->g_L_prev_fx = g_L;
+ move32();
+ hStereoDft->g_R_prev_fx = g_R;
+ move32();
+ }
+ ELSE IF ( L_max( hStereoDft->td_gain_fx[0], hStereoDft->td_gain_fx[1] ) > 0 )
+ {
+ win_dft = hStereoDft->win32ms_fx;
+ dftOvlLen = hStereoDft->dft32ms_ovl;
+
+ FOR ( i = 0; i < dftOvlLen; i++ )
+ {
+ win_in = mult(win_dft[STEREO_DFT32MS_STEP * i] , win_dft[STEREO_DFT32MS_STEP * i]);
+ win_out = sub(MAX_16 , win_in);
+ tmp = L_shr(Mpy_32_32(Madd_32_16(Mpy_32_16_1(hStereoDft->td_gain_fx[0], win_in) , hStereoDft->td_gain_fx[1] , win_out) , hStereoDft->hb_stefi_sig_fx[i]), 1);
+
+ output[0][i] = L_add(output[0][i], tmp);
+ move32();
+ output[1][i] = L_sub(output[1][i], tmp);
+ move32();
+ }
+ FOR ( i = dftOvlLen; i < output_frame; i++ )
+ {
+ tmp = L_shr(hStereoDft->td_gain_fx[0] * hStereoDft->hb_stefi_sig_fx[i], 1);
+ output[0][i] = L_add(output[0][i], tmp);
+ move32();
+ output[1][i] = L_sub(output[1][i], tmp);
+ move32();
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_smooth_parameters_fx()
+ *
+ * Smooth DFT Stereo parameters
+ *-------------------------------------------------------------------*/
+
+void ivas_sba_dirac_stereo_smooth_parameters_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ ivas_spar_md_dec_state_t *hMdDec, /* i/o: SPAR MD handle for upmixing */
+ const Word16 cross_fade_start_offset, /* i : SPAR mixer delay compensation */
+ const Word32 output_Fs, /* i : Fs for delay calculation */
+ const Word16 num_md_sub_frames /* i : number of subframes in mixing matrix */
+)
+{
+ Word16 i, j, k, i_sf;
+ Word16 b;
+ Word16 k_offset;
+ Word32 *side_gain, *prev_side_gain;
+ Word32 *res_pred_gain, *prev_res_pred_gain;
+
+ k_offset = STEREO_DFT_OFFSET;
+ move16();
+ prev_side_gain = hStereoDft->side_gain_fx;
+ side_gain = hStereoDft->side_gain_fx + k_offset * STEREO_DFT_BAND_MAX;
+ prev_res_pred_gain = hStereoDft->res_pred_gain_fx;
+ res_pred_gain = hStereoDft->res_pred_gain_fx + k_offset * STEREO_DFT_BAND_MAX;
+
+ IF ( !hMdDec )
+ {
+ /* Smoothing of side and prediction gains between ftrames */
+ FOR ( b = hStereoDft->res_pred_band_min; b < hStereoDft->nbands; b++ )
+ {
+ IF ( hStereoDft->attackPresent )
+ {
+ res_pred_gain[b] = Mpy_32_16_1(res_pred_gain[b], (Word16)0x6666);
+ move32();
+ res_pred_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_16_1(res_pred_gain[b + STEREO_DFT_BAND_MAX], (Word16)0x6666);
+ move32();
+ }
+ ELSE
+ {
+ side_gain[b] = Madd_32_16(Mpy_32_16_1(prev_side_gain[b], hStereoDft->smooth_fac_fx[0][b]),
+ side_gain[b], sub((Word16)0x7FFF, hStereoDft->smooth_fac_fx[0][b]));
+ move32();
+ side_gain[b + STEREO_DFT_BAND_MAX] = Madd_32_16(Mpy_32_16_1(side_gain[b], hStereoDft->smooth_fac_fx[1][b]),
+ side_gain[b + STEREO_DFT_BAND_MAX],
+ sub((Word16)0x7FFF, hStereoDft->smooth_fac_fx[1][b]));
+ move32();
+ res_pred_gain[b] = Madd_32_16(Mpy_32_16_1(prev_res_pred_gain[b], hStereoDft->smooth_fac_fx[0][b]),
+ res_pred_gain[b],
+ sub((Word16)0x7FFF, hStereoDft->smooth_fac_fx[0][b]));
+ move32();
+ res_pred_gain[b + STEREO_DFT_BAND_MAX] = Madd_32_16(Mpy_32_16_1(res_pred_gain[b], hStereoDft->smooth_fac_fx[1][b]),
+ res_pred_gain[b + STEREO_DFT_BAND_MAX],
+ sub((Word16)0x7FFF, hStereoDft->smooth_fac_fx[1][b] ));
+ move32();
+ }
+ }
+ }
+
+ IF ( hMdDec != 0 )
+ {
+ Word64 xfade_start_ns;
+ Word16 xfade_delay_subframes;
+ Word16 i_hist;
+ Word16 md_sf;
+
+ xfade_start_ns = W_sub(W_mult_32_32((Word32)cross_fade_start_offset, 1000000000), W_mult_32_32(IVAS_FB_ENC_DELAY_NS, output_Fs));
+ xfade_delay_subframes = (Word16) ( xfade_start_ns / W_mult_32_32(( FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ), output_Fs) );
+ move16();
+ i_hist = 4 - xfade_delay_subframes;
+ move16();
+ FOR ( k = 0; k < 2; k++ )
+ {
+ FOR ( i_sf = k * 2; i_sf < ( k + 1 ) * 2; i_sf++ )
+ {
+ md_sf = (Word16)(EQ_16( num_md_sub_frames, MAX_PARAM_SPATIAL_SUBFRAMES ) ? i_sf : 0);
+ IF ( hStereoDft->first_frame )
+ {
+ FOR ( i = 0; i < 2; i++ )
+ {
+ FOR ( j = 0; j < 4; j++ )
+ {
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ hStereoDft->mixer_mat_smooth_fx[i][j][b + k * IVAS_MAX_NUM_BANDS] = hMdDec->mixer_mat_fx[i][j][b];
+ move32();
+ }
+ FOR ( ; b < IVAS_MAX_NUM_BANDS; b++ )
+ {
+ hStereoDft->mixer_mat_smooth_fx[i][j][b + k * IVAS_MAX_NUM_BANDS] = 0;
+ move32();
+ }
+ }
+ }
+ }
+ ELSE
+ {
+ FOR ( i = 0; i < 2; i++ )
+ {
+ FOR ( j = 0; j < 4; j++ )
+ {
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ Word16 beta = hStereoDft->smooth_fac_fx[k][b];
+ move16();
+ hStereoDft->mixer_mat_smooth_fx[i][j][b + k * IVAS_MAX_NUM_BANDS] =
+ Madd_32_16(Mpy_32_16_1(hStereoDft->mixer_mat_smooth_fx[i][j][b + k * IVAS_MAX_NUM_BANDS], beta),
+ hMdDec->mixer_mat_prev_fx[i_hist][i][j][b], sub((Word16)0x7FFF, beta));
+ move32();
+ }
+ }
+ }
+ }
+
+ Copy32( hMdDec->mixer_mat_prev_fx[1][0][0], hMdDec->mixer_mat_prev_fx[0][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS );
+ Copy32( hMdDec->mixer_mat_prev_fx[2][0][0], hMdDec->mixer_mat_prev_fx[1][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS );
+ Copy32( hMdDec->mixer_mat_prev_fx[3][0][0], hMdDec->mixer_mat_prev_fx[2][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS );
+ Copy32( hMdDec->mixer_mat_prev_fx[4][0][0], hMdDec->mixer_mat_prev_fx[3][0][0], IVAS_MAX_FB_MIXER_OUT_CH * IVAS_MAX_SPAR_FB_MIXER_IN_CH * IVAS_MAX_NUM_BANDS );
+
+ FOR ( i = 0; i < 2; i++ )
+ {
+ FOR ( j = 0; j < 4; j++ )
+ {
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ hMdDec->mixer_mat_prev_fx[4][i][j][b] = hMdDec->mixer_mat_fx[i][j][b + md_sf * IVAS_MAX_NUM_BANDS];
+ move32();
+ }
+ }
+ }
+ }
+ }
+
+ hStereoDft->first_frame = 0;
+ move16();
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ivas_sba_dirac_stereo_dec_fx()
+ *
+ * Create stereo output for SBA DirAC via DFT stereo
+ *-------------------------------------------------------------------*/
+
+void ivas_sba_dirac_stereo_dec_fx(
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ Word32 *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 mcmasa /* i : McMASA flag */
+)
+{
+ Word16 dtx_flag, fd_cng_flag;
+ Word16 sba_mono_flag;
+ Word16 memOffset;
+ Word32 tmp_buf[NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )];
+ Word32 tmp_synth[L_FRAME16k];
+ Word32 hb_gain[NB_DIV];
+ Word32 hb_synth_stereo[CPE_CHANNELS][L_FRAME48k];
+ Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX];
+ Word16 q_dft = 0;
+ Word16 q = 0;
+ SCE_DEC_HANDLE hSCE;
+ CPE_DEC_HANDLE hCPE;
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft;
+
+ hSCE = st_ivas->hSCE[0];
+ hCPE = st_ivas->hCPE[0];
+ hStereoDft = hCPE->hStereoDft;
+ q = hCPE->hStereoDft->q_dft;
+
+ IF ( GT_16(st_ivas->nchan_transport, 1) && EQ_16(mcmasa, 0) )
+ {
+ dtx_flag = 0;
+ move16();
+ fd_cng_flag = 0;
+ move16();
+ }
+ ELSE
+ {
+ dtx_flag = (Word16)LE_32(hSCE->hCoreCoder[0]->core_brate, SID_2k40);
+ fd_cng_flag = ( dtx_flag && EQ_16(hSCE->hCoreCoder[0]->cng_type, FD_CNG) );
+ }
+ sba_mono_flag = (Word16)EQ_16(st_ivas->hDecoderConfig->nchan_out, 1);
+
+ memOffset = NS2SA( L_mult0(output_frame, FRAMES_PER_SEC), L_sub(IVAS_DEC_DELAY_NS, DELAY_BWE_TOTAL_NS) );
+
+ ivas_sba_dirac_stereo_config( hStereoDft->hConfig );
+ hStereoDft->nbands = ivas_sba_dirac_stereo_band_config( hStereoDft->band_limits, st_ivas->hDecoderConfig->output_Fs, hStereoDft->NFFT, ( ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT ) && !mcmasa ) );
+ stereo_dft_dec_update_fx( hStereoDft, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
+ IF ( GT_16(st_ivas->nchan_transport, 1) )
+ {
+ stereo_dft_dec_analyze_fx( hCPE, output[0], DFT, 0, output_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0, &q, &q_dft );
+ stereo_dft_dec_analyze_fx( hCPE, output[1], DFT, 1, output_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0, &q, &q_dft );
+ hStereoDft->core_hist[0] = hCPE->hCoreCoder[0]->core;
+ move16();
+ }
+ ELSE
+ {
+ /* nrg calculation for TD Stereo Filling, as done in ICBWE which is not used in this case */
+ ivas_sba_dirac_stereo_compute_td_stefi_nrgs( hStereoDft, hSCE->save_hb_synth_fx, hSCE->hCoreCoder[0]->core, output_frame, fd_cng_flag );
+
+ /* do DFT Stereo core switching (including DFT analysis) here as CPE element was not available in SCE decoder */
+ Copy32( hSCE->save_synth_fx, tmp_synth, hSCE->hCoreCoder[0]->L_frame );
+ stereo_dft_dec_core_switching_fx( hCPE, output[0] /*hSCE->save_output*/, hSCE->save_synth_fx, hSCE->save_hb_synth_fx, DFT, output_frame, 0, dtx_flag, &q, &q_dft );
+
+ /* do updates here after skipping this in SCE decoder (needs to be done after core switching) */
+ ivas_updt_dec_common_fx( hSCE->hCoreCoder[0], NORMAL_HQ_CORE, -1, hSCE->save_synth_fx, q);
+ }
+
+ /* mapping of DirAC parameters (azimuth, elevation, diffuseness) to DFT Stereo parameters (side gain, prediction gain) */
+ map_params_dirac_to_stereo( hStereoDft, st_ivas->hQMetaData, tmp_synth, DFT[0], st_ivas->ivas_format == MC_FORMAT,
+ ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa ) ? hSCE->hCoreCoder[0]->L_frame : output_frame,
+ ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa ), q_dft );
+
+ IF ( (EQ_32( st_ivas->ivas_format , SBA_FORMAT) || EQ_32(st_ivas->ivas_format , SBA_ISM_FORMAT) ) && !mcmasa )
+ {
+ set_val_Word32( hStereoDft->res_pred_gain_fx, MAX_32, 3 * STEREO_DFT_BAND_MAX );
+ }
+
+ /* DFT Stereo upmix */
+ stereo_dft_dec_fx( hStereoDft, hCPE->hCoreCoder[0], DFT, NULL, NULL, 1 /*st_ivas->sba_dirac_stereo_flag*/, sba_mono_flag, ( st_ivas->hSpar != NULL && !mcmasa ) ? st_ivas->hSpar->hMdDec : NULL, ( st_ivas->hSpar != NULL && !mcmasa ) ? st_ivas->hSpar->hFbMixer->cross_fade_start_offset : 0,
+ st_ivas->hDecoderConfig->output_Fs, st_ivas->nchan_transport, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) );
+
+ /* DFT synthesis */
+ stereo_dft_dec_synthesize_fx( hCPE, DFT, 0, output[0], output_frame );
+ IF ( EQ_16(sba_mono_flag, 0) )
+ {
+ stereo_dft_dec_synthesize_fx( hCPE, DFT, 1, output[1], output_frame );
+ }
+
+ synchro_synthesis_fx( st_ivas->hDecoderConfig->ivas_total_brate, hCPE, output, output_frame, 1 /*st_ivas->sba_dirac_stereo_flag*/ );
+
+ /* output scaling */
+ IF ( EQ_16(sba_mono_flag, 0) )
+ {
+ v_shr( output[0], 1, output[0], output_frame );
+ v_shr( output[1], 1, output[1], output_frame );
+ }
+
+ /* delay HB synth */
+ IF ( EQ_16(st_ivas->nchan_transport, 1) )
+ {
+ Copy32( hSCE->save_hb_synth_fx + output_frame - memOffset, tmp_buf, memOffset );
+ Copy32( hSCE->save_hb_synth_fx, hSCE->save_hb_synth_fx + memOffset, output_frame - memOffset );
+ Copy32( hSCE->prev_hb_synth_fx, hSCE->save_hb_synth_fx, memOffset );
+ Copy32( tmp_buf, hSCE->prev_hb_synth_fx, memOffset );
+ }
+
+ IF ( (EQ_16( hCPE->hCoreCoder[0]->core, ACELP_CORE) || EQ_16(hCPE->hCoreCoder[0]->last_core, ACELP_CORE)) && EQ_16(fd_cng_flag, 0) && EQ_16(st_ivas->nchan_transport, 1) )
+ {
+ /* upmix ACELP BWE */
+ ivas_sba_dirac_stereo_compute_hb_gain( hStereoDft, hb_gain );
+
+ ivas_sba_dirac_stereo_upmix_hb( hb_synth_stereo, hSCE->save_hb_synth_fx, hb_gain, output_frame, ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa ), sba_mono_flag, hSCE->hCoreCoder[0]->bwidth, hStereoDft );
+
+ /* add HB to ACELP core */
+ v_add_fx( output[0], hb_synth_stereo[0], output[0], output_frame );
+ IF ( EQ_16(sba_mono_flag, 0) )
+ {
+ v_add_fx( output[1], hb_synth_stereo[1], output[1], output_frame );
+
+ /* apply TD Stereo Filling as is done in ICBWE */
+ ivas_sba_dirac_stereo_apply_td_stefi( hStereoDft, output, output_frame, ( ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT ) && !mcmasa ) );
+ }
+ }
+
+ /* reset the other channels to 0 (they are not used since here) */
+ FOR ( Word16 ch = CPE_CHANNELS; ch < st_ivas->nchan_transport; ch++ )
+ {
+ set_val_Word32( output[ch], 0, output_frame );
+ }
+
+ return;
+}
+#endif
\ No newline at end of file
diff --git a/lib_dec/ivas_sce_dec_fx.c b/lib_dec/ivas_sce_dec_fx.c
index de8f53f097ae25905887a928070b93b411fa8f4a..d89aab4cfe66c2e3a34c9a6e3f4eb733e2d5faba 100644
--- a/lib_dec/ivas_sce_dec_fx.c
+++ b/lib_dec/ivas_sce_dec_fx.c
@@ -414,6 +414,7 @@ ivas_error create_sce_dec(
#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED
IF( st_ivas->sba_dirac_stereo_flag )
{
+
IF( ( hSCE->save_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) );
@@ -425,11 +426,28 @@ ivas_error create_sce_dec(
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) );
}
set_zero( hSCE->save_hb_synth, output_frame );
+#ifdef IVAS_FLOAT_FIXED
+ IF( ( hSCE->save_synth_fx = (Word32 *) malloc( sizeof( *(hSCE->save_synth_fx) ) * output_frame ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) );
+ }
+ set_zero( hSCE->save_synth_fx, output_frame );
+
+ IF( ( hSCE->save_hb_synth_fx = (Word32 *) malloc( sizeof( *(hSCE->save_hb_synth_fx) ) * output_frame ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) );
+ }
+ set_zero( hSCE->save_hb_synth_fx, output_frame );
+#endif
}
ELSE
{
hSCE->save_synth = NULL;
hSCE->save_hb_synth = NULL;
+#ifdef IVAS_FLOAT_FIXED
+ hSCE->save_synth_fx = NULL;
+ hSCE->save_hb_synth_fx = NULL;
+#endif
}
#else
IF( st_ivas->sba_dirac_stereo_flag )
diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h
index f8d4f0ac67cfb92db31747040bf8a849f9604440..663ec1c721ed21c7a3d016a7227716bef0d85cc3 100644
--- a/lib_dec/ivas_stat_dec.h
+++ b/lib_dec/ivas_stat_dec.h
@@ -93,6 +93,7 @@ typedef struct stereo_dft_dec_data_struct
int16_t dft_trigo_step;
#ifdef IVAS_FLOAT_FIXED
+ Word32 ONE_NFFT; /* Size of DFT */
const Word16 *dft_trigo_fx;
const Word16 *dft_trigo_12k8_fx;
const Word16 *dft_trigo_16k_fx;
@@ -122,6 +123,7 @@ typedef struct stereo_dft_dec_data_struct
const Word16 *win232ms_12k8_fx; /* DFT window */
const Word16 *win232ms_16k_fx; /* DFT window */
const Word16 *win232ms_8k_fx; /* DFT window */
+ const Word16 *win_8k_fx; /* DFT window residual */
#endif
const float *win_8k; /* DFT window residual */
@@ -145,11 +147,16 @@ typedef struct stereo_dft_dec_data_struct
int16_t side_gain_index[STEREO_DFT_BAND_MAX];
float gipd[STEREO_DFT_DEC_DFT_NB];
+#ifdef IVAS_FLOAT_FIXED
+ Word32 gipd_fx[STEREO_DFT_DEC_DFT_NB];
+#endif
int16_t no_ipd_flag; /* flag to indicate when no IPD gets used */
float itd[STEREO_DFT_DEC_DFT_NB];
+#if 0
#ifdef IVAS_FLOAT_FIXED
Word16 itd_fx[STEREO_DFT_DEC_DFT_NB];
+#endif
#endif
float itd_xfade_step;
@@ -165,6 +172,18 @@ typedef struct stereo_dft_dec_data_struct
/*residual prediction*/
int16_t res_pred_mode[STEREO_DFT_DEC_DFT_NB]; /* residual prediction mode: 0(off), 1(stereo filling only), 2(enhanced stereo filling) */
float res_pred_gain[STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX]; /* prediction gain for the residual HFs */
+#ifdef IVAS_FLOAT_FIXED
+ Word32 itd_fx[STEREO_DFT_DEC_DFT_NB];
+
+ Word32 itd_xfade_step_fx;
+ Word32 itd_xfade_target_fx;
+ Word32 itd_xfade_prev_fx;
+
+ Word32 ipd_xfade_target_fx;
+ Word32 ipd_xfade_step_fx;
+ Word32 ipd_xfade_prev_fx;
+ Word32 res_pred_gain_fx[STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX]; /* prediction gain for the residual HFs */
+#endif
int16_t res_pred_band_min; /* Band min for prediction of residual */
float DFT_past_DMX[STEREO_DFT_PAST_MAX][STEREO_DFT32MS_N_32k]; /* Past DMX for residual prediction */
int16_t past_DMX_pos;
@@ -186,13 +205,21 @@ typedef struct stereo_dft_dec_data_struct
float bpf_error_signal_last;
float bpf_error_ratio_mem;
#ifdef IVAS_FLOAT_FIXED
+ Word32 DFT_past_DMX_fx[STEREO_DFT_PAST_MAX][STEREO_DFT32MS_N_32k]; /* Past DMX for residual prediction */
+ Word32 past_res_pred_gain_fx[STEREO_DFT_PAST_MAX][STEREO_DFT_BAND_MAX];
+ Word32 res_gains_ind_fx[2][2 * STEREO_DFT_BAND_MAX];
Word32 res_hb_nrg_mem_fx;
Word32 bpf_error_signal_last_fx;
Word16 bpf_error_ratio_mem_fx;
+ Word16 q_dft;
+ Word16 q_past_dft;
+ Word16 q_ip_mem;
+ Word16 q_smoothed_nrg;
#endif // IVAS_FLOAT_FIXED
float res_cod_mem[STEREO_DFT_OVL_8k];
float buff_LBTCX_mem[NS2SA( 16000, STEREO_DFT32MS_OVL_NS )];
#ifdef IVAS_FLOAT_FIXED
+ Word32 res_cod_mem_fx[STEREO_DFT_OVL_8k];
Word32 buff_LBTCX_mem_fx[NS2SA( 16000, STEREO_DFT32MS_OVL_NS )];
#endif
@@ -215,6 +242,13 @@ typedef struct stereo_dft_dec_data_struct
float ap_delay_mem[NS2SA( 16000, DELAY_BWE_TOTAL_NS )];
float ap_fade_mem[STEREO_DFT_ALLPASS_FADELEN_16k];
#ifdef IVAS_FLOAT_FIXED
+ Word32 stab_fac_smooth_res_fx; /* low-pass filtered stability factor */
+ Word32 lt_pred_gain_fx;
+ Word32 lt_pred_gain_variation_fx;
+ Word32 lt_var_mean_ratio_fx;
+ Word16 stefi_short_gain_fx;
+ Word16 stefi_long_gain_fx;
+ Word16 q_lt_pred_gain;
Word32 ap_delay_mem_fx[NS2SA( 16000, DELAY_BWE_TOTAL_NS )];
Word32 ap_fade_mem_fx[STEREO_DFT_ALLPASS_FADELEN_16k];
#endif
@@ -229,6 +263,8 @@ typedef struct stereo_dft_dec_data_struct
float hb_nrg_subr[STEREO_DFT_NBDIV];
float td_gain[STEREO_DFT_CORE_HIST_MAX];
#ifdef IVAS_FLOAT_FIXED
+ Word32 smooth_dmx_nrg_fx[STEREO_DFT_BAND_MAX];
+ Word32 smooth_res_nrg_fx[STEREO_DFT_BAND_MAX];
Word32 td_gain_fx[STEREO_DFT_CORE_HIST_MAX];
#endif
@@ -239,10 +275,14 @@ typedef struct stereo_dft_dec_data_struct
Word16 Q_nrg_subr;
Word16 prev_Q_stefi_sig;
+ Word32 q_td_gain[STEREO_DFT_CORE_HIST_MAX];
#endif
/* stereo DTX */
float g_state[STEREO_DFT_BAND_MAX];
+#ifdef IVAS_FLOAT_FIXED
+ Word16 g_state_fx[STEREO_DFT_BAND_MAX];
+#endif
int16_t frame_sid_nodata;
int16_t frame_nodata;
int16_t frame_sid;
@@ -259,12 +299,30 @@ typedef struct stereo_dft_dec_data_struct
float smooth_buf[SBA_DIRAC_STEREO_NUM_BANDS][SBA_DIRAC_NRG_SMOOTH_LONG + 1];
float smooth_fac[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS];
+#ifdef IVAS_FLOAT_FIXED
+ /* PLC on residual signal */
+ Word32 sg_mean_fx;
+ Word32 res_mem_fx[STEREO_DFT_RES_BW_MAX];
+ Word32 past_dmx_nrg_fx;
+ Word32 smooth_buf_fx[SBA_DIRAC_STEREO_NUM_BANDS][SBA_DIRAC_NRG_SMOOTH_LONG + 1];
+ Word16 smooth_fac_fx[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS];
+ Word16 q_hb_nrg;
+ Word16 q_hb_nrg_subr;
+#endif
int16_t first_frame;
float mixer_mat_smooth[2][4][2 * IVAS_MAX_NUM_BANDS];
+#ifdef IVAS_FLOAT_FIXED
+ Word32 mixer_mat_smooth_fx[2][4][2 * IVAS_MAX_NUM_BANDS];
+#endif
float g_L_prev;
float g_R_prev;
const float *max_smooth_gains, *min_smooth_gains;
+#ifdef IVAS_FLOAT_FIXED
+ Word32 g_L_prev_fx;
+ Word32 g_R_prev_fx;
+ const Word16 *max_smooth_gains_fx, *min_smooth_gains_fx;
+#endif
} STEREO_DFT_DEC_DATA, *STEREO_DFT_DEC_DATA_HANDLE;
@@ -296,6 +354,9 @@ typedef struct stereo_dec_cng
{
float coh[STEREO_DFT_BAND_MAX + 1]; /* coherence */
float cm[STEREO_DFT_BAND_MAX]; /* cm */
+#ifdef IVAS_FLOAT_FIXED
+ Word16 cm_fx[STEREO_DFT_BAND_MAX]; /* cm */
+#endif
int16_t first_SID; /* first SID indicator */
int16_t first_SID_after_TD; /* first SID after TD-stereo indicator */
int16_t prev_sid_nodata; /* previous frame SID/FRAME_NO_DATA indicator */
diff --git a/lib_dec/ivas_stereo_dft_dec.c b/lib_dec/ivas_stereo_dft_dec.c
index 7be18cb84b96912f96fb6e4cc03a850ab5ea41c7..2e0a6376d256c8544cd1b8968a38ecc89430c526 100644
--- a/lib_dec/ivas_stereo_dft_dec.c
+++ b/lib_dec/ivas_stereo_dft_dec.c
@@ -56,6 +56,9 @@
#define STEFI_DELAY_IND( d, buf_ind ) ( ( buf_ind ) + STEREO_DFT_PAST_MAX - ( d ) + 1 ) % STEREO_DFT_PAST_MAX
#define STEREO_DFT_RES_RATIO_LIMIT 0.18f
+#ifdef IVAS_FLOAT_FIXED
+#define STEREO_DFT_RES_RATIO_LIMIT_FX (Word32)(0x170A3D71)
+#endif
#define STEREO_DFT_LT_PREDGAIN_UPD 0.1f
#define STEREO_DFT_VR_PREDGAIN_UPD 0.1f
#define STEREO_DFT_STEFFI_PG_THRESHOLD 0.6f
@@ -329,6 +332,23 @@ static void stereo_dft_dec_open(
hStereoDft->dft_trigo_12k8 = dft_trigo_12k8;
hStereoDft->dft_trigo_16k = dft_trigo_32k;
#ifdef IVAS_FLOAT_FIXED
+ switch (output_Fs)
+ {
+ case 48000:
+ hStereoDft->ONE_NFFT = (Word32) ( 0x00222222 );
+ BREAK;
+ case 32000:
+ hStereoDft->ONE_NFFT = (Word32) ( 0x00333333 );
+ BREAK;
+ case 16000:
+ hStereoDft->ONE_NFFT = (Word32) ( 0x00666666 );
+ BREAK;
+ case 8000:
+ hStereoDft->ONE_NFFT = (Word32) ( 0x00CCCCCC );
+ BREAK;
+ default:
+ assert(0);
+ }
hStereoDft->dft_trigo_8k_fx = dft_trigo_32k_fx;
hStereoDft->dft_trigo_12k8_fx = dft_trigo_12k8_fx;
hStereoDft->dft_trigo_16k_fx = dft_trigo_32k_fx;
@@ -421,6 +441,19 @@ static void stereo_dft_dec_open(
hStereoDft->max_smooth_gains = max_smooth_gains1;
}
+#ifdef IVAS_FLOAT_FIXED
+ if ( nchan_transport > 2 )
+ {
+ hStereoDft->min_smooth_gains_fx = min_smooth_gains2_fx;
+ hStereoDft->max_smooth_gains_fx = max_smooth_gains2_fx;
+ }
+ else
+ {
+ hStereoDft->min_smooth_gains_fx = min_smooth_gains1_fx;
+ hStereoDft->max_smooth_gains_fx = max_smooth_gains1_fx;
+ }
+#endif
+
/* reset DFT stereo memories */
stereo_dft_dec_reset( hStereoDft );
@@ -456,6 +489,14 @@ void stereo_dft_dec_reset(
set_zero( hStereoDft->past_res_pred_gain[i], STEREO_DFT_BAND_MAX );
}
+#ifdef IVAS_FLOAT_FIXED
+ FOR ( i = 0; i < STEREO_DFT_PAST_MAX; i++ )
+ {
+ set_val_Word32( hStereoDft->DFT_past_DMX_fx[i], 0, STEREO_DFT32MS_N_32k );
+ set_val_Word32( hStereoDft->past_res_pred_gain_fx[i], 0, STEREO_DFT_BAND_MAX );
+ }
+#endif
+
hStereoDft->past_DMX_pos = 0;
set_s( hStereoDft->res_pred_index_previous, 0, STEREO_DFT_BAND_MAX );
@@ -467,10 +508,22 @@ void stereo_dft_dec_reset(
set_zero( hStereoDft->res_gains_ind[1], STEREO_DFT_BAND_MAX );
+#ifdef IVAS_FLOAT_FIXED
+ FOR ( i = 0; i < STEREO_DFT_BAND_MAX; i++ )
+ {
+ hStereoDft->res_gains_ind_fx[0][i] = L_shl(15, Q26);
+ }
+
+ set_val_Word32( hStereoDft->res_gains_ind_fx[1], 0, STEREO_DFT_BAND_MAX );
+#endif
+
/*residual coding*/
set_s( hStereoDft->res_cod_mode, hStereoDft->hConfig->res_cod_mode, STEREO_DFT_DEC_DFT_NB );
hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->hConfig->res_cod_mode];
set_zero( hStereoDft->res_cod_mem, STEREO_DFT_OVL_8k );
+#ifdef IVAS_FLOAT_FIXED
+ set_l( hStereoDft->res_cod_mem_fx, 0, STEREO_DFT_OVL_8k );
+#endif
hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max );
@@ -496,6 +549,14 @@ void stereo_dft_dec_reset(
set_zero( hStereoDft->itd, STEREO_DFT_DEC_DFT_NB );
set_zero( hStereoDft->res_pred_gain, STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX );
+#ifdef IVAS_FLOAT_FIXED
+ /*reset parameters*/
+ set_val_Word32( hStereoDft->side_gain_fx, 0, STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX );
+ set_val_Word32( hStereoDft->gipd_fx, 0, STEREO_DFT_DEC_DFT_NB );
+ set_val_Word32( hStereoDft->itd_fx, 0, STEREO_DFT_DEC_DFT_NB );
+ set_val_Word32( hStereoDft->res_pred_gain_fx, 0, STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX );
+#endif
+
hStereoDft->wasTransient = 0;
hStereoDft->attackPresent = 0;
@@ -504,10 +565,19 @@ void stereo_dft_dec_reset(
hStereoDft->lt_var_mean_ratio = STEREO_DFT_RES_RATIO_LIMIT;
hStereoDft->stefi_short_gain = 1.0f;
hStereoDft->stefi_long_gain = 0.0f;
+#ifdef IVAS_FLOAT_FIXED
+ hStereoDft->lt_pred_gain_fx = 0;
+ hStereoDft->lt_pred_gain_variation_fx = 0;
+ hStereoDft->lt_var_mean_ratio_fx = STEREO_DFT_RES_RATIO_LIMIT_FX;
+ hStereoDft->stefi_short_gain_fx = MAX_16;
+ hStereoDft->stefi_long_gain_fx = 0;
+ hStereoDft->q_lt_pred_gain = 0;
+#endif
set_zero( hStereoDft->g_state, STEREO_DFT_BAND_MAX );
#ifdef IVAS_FLOAT_FIXED
+ set_val_Word32( hStereoDft->g_state_fx, 0, STEREO_DFT_BAND_MAX );
init_basic_allpass( &hStereoDft->ap1, dft_ap_gains[0], dft_ap_gains_fx[0], dft_ap_delays[0] );
init_basic_allpass( &hStereoDft->ap2, dft_ap_gains[1], dft_ap_gains_fx[1], dft_ap_delays[1] );
init_basic_allpass( &hStereoDft->ap3, dft_ap_gains[2], dft_ap_gains_fx[2], dft_ap_delays[2] );
@@ -573,6 +643,55 @@ void stereo_dft_dec_reset(
hStereoDft->g_L_prev = 0.f;
hStereoDft->g_R_prev = 0.f;
+#ifdef IVAS_FLOAT_FIXED
+ set_val_Word32( hStereoDft->ap_delay_mem_fx, 0, NS2SA( 16000, DELAY_BWE_TOTAL_NS ) );
+ set_val_Word32( hStereoDft->ap_fade_mem_fx, 0, STEREO_DFT_ALLPASS_FADELEN_16k );
+ set_val_Word32( hStereoDft->smooth_dmx_nrg_fx, 0, STEREO_DFT_BAND_MAX );
+ set_val_Word32( hStereoDft->smooth_res_nrg_fx, 0, STEREO_DFT_BAND_MAX );
+
+ set_s( hStereoDft->core_hist, ACELP_CORE, STEREO_DFT_CORE_HIST_MAX );
+
+ set_val_Word32( hStereoDft->hb_stefi_sig_fx, 0, L_FRAME48k + NS2SA( 48000, STEREO_DFT_TD_STEFI_DELAY_NS ) );
+ set_val_Word32( hStereoDft->hb_nrg_fx, 0, STEREO_DFT_CORE_HIST_MAX );
+ set_val_Word32( hStereoDft->td_gain_fx, 0, STEREO_DFT_CORE_HIST_MAX );
+ set_val_Word32( hStereoDft->q_td_gain, 0, STEREO_DFT_CORE_HIST_MAX );
+
+ /* PLC parameters */
+ set_val_Word32( hStereoDft->res_mem_fx, 0, STEREO_DFT_RES_BW_MAX );
+ hStereoDft->past_dmx_nrg_fx = 0;
+ hStereoDft->sg_mean_fx = 0;
+ hStereoDft->q_dft = 0;
+ hStereoDft->q_past_dft = 0;
+ hStereoDft->q_smoothed_nrg = 0;
+
+ FOR ( i = 0; i < SBA_DIRAC_STEREO_NUM_BANDS; i++ )
+ {
+ set_val_Word32( hStereoDft->smooth_buf_fx[i], 0, SBA_DIRAC_NRG_SMOOTH_LONG + 1 );
+ }
+ set_val_Word16( hStereoDft->smooth_fac_fx[0], 0, SBA_DIRAC_STEREO_NUM_BANDS );
+ set_val_Word16( hStereoDft->smooth_fac_fx[1], 0, SBA_DIRAC_STEREO_NUM_BANDS );
+
+ hStereoDft->itd_xfade_target_fx = 0;
+ hStereoDft->itd_xfade_step_fx = 0;
+ hStereoDft->itd_xfade_prev_fx = 0;
+ hStereoDft->ipd_xfade_target_fx = 0;
+ hStereoDft->ipd_xfade_step_fx = 0;
+ hStereoDft->ipd_xfade_prev_fx = 0;
+
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ FOR ( i = 0; i < 2; i++ )
+ {
+ FOR ( j = 0; j < 4; j++ )
+ {
+ hStereoDft->mixer_mat_smooth_fx[i][j][b] = 0;
+ }
+ }
+ }
+ hStereoDft->g_L_prev_fx = 0;
+ hStereoDft->g_R_prev_fx = 0;
+#endif
+
return;
}
diff --git a/lib_dec/ivas_stereo_dft_dec_fx.c b/lib_dec/ivas_stereo_dft_dec_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..291a987625d066554239de83ada705dc74e58ac6
--- /dev/null
+++ b/lib_dec/ivas_stereo_dft_dec_fx.c
@@ -0,0 +1,2833 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include
+#include "options.h"
+#include
+#include "cnst.h"
+#include "rom_com.h"
+#include "rom_dec.h"
+#include "prot.h"
+#include "prot_fx2.h"
+#include "ivas_prot.h"
+#include "ivas_prot_fx.h"
+#include "ivas_cnst.h"
+#include "ivas_rom_com.h"
+#include "ivas_rom_com_fx.h"
+#include "ivas_rom_dec.h"
+#include "wmc_auto.h"
+#ifdef IVAS_FLOAT_FIXED
+#include "ivas_prot_fx.h"
+#include "basop_util.h"
+#endif // IVAS_FLOAT_FIXED
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define STEFI_DELAY_IND( d, buf_ind ) ( ( buf_ind ) + STEREO_DFT_PAST_MAX - ( d ) + 1 ) % STEREO_DFT_PAST_MAX
+
+#define STEREO_DFT_RES_RATIO_LIMIT_FX (Word32)(0x170A3D71)
+#define STEREO_DFT_RES_RATIO_LIMIT_FX_3_BY_2 (Word32)(0x228F5C28)
+#define ONE_STEREO_DFT_RES_RATIO_LIMIT_Q12 (Word16)(0x58E4)
+#define STEREO_DFT_LT_PREDGAIN_UPD_FX (Word16)(0x0CCD)
+#define STEREO_DFT_VR_PREDGAIN_UPD_FX (Word16)(0x0CCD)
+#define STEREO_DFT_STEFFI_PG_THRESHOLD_FX (Word32)(0x4CCCCCCD)
+#define STEREO_DFT_STEFFI_RATIO_UP_HIGH_FX (Word32)(0x03D70A3D)
+#define STEREO_DFT_STEFFI_RATIO_DOWN_HIGH_FX (Word32)(0x06666666)
+#define STEREO_DFT_STEFFI_RATIO_UP_LOW_FX (Word32)(0x0CCCCCCC)
+#define STEREO_DFT_STEFFI_RATIO_DOWN_LOW_FX (Word32)(0x0020C49C)
+#define STEREO_DFT_STEFFI_DELAY_SHORT 2
+#define STEREO_DFT_STEFFI_DELAY_LONG 4
+#define STEREO_DFT_STEFFI_DELAY_OFFSET 2
+#define STEREO_DFT_STEFFI_GAIN_REST_AMT_FX (Word16)(0x4CCD)
+#define STEREO_DFT_STEFFI_GAIN_AMP_FX (Word16)(0x7FFF)
+
+
+#define STEREO_DFT_BPF_SIZE 40 /* BPF: Number of weights for BPF in DFT: 40*40Hz=1.6kHz*/
+
+/*-------------------------------------------------------------------------
+ * Local function prototypes
+ *-------------------------------------------------------------------------*/
+
+static void stereo_dft_dec_open( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, const int32_t output_Fs, const int16_t nchan_transport );
+
+static void stereo_dft_compute_td_stefi_params_fx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, const Word16 samp_ratio );
+
+static void stereo_dft_adapt_sf_delay_fx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, Word32 *pPredGain );
+
+void stereo_dft_generate_res_pred_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 samp_ratio, /* i : sampling ratio */
+ Word32 *pDFT_DMX, /* i : downmix signal */
+ Word32 *DFT_PRED_RES, /* o : residual prediction signal */
+ Word32 *pPredGain, /* i : residual prediction gains */
+ const Word16 k, /* i : subframe index */
+ Word32 *ap_filt_DMX, /* i : enhanced stereo filling signal */
+ Word16 *stop, /* o : last FD stereo filling bin */
+ const Word16 bfi /* i : BFI flag */
+);
+
+#ifdef IVAS_FLOAT_FIXED
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_reset_fx()
+ *
+ * Reset DFT stereo memories
+ *------------------------------------------------------------------------*/
+
+void stereo_dft_dec_reset_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i/o: decoder DFT stereo handle */
+)
+{
+ Word16 i;
+ Word16 j, b;
+
+ /*Configuration*/
+ set_s( hStereoDft->prm_res, hStereoDft->hConfig->prm_res, STEREO_DFT_DEC_DFT_NB );
+
+ /* SIDE_GAIN */
+ set_s( hStereoDft->side_gain_index, 15, STEREO_DFT_BAND_MAX );
+ set_s( hStereoDft->side_gain_index_previous, 15, STEREO_DFT_BAND_MAX );
+
+ /*residual prediction*/
+ set_s( hStereoDft->res_pred_mode, hStereoDft->hConfig->res_pred_mode, STEREO_DFT_DEC_DFT_NB );
+ FOR ( i = 0; i < STEREO_DFT_PAST_MAX; i++ )
+ {
+ set_val_Word32( hStereoDft->DFT_past_DMX_fx[i], 0, STEREO_DFT32MS_N_32k );
+ set_val_Word32( hStereoDft->past_res_pred_gain_fx[i], 0, STEREO_DFT_BAND_MAX );
+ }
+
+ hStereoDft->past_DMX_pos = 0;
+ move16();
+
+ set_s( hStereoDft->res_pred_index_previous, 0, STEREO_DFT_BAND_MAX );
+
+ FOR ( i = 0; i < STEREO_DFT_BAND_MAX; i++ )
+ {
+ hStereoDft->res_gains_ind_fx[0][i] = (Word32)0x3C000000;
+ move32();
+ }
+
+ set_val_Word32( hStereoDft->res_gains_ind_fx[1], 0, STEREO_DFT_BAND_MAX );
+
+ /*residual coding*/
+ set_s( hStereoDft->res_cod_mode, hStereoDft->hConfig->res_cod_mode, STEREO_DFT_DEC_DFT_NB );
+ hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->hConfig->res_cod_mode];
+ set_val_Word32( hStereoDft->res_cod_mem_fx, 0, STEREO_DFT_OVL_8k );
+
+ hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max );
+ move32();
+
+ hStereoDft->stab_fac_smooth_res_fx = 0;
+ move32();
+ bass_psfilter_init( hStereoDft->hBpf );
+
+ tcxltp_dec_init( hStereoDft->hTcxLtpDec, 0, MODE1, IVAS_CPE_DFT, PIT_MAX, 12800 );
+
+ hStereoDft->reverb_flag = 0;
+ move16();
+
+ hStereoDft->res_hb_nrg_mem_fx = 0;
+ move32();
+ hStereoDft->bpf_error_signal_last_fx = 0;
+ move32();
+ hStereoDft->bpf_error_ratio_mem_fx = ONE_IN_Q12;
+ move16();
+
+ /*reset parameters*/
+ set_val_Word32( hStereoDft->side_gain_fx, 0, STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX );
+ set_val_Word32( hStereoDft->gipd_fx, 0, STEREO_DFT_DEC_DFT_NB );
+ set_val_Word32( hStereoDft->itd_fx, 0, STEREO_DFT_DEC_DFT_NB );
+ set_val_Word32( hStereoDft->res_pred_gain_fx, 0, STEREO_DFT_DEC_DFT_NB * STEREO_DFT_BAND_MAX );
+
+ hStereoDft->wasTransient = 0;
+ move16();
+ hStereoDft->attackPresent = 0;
+ move16();
+
+ hStereoDft->lt_pred_gain_fx = 0;
+ hStereoDft->lt_pred_gain_variation_fx = 0;
+ hStereoDft->lt_var_mean_ratio_fx = STEREO_DFT_RES_RATIO_LIMIT_FX;
+ hStereoDft->stefi_short_gain_fx = MAX_16;
+ hStereoDft->stefi_long_gain_fx = 0;
+ hStereoDft->q_lt_pred_gain = 0;
+
+ set_val_Word16( &hStereoDft->g_state_fx[0], 0, STEREO_DFT_BAND_MAX );
+
+ init_basic_allpass( &hStereoDft->ap1, dft_ap_gains[0], dft_ap_gains_fx[0], dft_ap_delays[0] );
+ init_basic_allpass( &hStereoDft->ap2, dft_ap_gains[1], dft_ap_gains_fx[1], dft_ap_delays[1] );
+ init_basic_allpass( &hStereoDft->ap3, dft_ap_gains[2], dft_ap_gains_fx[2], dft_ap_delays[2] );
+
+ set_val_Word32( hStereoDft->ap_delay_mem_fx, 0, NS2SA( 16000, DELAY_BWE_TOTAL_NS ) );
+ set_val_Word32( hStereoDft->ap_fade_mem_fx, 0, STEREO_DFT_ALLPASS_FADELEN_16k );
+ hStereoDft->ap_wasTransient = 0;
+ move16();
+ set_val_Word32( hStereoDft->smooth_dmx_nrg_fx, 0, STEREO_DFT_BAND_MAX );
+ set_val_Word32( hStereoDft->smooth_res_nrg_fx, 0, STEREO_DFT_BAND_MAX );
+
+ set_s( hStereoDft->core_hist, ACELP_CORE, STEREO_DFT_CORE_HIST_MAX );
+
+ set_val_Word32( hStereoDft->hb_stefi_sig_fx, 0, L_FRAME48k + NS2SA( 48000, STEREO_DFT_TD_STEFI_DELAY_NS ) );
+ set_val_Word32( hStereoDft->hb_nrg_fx, 0, STEREO_DFT_CORE_HIST_MAX );
+ set_val_Word32( hStereoDft->td_gain_fx, 0, STEREO_DFT_CORE_HIST_MAX );
+ set_val_Word32( hStereoDft->q_td_gain, 0, STEREO_DFT_CORE_HIST_MAX );
+
+ /* PLC parameters */
+ set_val_Word32( hStereoDft->res_mem_fx, 0, STEREO_DFT_RES_BW_MAX );
+ hStereoDft->time_offs = 0;
+ move16();
+ hStereoDft->past_dmx_nrg_fx = 0;
+ move32();
+ hStereoDft->sg_mean_fx = 0;
+ move32();
+ hStereoDft->sg_mem_corrupt = 0;
+ move16();
+ hStereoDft->recovery_flg = 0;
+ move16();
+
+ FOR ( i = 0; i < SBA_DIRAC_STEREO_NUM_BANDS; i++ )
+ {
+ set_val_Word32( hStereoDft->smooth_buf_fx[i], 0, SBA_DIRAC_NRG_SMOOTH_LONG + 1 );
+ }
+ set_val_Word16( &hStereoDft->smooth_fac_fx[0][0], 0, SBA_DIRAC_STEREO_NUM_BANDS );
+ set_zero( hStereoDft->smooth_fac[1], SBA_DIRAC_STEREO_NUM_BANDS );
+
+ hStereoDft->itd_xfade_target_fx = 0; move32();
+ hStereoDft->itd_xfade_step_fx = 0; move32();
+ hStereoDft->itd_xfade_counter = 0; move16();
+ hStereoDft->itd_xfade_prev_fx = 0; move32();
+ hStereoDft->last_active_element_brate = 0; move32();
+ hStereoDft->ipd_xfade_target_fx = 0; move32();
+ hStereoDft->ipd_xfade_step_fx = 0; move32();
+ hStereoDft->ipd_xfade_counter = 0; move16();
+ hStereoDft->ipd_xfade_prev_fx = 0; move32();
+
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ FOR ( i = 0; i < 2; i++ )
+ {
+ FOR ( j = 0; j < 4; j++ )
+ {
+ hStereoDft->mixer_mat_smooth_fx[i][j][b] = 0; move32();
+ }
+ }
+ }
+ hStereoDft->first_frame = 1; move16();
+ hStereoDft->g_L_prev_fx = 0; move32();
+ hStereoDft->g_R_prev_fx = 0; move32();
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_open()
+ *
+ * Open DFT decoder stereo handle
+ *-------------------------------------------------------------------------*/
+
+static void stereo_dft_dec_open_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word32 output_Fs, /* i : output sampling rate */
+ const Word16 nchan_transport /* i : number of transport channels */
+)
+{
+ /*Sizes*/
+ hStereoDft->N = (int16_t) ( STEREO_DFT_HOP_MAX * output_Fs / 48000 );
+
+ /*Init. DFT sizes*/
+ hStereoDft->NFFT = (int16_t) ( STEREO_DFT32MS_N_MAX * output_Fs / 48000 );
+
+ hStereoDft->dft_trigo_8k_fx = dft_trigo_32k_fx;
+ hStereoDft->dft_trigo_12k8_fx = dft_trigo_12k8_fx;
+ hStereoDft->dft_trigo_16k_fx = dft_trigo_32k_fx;
+
+ hStereoDft->dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * output_Fs ) / 48000 );
+ hStereoDft->win232ms_8k_fx = dft_win232ms_8k_fx;
+ hStereoDft->win232ms_12k8_fx = dft_win232ms_12k8_fx;
+ hStereoDft->win232ms_16k_fx = dft_win232ms_16k_fx;
+
+ hStereoDft->dft32ms_ovl2 = (int16_t) ( ( STEREO_DFT32MS_OVL2_MAX * output_Fs ) / 48000 );
+ hStereoDft->win32ms_8k_fx = dft_win232ms_8k_fx + 1;
+ hStereoDft->win32ms_12k8_fx = dft_win232ms_12k8_fx + 1;
+ hStereoDft->win32ms_16k_fx = dft_win232ms_16k_fx + 1;
+
+ IF ( EQ_32(output_Fs , 16000) )
+ {
+ hStereoDft->dft_trigo_fx = dft_trigo_32k_fx;
+ hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP;
+ hStereoDft->win232ms_fx = dft_win232ms_16k_fx;
+ hStereoDft->win32ms_fx = dft_win232ms_16k_fx + 1;
+ }
+ ELSE IF ( EQ_32(output_Fs , 32000) )
+ {
+ hStereoDft->dft_trigo_fx = dft_trigo_32k_fx;
+ hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_32k_STEP;
+ hStereoDft->win232ms_fx = dft_win232ms_32k_fx;
+ hStereoDft->win32ms_fx = dft_win232ms_32k_fx + 1;
+ }
+ ELSE
+ {
+ assert( output_Fs == 48000 );
+ hStereoDft->dft_trigo_fx = dft_trigo_48k_fx;
+ hStereoDft->dft_trigo_step = STEREO_DFT_TRIGO_SRATE_48k_STEP;
+ hStereoDft->win232ms_fx = dft_win232ms_48k_fx;
+ hStereoDft->win32ms_fx = dft_win232ms_48k_fx + 1;
+ }
+
+ hStereoDft->win_8k_fx = dft_win_8k_fx;
+
+ /*Bands: find the number of bands, Nyquist freq. is not taken into account*/
+ set_s( hStereoDft->band_res, hStereoDft->hConfig->band_res, STEREO_DFT_DEC_DFT_NB );
+
+ hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[0], hStereoDft->NFFT, DEC );
+ hStereoDft->hb_stefi_delay = NS2SA( output_Fs, STEREO_DFT_TD_STEFI_DELAY_NS );
+
+ IF ( GT_16(nchan_transport , 2) )
+ {
+ hStereoDft->min_smooth_gains_fx = min_smooth_gains2_fx;
+ hStereoDft->max_smooth_gains_fx = max_smooth_gains2_fx;
+ }
+ ELSE
+ {
+ hStereoDft->min_smooth_gains_fx = min_smooth_gains1_fx;
+ hStereoDft->max_smooth_gains_fx = max_smooth_gains1_fx;
+ }
+
+ /* reset DFT stereo memories */
+ stereo_dft_dec_reset_fx( hStereoDft );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_create_fx()
+ *
+ * Create DFT stereo handle
+ *------------------------------------------------------------------------*/
+
+ivas_error stereo_dft_dec_create_fx(
+ STEREO_DFT_DEC_DATA_HANDLE *hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word32 element_brate, /* i : element bitrate */
+ const Word32 output_Fs, /* i : output sampling rate */
+ const Word16 sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */
+ const Word16 nchan_transport /* i : number of transport channels */
+)
+{
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft_loc;
+ Word16 tmpS;
+
+ IF ( *hStereoDft != NULL )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: DFT Stereo memory already allocated\n" );
+ }
+
+ IF ( ( hStereoDft_loc = (STEREO_DFT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DEC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo\n" ) );
+ }
+
+ IF ( ( hStereoDft_loc->hConfig = (STEREO_DFT_CONFIG_DATA_HANDLE) malloc( sizeof( STEREO_DFT_CONFIG_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT Stereo Config\n" ) );
+ }
+
+ IF ( ( hStereoDft_loc->hBpf = (BPF_DEC_HANDLE) malloc( sizeof( BPF_DEC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for BPF handle\n" ) );
+ }
+
+ IF ( ( hStereoDft_loc->hTcxLtpDec = (TCX_LTP_DEC_HANDLE) malloc( sizeof( TCX_LTP_DEC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TCX-LTP handle\n" ) );
+ }
+
+ hStereoDft_loc->hConfig->force_mono_transmission = 0;
+ move16();
+
+ IF ( sba_dirac_stereo_flag )
+ {
+ ivas_sba_dirac_stereo_config( hStereoDft_loc->hConfig );
+ }
+ ELSE
+ {
+ stereo_dft_config_fx( hStereoDft_loc->hConfig, element_brate, &tmpS, &tmpS );
+ }
+
+ stereo_dft_dec_open_fx( hStereoDft_loc, output_Fs, nchan_transport );
+
+ *hStereoDft = hStereoDft_loc;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dequantize_res_gains_fx()
+ *
+ * joint dequantizer for side channel prediction gain and residual energy
+ *-------------------------------------------------------------------------*/
+
+static void stereo_dft_dequantize_res_gains_fx(
+ Word16 *ind1,
+ Word16 *ind2,
+ Word32 *gout,
+ Word32 *rout,
+ const Word16 N )
+{
+ Word16 i, index;
+
+ FOR ( i = 0; i < N; i++ )
+ {
+ /* Ensure the indices are within range -- may go out of range due to frame loss */
+ ind1[i] = check_bounds_s( ind1[i], 0, 30 );
+ move16();
+ ind2[i] = check_bounds_s( ind2[i], 0, 7 );
+ move16();
+ index = add(shl( LE_16(ind1[i], 15) ? sub(15, ind1[i]) : sub(ind1[i], 15), 3 ), ind2[i]);
+ move16();
+ gout[i] = LE_16(ind1[i], 15) ? L_negate(dft_res_gains_q_fx[index][0]) : dft_res_gains_q_fx[index][0];
+ move16();
+ rout[i] = dft_res_gains_q_fx[index][1];
+ move16();
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------------
+ * stereo_dft_dequantize_res_gains_f_fx()
+ *
+ * returns interepolated values for non-integer indices
+ *---------------------------------------------------------------------------*/
+
+static void stereo_dft_dequantize_res_gains_f_fx(
+ Word32 *ind1,
+ Word32 *ind2,
+ Word32 *gout,
+ Word32 *rout,
+ const Word16 N )
+{
+ Word16 i, i1, j1, sign, ji, ij;
+ Word32 fi, fj;
+
+ FOR ( i = 0; i < N; i++ )
+ {
+ /* Ensure the indices are within range -- may go out of range due to frame loss */
+ ind1[i] = check_bounds_l( ind1[i], 0, L_shl(31, Q26));
+ move32();
+ ind2[i] = check_bounds_l( ind2[i], 0, L_shl(7, Q26));
+ move32();
+
+ /* compensate for the offset and extract/remove sign of first index */
+ sign = LT_32(ind1[i], L_shl(15, Q26)) ? -1 : 1;
+ move16();
+ i1 = (Word16)L_shr(( LT_32(ind1[i], L_shl(15, Q26)) ? L_sub(L_shl(15, Q26), ind1[i]) : L_sub(ind1[i], L_shl(15, Q26)) ), Q26);
+ fi = (LT_32( ind1[i], L_shl(15, Q26)) ? L_sub(L_shl(15, Q26), ind1[i]) : L_sub(ind1[i], L_shl(15, Q26))) - L_shl(i1, Q26);
+ move16();
+ j1 = (Word16) L_shr( ind2[i], Q26 );
+ fj = L_sub(ind2[i], L_shl(j1, Q26));
+
+ /* choose base indices for interpolation */
+ ji = (Word16)L_min( fj < ONE_IN_Q25 ? j1 : j1 + 1, 7 );
+ ij = (Word16)L_min( fi < ONE_IN_Q25 ? i1 : i1 + 1, 15 );
+
+ /* interpolate values from table */
+ IF ( LT_32(i1, L_shl(15, Q26)) )
+ {
+ gout[i] = Madd_32_32( Mpy_32_32(L_sub(MAX_32, L_shl(fi , Q5)), dft_res_gains_q_fx[( i1 << 3 ) + ji][0]), dft_res_gains_q_fx[( ( i1 + 1 ) << 3 ) + ji][0], L_shl(fi, Q5) );
+ move32();
+ IF (EQ_16(sign , -1))
+ {
+ gout[i] = L_negate(gout[i]);
+ move32();
+ }
+ }
+ ELSE
+ {
+ gout[i] = sign * dft_res_gains_q_fx[120 + ji][0];
+ move32();
+ IF (EQ_16(sign , -1))
+ {
+ gout[i] = L_negate(gout[i]);
+ move32();
+ }
+ }
+
+ IF ( LT_32(j1, L_shl(7, Q26)) )
+ {
+ rout[i] = Madd_32_32(Mpy_32_32(L_sub(MAX_32, L_shl(fj , Q5)), dft_res_gains_q_fx[( ij << 3 ) + j1][1]), L_shl(fj, Q5) , dft_res_gains_q_fx[( ij << 3 ) + j1 + 1][1]);
+ move32();
+ }
+ ELSE
+ {
+ rout[i] = dft_res_gains_q_fx[( ij << 3 ) + 7][1];
+ move32();
+ }
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_update_fx()
+ *
+ * Update DFT memories for new frame
+ *-------------------------------------------------------------------------*/
+
+void stereo_dft_dec_update_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 output_frame, /* i : output frame length */
+ const Word16 sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
+)
+{
+ Word16 b, i, k_offset;
+
+ /* Initialization */
+ k_offset = STEREO_DFT_OFFSET; /*Add an offset*/
+ move16();
+ /* Update parameters */
+ FOR ( i = 0; i < k_offset * STEREO_DFT_BAND_MAX; i++ )
+ {
+ hStereoDft->side_gain_fx[i] = hStereoDft->side_gain_fx[STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX + i];
+ move32();
+ hStereoDft->res_pred_gain_fx[i] = hStereoDft->res_pred_gain_fx[STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX + i];
+ move32();
+ }
+
+ FOR ( i = 0; i < k_offset; i++ )
+ {
+ hStereoDft->gipd_fx[i] = hStereoDft->gipd_fx[STEREO_DFT_NBDIV + i];
+ move32();
+ }
+
+ /* Update configuration memories */
+ FOR ( i = 0; i < k_offset; i++ )
+ {
+ hStereoDft->band_res[i] = hStereoDft->band_res[i + STEREO_DFT_NBDIV];
+ move16();
+ hStereoDft->prm_res[i] = hStereoDft->prm_res[i + STEREO_DFT_NBDIV];
+ move16();
+ hStereoDft->itd_fx[i] = hStereoDft->itd_fx[STEREO_DFT_NBDIV + i];
+ move32();
+ hStereoDft->res_cod_mode[i] = hStereoDft->res_cod_mode[i + STEREO_DFT_NBDIV];
+ move16();
+ hStereoDft->res_pred_mode[i] = hStereoDft->res_pred_mode[i + STEREO_DFT_NBDIV];
+ move16();
+ }
+
+ /* Load new configurations */
+ set_s( hStereoDft->band_res + k_offset, hStereoDft->hConfig->band_res, STEREO_DFT_NBDIV );
+ set_s( hStereoDft->prm_res + k_offset, hStereoDft->hConfig->prm_res, STEREO_DFT_NBDIV );
+ set_s( hStereoDft->res_pred_mode + k_offset, hStereoDft->hConfig->res_pred_mode, STEREO_DFT_NBDIV );
+ set_s( hStereoDft->res_cod_mode + k_offset, hStereoDft->hConfig->res_cod_mode, STEREO_DFT_NBDIV );
+
+ /*Update attack info*/
+ IF ( hStereoDft->attackPresent )
+ {
+ hStereoDft->wasTransient = 1;
+ move16();
+ }
+ ELSE IF ( hStereoDft->wasTransient )
+ {
+ hStereoDft->wasTransient = 0;
+ move16();
+ }
+
+ FOR ( i = STEREO_DFT_CORE_HIST_MAX - 1; i > 0; i-- )
+ {
+ hStereoDft->core_hist[i] = hStereoDft->core_hist[i - 1];
+ move16();
+ }
+
+ Copy32( hStereoDft->hb_stefi_sig_fx + output_frame, hStereoDft->hb_stefi_sig_fx, hStereoDft->hb_stefi_delay );
+ Copy32( hStereoDft->hb_nrg_fx, hStereoDft->hb_nrg_fx + 1, STEREO_DFT_CORE_HIST_MAX - 1 );
+ Copy32( hStereoDft->td_gain_fx, hStereoDft->td_gain_fx + 1, STEREO_DFT_CORE_HIST_MAX - 1 );
+ Copy32( hStereoDft->q_td_gain, hStereoDft->q_td_gain + 1, STEREO_DFT_CORE_HIST_MAX - 1);
+
+ IF ( sba_dirac_stereo_flag )
+ {
+ /* buffer update, push back by 2 because of 2 subframes */
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ FOR ( i = SBA_DIRAC_NRG_SMOOTH_LONG; i > 1; i-- )
+ {
+ hStereoDft->smooth_buf_fx[b][i] = hStereoDft->smooth_buf_fx[b][i - 2];
+ move32();
+ }
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_synthesize_fx()
+ *
+ * Inverse DFT on a 20ms frame
+ *-------------------------------------------------------------------------*/
+
+void stereo_dft_dec_synthesize_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i : DFT buffers */
+ const Word16 chan, /* i : channel number */
+ Word32 output[L_FRAME48k], /* o : output synthesis signal */
+ const Word16 output_frame /* i : output frame length */
+)
+{
+ Word16 i, k;
+ Word16 offset;
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft;
+ Word32 *p_DFT;
+ const Word16 *win, *win2;
+ Word16 trigo_dec[((STEREO_DFT32MS_N_MAX) >> 1) + 1];
+ Word16 trigo_step;
+ Word16 ovl, zp, NFFT;
+ Word32 outputFs;
+ Word16 ovl2, flat_portion_end;
+ Word32 ola_buff[STEREO_DFT32MS_OVL2_MAX];
+ Word16 moffset;
+ push_wmops( "DFT_synthesis" );
+
+ /*-----------------------------------------------------------------*
+ * Initialization
+ *-----------------------------------------------------------------*/
+
+ hStereoDft = hCPE->hStereoDft;
+
+ outputFs = L_mult0(output_frame, FRAMES_PER_SEC);
+
+ zp = NS2SA( outputFs, STEREO_DFT32MS_ZP_NS );
+ move16();
+ ovl = NS2SA( outputFs, STEREO_DFT32MS_OVL_NS );
+ move16();
+ win = hStereoDft->win32ms_fx;
+ NFFT = NS2SA( outputFs, STEREO_DFT32MS_N_NS );
+ move16();
+ ovl2 = NS2SA( outputFs, STEREO_DFT32MS_OVL2_NS );
+ move16();
+ flat_portion_end = NS2SA( outputFs, L_sub(STEREO_DFT32MS_WIN_CENTER_NS , L_shr(STEREO_DFT32MS_OVL2_NS, 1)) );
+ move16();
+ win2 = hStereoDft->win232ms_fx;
+
+ p_DFT = DFT[chan];
+ set_val_Word32( output, 0, NS2SA( outputFs, FRAME_SIZE_NS ) );
+
+ /* deactivating the spectrum scrambling on active speech */
+ IF ( ( EQ_16(chan, 0) && GT_16(hCPE->hCoreCoder[0]->last_coder_type, UNVOICED) ) || EQ_16(hCPE->last_element_mode, IVAS_CPE_MDCT) || LT_16(hCPE->last_element_mode, IVAS_CPE_DFT) )
+ {
+ hCPE->stereo_switching_counter = 10;
+ move16();
+ }
+
+ IF ( EQ_16(hCPE->stereo_switching_counter, 0) )
+ {
+ /* Set the level of dispersion */
+ hCPE->NbFrameMod = (int16_t) ( 12.0f * max( -0.1f, min( 0.4, hCPE->lt_es_em ) ) + 1.2f + 0.5f ); /* -0.1: -0.4 ; -0.1 -> 0, 0.4 -> 6*/
+ }
+ moffset = max( 0, 6 - hCPE->NbFrameMod );
+
+ /*-----------------------------------------------------------------*
+ * Synthesis
+ *-----------------------------------------------------------------*/
+
+ trigo_step = i_mult(hStereoDft->dft_trigo_step, STEREO_DFT_TRIGO_DEC_STEP);
+ FOR ( i = 0; i < shr(NFFT, 2); i++ )
+ {
+ trigo_dec[i] = hStereoDft->dft_trigo_fx[i * trigo_step];
+ move16();
+ trigo_dec[sub(shr(NFFT , 1) , i)] = hStereoDft->dft_trigo_fx[i * trigo_step];
+ move16();
+ }
+ trigo_dec[shr(NFFT , 2)] = hStereoDft->dft_trigo_fx[shr(NFFT , 2) * trigo_step];
+ move16();
+
+ FOR ( k = 0; k < STEREO_DFT_NBDIV; k++ )
+ {
+ /* scrambling the spectrum */
+ IF ( LE_16(hCPE->stereo_switching_counter , 6) && EQ_16(chan, 1) && ( hCPE->lt_es_em > -0.4f || GT_16(hCPE->NbFrameMod, 4) ) )
+ {
+ FOR ( i = 3; i < NFFT - moffset - 1; i++ )
+ {
+ p_DFT[i] = L_negate(p_DFT[i + moffset + 1]);
+ move32();
+ }
+ }
+ ELSE IF ( LT_16(hCPE->stereo_switching_counter, 7) && ( hCPE->lt_es_em > 0.2f || GT_16(hCPE->NbFrameMod , 4) ) )
+ {
+ FOR ( i = sub(16 , hCPE->NbFrameMod); i < sub(NFFT, add(moffset, 1)); i++ )
+ {
+ p_DFT[i - 2] = L_negate(p_DFT[i + moffset + 1]);
+ move32();
+ }
+ }
+
+ /*IFFT*/
+ rfft_fx( p_DFT, trigo_dec, NFFT, +1 );
+
+ IF ( EQ_16(k , 0) )
+ {
+ offset = 0;
+ move16();
+
+ /* Left OLA - 3.125ms */
+ FOR ( i = 0; i < ovl; i++ )
+ {
+ output[offset + i] = Mpy_32_16_1(L_add(hCPE->output_mem_fx[chan][i], p_DFT[zp + i]), win[STEREO_DFT32MS_STEP * i]);
+ move32();
+ }
+ /* Flat Portion */
+ FOR ( i = ovl; i < flat_portion_end; i++ )
+ {
+ output[offset + i] = p_DFT[zp + i];
+ move32();
+ }
+ /* Right OLA */
+ FOR ( i = 0; i < ovl2; i++ )
+ {
+ ola_buff[i] = Mpy_32_16_1( p_DFT[NFFT - zp - ovl2 + i], win2[ovl2 - 1 - i]);
+ move32();
+ }
+ }
+ ELSE
+ {
+ /* If OVL2 = OVL offset = 10ms */
+ offset = flat_portion_end;
+ move16();
+ /* Left OLA */
+ FOR ( i = 0; i < ovl2; i++ )
+ {
+ output[offset + i] = Madd_32_16(ola_buff[i], p_DFT[zp + i], win2[i]);
+ move32();
+ }
+ /* Flat Portion */
+ FOR ( i = ovl2; i < NFFT - 2 * zp - ovl; i++ )
+ {
+ output[offset + i] = p_DFT[zp + i];
+ move32();
+ }
+ /* Right OLA - 3.125ms */
+ FOR ( i = 0; i < ovl; i++ )
+ {
+ hCPE->output_mem_fx[chan][i] = Mpy_32_16_1(p_DFT[NFFT - zp - ovl + i], win[STEREO_DFT32MS_STEP * ( ovl - 1 - i )]);
+ move32();
+ }
+ }
+ p_DFT += STEREO_DFT32MS_N_MAX;
+ }
+
+
+ pop_wmops();
+ return;
+}
+
+/*---------------------------------------------------------------
+ * stereo_dft_dec_smooth_parameters_fx()
+ *
+ *
+ * ---------------------------------------------------------------*/
+
+void stereo_dft_dec_smooth_parameters_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 prev_sid_nodata, /* i : Previous SID/No data indicator */
+ const Word16 active_frame_counter, /* i : Active frame counter */
+ const Word32 element_brate /* i : Element bitrate */
+)
+{
+ Word16 k_offset, k, k2, b, N_div;
+ Word32 *pIpd, *pInterpol;
+ Word32 *pgIpd;
+ Word32 *pSideGain;
+ Word32 diff_ipd;
+ Word16 nbands;
+ Word32 max_res_pred_ind;
+
+ N_div = STEREO_DFT_NBDIV;
+ move16();
+ k_offset = STEREO_DFT_OFFSET;
+ move16();
+
+ IF ( hStereoDft->frame_sid_nodata || prev_sid_nodata )
+ {
+ k = 1;
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ *( hStereoDft->side_gain_fx + ( ( add( k , k_offset ) ) - 1 ) * STEREO_DFT_BAND_MAX + b ) = *( hStereoDft->side_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b );
+ move32();
+ }
+
+ IF ( hStereoDft->frame_sid_nodata )
+ {
+ /* set new xfade target if new itd received */
+ IF ( NE_32(hStereoDft->gipd_fx[add( k , k_offset )], hStereoDft->ipd_xfade_target_fx) )
+ {
+ Word16 q_val;
+ IF ( GT_32(L_sub( hStereoDft->gipd_fx[add( k , k_offset )], hStereoDft->ipd_xfade_prev_fx ), EVS_PI_FX) )
+ {
+ hStereoDft->ipd_xfade_target_fx = L_sub(hStereoDft->gipd_fx[add( k , k_offset )], EVS_PI_FX);
+ move32();
+ hStereoDft->ipd_xfade_step_fx = BASOP_Util_Divide3232_Scale(L_sub( hStereoDft->ipd_xfade_target_fx, hStereoDft->ipd_xfade_prev_fx ) , L_sub( STEREO_DFT_ITD_CNG_XFADE, hStereoDft->ipd_xfade_counter ), &q_val);
+ move32();
+ IF (GT_16(q_val, 16))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ hStereoDft->ipd_xfade_step_fx = L_shl(hStereoDft->ipd_xfade_step_fx, q_val);
+ }
+ }
+ ELSE IF ( GT_32(L_sub( hStereoDft->ipd_xfade_prev_fx, hStereoDft->gipd_fx[add( k , k_offset )] ), EVS_PI_FX) )
+ {
+ hStereoDft->ipd_xfade_target_fx = L_add(hStereoDft->gipd_fx[add( k , k_offset )], L_shl(EVS_PI_FX, 1));
+ move32();
+ hStereoDft->ipd_xfade_step_fx = BASOP_Util_Divide3232_Scale(L_sub( hStereoDft->ipd_xfade_target_fx, hStereoDft->ipd_xfade_prev_fx ) , L_sub( STEREO_DFT_ITD_CNG_XFADE, hStereoDft->ipd_xfade_counter ), &q_val);
+ move32();
+ IF (GT_16(q_val, 16))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ hStereoDft->ipd_xfade_step_fx = L_shl(hStereoDft->ipd_xfade_step_fx, q_val);
+ }
+ }
+ ELSE
+ {
+ hStereoDft->ipd_xfade_target_fx = hStereoDft->gipd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->ipd_xfade_step_fx = BASOP_Util_Divide3232_Scale(L_sub( hStereoDft->ipd_xfade_target_fx, hStereoDft->ipd_xfade_prev_fx ) , L_sub( STEREO_DFT_ITD_CNG_XFADE, hStereoDft->ipd_xfade_counter ), &q_val);
+ move32();
+ IF (GT_16(q_val, 16))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ hStereoDft->ipd_xfade_step_fx = L_shl(hStereoDft->ipd_xfade_step_fx, q_val);
+ }
+ }
+ }
+
+ /* xfade */
+ IF ( NE_32(hStereoDft->ipd_xfade_prev_fx, hStereoDft->ipd_xfade_target_fx) && LT_16(hStereoDft->ipd_xfade_counter, STEREO_DFT_ITD_CNG_XFADE) && LE_32(hStereoDft->last_active_element_brate, 24400) )
+ {
+ hStereoDft->gipd_fx[add( k , k_offset )] = L_add(hStereoDft->ipd_xfade_prev_fx, hStereoDft->ipd_xfade_step_fx);
+ move32();
+ hStereoDft->ipd_xfade_prev_fx = hStereoDft->gipd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->ipd_xfade_counter++;
+ }
+ }
+ ELSE
+ {
+ /* First active frame, "reset" everything if long enough active encoding, only triggered if STEREO_DFT_ITD_CNG_XFADE_RESET = -1 */
+ IF ( GT_16(active_frame_counter, STEREO_DFT_ITD_CNG_XFADE_RESET) )
+ {
+ hStereoDft->ipd_xfade_target_fx = hStereoDft->gipd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->ipd_xfade_prev_fx = hStereoDft->gipd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->ipd_xfade_counter = 0;
+ move16();
+ }
+ }
+
+ FOR ( k2 = 1; k2 < hStereoDft->prm_res[add( k , k_offset )]; k2++ )
+ {
+ hStereoDft->gipd_fx[( add( k , k_offset ) ) - k2] = hStereoDft->gipd_fx[add( k , k_offset )];
+ move32();
+ }
+
+ IF ( hStereoDft->frame_sid_nodata )
+ {
+ /* set new xfade target if new itd received */
+ IF ( NE_32(hStereoDft->itd_fx[add( k , k_offset )], hStereoDft->itd_xfade_target_fx) )
+ {
+ Word16 q_val;
+ hStereoDft->itd_xfade_target_fx = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->itd_xfade_step_fx = BASOP_Util_Divide3232_Scale(L_sub( hStereoDft->itd_xfade_target_fx, hStereoDft->itd_xfade_prev_fx) , sub( STEREO_DFT_ITD_CNG_XFADE, hStereoDft->itd_xfade_counter ), &q_val);
+ IF (GT_16(q_val, 16))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ hStereoDft->itd_xfade_step_fx = L_shl(hStereoDft->itd_xfade_step_fx, q_val);
+ }
+ move32();
+ }
+
+ /* xfade */
+ IF ( NE_32(hStereoDft->itd_xfade_prev_fx, hStereoDft->itd_xfade_target_fx) && LT_16(hStereoDft->itd_xfade_counter, STEREO_DFT_ITD_CNG_XFADE) && LE_32(hStereoDft->last_active_element_brate, 24400) )
+ {
+ hStereoDft->itd_fx[add( k , k_offset )] = L_add(hStereoDft->itd_xfade_prev_fx , hStereoDft->itd_xfade_step_fx);
+ move32();
+ hStereoDft->itd_xfade_prev_fx = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->itd_xfade_counter++;
+ }
+ }
+ ELSE
+ {
+ /* First active frame, "reset" everything if long enough active encoding, only triggered if STEREO_DFT_ITD_CNG_XFADE_RESET = -1 */
+ IF ( GT_16(active_frame_counter, STEREO_DFT_ITD_CNG_XFADE_RESET) )
+ {
+ hStereoDft->itd_xfade_target_fx = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->itd_xfade_prev_fx = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ hStereoDft->itd_xfade_counter = 0;
+ move32();
+ }
+
+ hStereoDft->last_active_element_brate = element_brate;
+ move32();
+ }
+ FOR ( k2 = 1; k2 < hStereoDft->prm_res[add( k , k_offset )]; k2++ )
+ {
+ hStereoDft->itd_fx[( add( k , k_offset ) ) - k2] = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ }
+
+ return;
+ }
+
+ /* Active frame, "reset" everything "reset" everything if long enough active encoding */
+ IF ( GT_16(active_frame_counter, STEREO_DFT_ITD_CNG_XFADE_RESET ))
+ {
+ hStereoDft->itd_xfade_counter = 0;
+ move16();
+ hStereoDft->itd_xfade_target_fx = hStereoDft->itd_fx[STEREO_DFT_NBDIV - 1];
+ move32();
+ hStereoDft->itd_xfade_prev_fx = hStereoDft->itd_fx[STEREO_DFT_NBDIV - 1];
+ move32();
+ hStereoDft->ipd_xfade_counter = 0;
+ move16();
+ hStereoDft->ipd_xfade_target_fx = hStereoDft->gipd_fx[STEREO_DFT_NBDIV - 1];
+ move32();
+ hStereoDft->ipd_xfade_prev_fx = hStereoDft->gipd_fx[STEREO_DFT_NBDIV - 1];
+ move32();
+ }
+
+ hStereoDft->last_active_element_brate = element_brate;
+ move32();
+
+ FOR ( k = hStereoDft->prm_res[k_offset] - 1; k < N_div; k += hStereoDft->prm_res[add( k , k_offset )] )
+ {
+ max_res_pred_ind = 0;
+ move32();
+ IF ( EQ_16(hStereoDft->reverb_flag, 1) )
+ {
+ nbands = min( 10, hStereoDft->nbands_respred );
+ move16();
+ /*Shift 2 last bands residual prediction gains for SWB/FB*/
+ IF ( EQ_16(hStereoDft->band_res[k_offset], STEREO_DFT_BAND_RES_HIGH) )
+ {
+ FOR ( b = hStereoDft->nbands_respred - 1; b >= nbands; b-- )
+ {
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX] =
+ hStereoDft->res_gains_ind_fx[1][b - STEREO_DFT_RES_PRED_BAND_MIN_RED + hStereoDft->res_pred_band_min + STEREO_DFT_BAND_MAX];
+ move32();
+ hStereoDft->res_gains_ind_fx[1][b - STEREO_DFT_RES_PRED_BAND_MIN_RED + hStereoDft->res_pred_band_min + STEREO_DFT_BAND_MAX] = 0;
+ move32();
+ }
+ }
+
+ /* Get maximal index */
+ FOR ( b = hStereoDft->res_pred_band_min; b < ( nbands - STEREO_DFT_RES_PRED_BAND_MIN_CONST ); b++ )
+ {
+ IF ( LT_32(max_res_pred_ind, hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX]) )
+ {
+ max_res_pred_ind = hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX];
+ move32();
+ }
+ }
+
+ /* predictive values */
+ FOR ( ; b < nbands; b++ )
+ {
+ assert( hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX] == 0 );
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX] = max_res_pred_ind;
+ move32();
+ }
+ }
+
+ FOR ( b = hStereoDft->res_pred_band_min; b < hStereoDft->res_cod_band_max; b++ )
+ {
+ Word32 tmp;
+ Word16 tmps1, tmps2;
+
+ hStereoDft->res_gains_ind_fx[0][b] = hStereoDft->res_gains_ind_fx[0][b + STEREO_DFT_BAND_MAX];
+ move32();
+ /*stereo_dft_dequantize_res_gains_f(&hStereoDft->res_gains_ind[0][b], &hStereoDft->res_gains_ind[1][b+STEREO_DFT_BAND_MAX],hStereoDft->side_gain+(k+k_offset)*STEREO_DFT_BAND_MAX+b, hStereoDft->res_pred_gain+(k+k_offset)*STEREO_DFT_BAND_MAX+b, 1);*/
+ tmps1 = (Word16) L_shr( hStereoDft->res_gains_ind_fx[0][b], Q26 );
+ move16();
+ tmps2 = (Word16) L_shr( hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], Q26 );
+ move16();
+ stereo_dft_dequantize_res_gains_fx( &tmps1, &tmps2, hStereoDft->side_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b, hStereoDft->res_pred_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b, 1 );
+
+ IF ( hStereoDft->attackPresent )
+ {
+ hStereoDft->res_gains_ind_fx[1][b] = Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], (Word16)0x6666);
+ move32();
+ }
+ ELSE IF ( hStereoDft->trans || ( hStereoDft->res_pred_mode[k] && ( hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX] < ONE_IN_Q27 ) ) ) /* Assuming Maximum Q of res_gains_ind_fx is Q26 */
+ {
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], (Word16)0x4CCD),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], (Word16)0x3333);
+ move32();
+ }
+ ELSE
+ {
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16( Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], dft_alpha_s2_fx[b]),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX],
+ sub( (Word16)0x7FFF, dft_alpha_s2_fx[b] ));
+ move32();
+ }
+
+ stereo_dft_dequantize_res_gains_f_fx( &hStereoDft->res_gains_ind_fx[0][b], &hStereoDft->res_gains_ind_fx[1][b], &tmp, hStereoDft->res_pred_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b, 1 );
+ }
+
+ /* Smoothing of prediction gains between ftrames */
+ FOR ( ; b < hStereoDft->nbands; b++ )
+ {
+ IF ( hStereoDft->attackPresent )
+ {
+ hStereoDft->res_gains_ind_fx[0][b] = hStereoDft->res_gains_ind_fx[0][b + STEREO_DFT_BAND_MAX];
+ move32();
+ hStereoDft->res_gains_ind_fx[1][b] = Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], (Word16)0x6666);
+ move32();
+ }
+ ELSE IF ( hStereoDft->trans || ( hStereoDft->res_pred_mode[k] && LT_32( hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], ONE_IN_Q27 ) ) )
+ {
+ hStereoDft->res_gains_ind_fx[0][b] = hStereoDft->res_gains_ind_fx[0][b + STEREO_DFT_BAND_MAX];
+ move32();
+ IF ( EQ_16(hStereoDft->hConfig->band_res, STEREO_DFT_BAND_RES_LOW) )
+ {
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], dft_alpha_w_b2_fx[b]),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], sub((Word16)0x7FFF, dft_alpha_w_b2_fx[b]));
+ move32();
+ }
+ ELSE
+ {
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], dft_alpha_w_fx[b]),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], sub((Word16)0x7FFF, dft_alpha_w_fx[b] ));
+ move32();
+ }
+ }
+ ELSE
+ {
+ IF ( EQ_16(hStereoDft->hConfig->band_res, STEREO_DFT_BAND_RES_LOW) )
+ {
+ hStereoDft->res_gains_ind_fx[0][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[0][b], dft_alpha_s_b2_fx[b]),
+ hStereoDft->res_gains_ind_fx[0][b + STEREO_DFT_BAND_MAX],
+ sub( (Word16)0x7FFF, dft_alpha_s_b2_fx[b] ) );
+ move32();
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], dft_alpha_s2_b2_fx[b]),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX],
+ sub( (Word16)0x7FFF, dft_alpha_s2_b2_fx[b] ) );
+ move32();
+ }
+ ELSE
+ {
+ hStereoDft->res_gains_ind_fx[0][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[0][b], dft_alpha_s_fx[b]),
+ hStereoDft->res_gains_ind_fx[0][b + STEREO_DFT_BAND_MAX],
+ sub((Word16)(0x7FFF), dft_alpha_s_fx[b] ));
+ move32();
+ hStereoDft->res_gains_ind_fx[1][b] = Madd_32_16(Mpy_32_16_1(hStereoDft->res_gains_ind_fx[1][b], dft_alpha_s2_fx[b]),
+ hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX],
+ sub((Word16)(0x7FFF), dft_alpha_s2_fx[b] ) );
+ move32();
+ }
+ }
+
+ IF ( !hStereoDft->recovery_flg )
+ {
+ stereo_dft_dequantize_res_gains_f_fx( &hStereoDft->res_gains_ind_fx[0][b], &hStereoDft->res_gains_ind_fx[1][b], hStereoDft->side_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b, hStereoDft->res_pred_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b, 1 );
+ }
+ }
+
+ /* Smoothing of IPDs*/
+ pgIpd = hStereoDft->gipd_fx + ( add( k , k_offset ) );
+ diff_ipd = L_sub(pgIpd[0] , pgIpd[-hStereoDft->prm_res[add( k , k_offset )]]);
+ IF ( LT_32(diff_ipd, -EVS_PI_FX) )
+ {
+ pgIpd[0] = L_add(L_add(pgIpd[0], EVS_PI_FX), EVS_PI_FX);
+ }
+ ELSE IF ( GT_32(diff_ipd, EVS_PI_FX) )
+ {
+ pgIpd[0] = L_sub(L_sub(pgIpd[0], EVS_PI_FX), EVS_PI_FX);
+ }
+
+ IF ( !hStereoDft->attackPresent )
+ {
+ IF ( hStereoDft->wasTransient )
+ {
+ pgIpd[0] = L_add(Mpy_32_16_1(pgIpd[0], (Word16)0x6666), Mpy_32_16_1(pgIpd[-hStereoDft->prm_res[add( k , k_offset )]], (Word16)(0x199A)));
+ move16();
+ }
+ ELSE
+ {
+ pgIpd[0] = L_add(L_shr(pgIpd[0], 1), L_shr(pgIpd[-hStereoDft->prm_res[add( k , k_offset )]], 1));
+ move16();
+ }
+ }
+
+
+ IF ( !hStereoDft->attackPresent )
+ {
+ pSideGain = hStereoDft->side_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX;
+ FOR ( b = 0; b < hStereoDft->res_cod_band_max; b++ )
+ {
+ pSideGain[b] = Madd_32_16(Mpy_32_16_1(pSideGain[b], dft_res_cod_alpha_fx[b]),
+ pSideGain[b - hStereoDft->prm_res[add( k , k_offset )] * STEREO_DFT_BAND_MAX],
+ sub( (Word16)0x7FFF, dft_res_cod_alpha_fx[b] ) );
+ move32();
+ }
+ }
+
+ /*Interpolation between DFT slots*/
+ FOR ( k2 = 1; k2 < hStereoDft->prm_res[add( k , k_offset )]; k2++ )
+ {
+ pInterpol = hStereoDft->gipd_fx + sub( add( k , k_offset ) , k2 );
+ pIpd = hStereoDft->gipd_fx + add( k , k_offset );
+ IF ( hStereoDft->attackPresent )
+ {
+ *( pInterpol ) = *( pIpd );
+ move32();
+ }
+ ELSE
+ {
+ *( pInterpol ) = *( hStereoDft->gipd_fx + ( add( k , k_offset ) - hStereoDft->prm_res[add( k , k_offset )] ) );
+ move32();
+ }
+
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ *( hStereoDft->res_pred_gain_fx + sub( add( k , k_offset ) , k2 ) * STEREO_DFT_BAND_MAX + b ) = *( hStereoDft->res_pred_gain_fx + ( add( k , k_offset ) - hStereoDft->prm_res[add( k , k_offset )] ) * STEREO_DFT_BAND_MAX + b );
+ move32();
+ IF ( b < hStereoDft->res_cod_band_max || hStereoDft->attackPresent || hStereoDft->trans || ( hStereoDft->res_pred_mode[k] && LT_32( hStereoDft->res_gains_ind_fx[1][b + STEREO_DFT_BAND_MAX], ONE_IN_Q27 ) ) )
+ {
+ *( hStereoDft->side_gain_fx + sub( add( k , k_offset ) , k2 ) * STEREO_DFT_BAND_MAX + b ) = *( hStereoDft->side_gain_fx + ( add( k , k_offset ) ) * STEREO_DFT_BAND_MAX + b );
+ move32();
+ }
+ ELSE
+ {
+ *( hStereoDft->side_gain_fx + sub( add( k , k_offset ) , k2 ) * STEREO_DFT_BAND_MAX + b ) = *( hStereoDft->side_gain_fx + ( add( k , k_offset ) - hStereoDft->prm_res[add( k , k_offset )] ) * STEREO_DFT_BAND_MAX + b );
+ move32();
+ }
+ }
+
+ hStereoDft->itd_fx[( add( k , k_offset ) ) - k2] = hStereoDft->itd_fx[add( k , k_offset )];
+ move32();
+ } /*end of interpolation*/
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_dec_fx()
+ *
+ * DFT-based stereo main processing function
+ *-------------------------------------------------------------------------*/
+
+void stereo_dft_dec_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ Decoder_State *st0, /* i/o: decoder state structure */
+ Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */
+ Word32 *input_mem, /* i/o: mem of buffer DFT analysis */
+ STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */
+ const Word16 sba_dirac_stereo_flag, /* i : signal stereo output for SBA DirAC */
+ const Word16 sba_mono_flag, /* i : signal mono output for SBA DirAC */
+ ivas_spar_md_dec_state_t *hMdDec, /* i : SPAR MD handle for upmixing */
+ const Word16 cross_fade_start_offset, /* i : SPAR mixer delay compensation */
+ const Word32 output_Fs, /* i : Fs for delay calculation */
+ const Word16 nchan_transport, /* i : number of transpor channels */
+ const Word16 num_md_sub_frames /* i : number of MD subframes */
+)
+{
+ Word16 i, k, b, N_div, stop;
+ Word32 DFT_L[STEREO_DFT32MS_N_MAX];
+ Word32 DFT_R[STEREO_DFT32MS_N_MAX];
+ Word32 DFT_PRED_RES[STEREO_DFT32MS_N_32k];
+ Word32 *pDFT_DMX;
+ Word32 *pDFT_DMX1;
+ Word32 *pDFT_RES;
+ Word16 g;
+ Word32 tmp;
+ Word32 *pPredGain;
+ Word32 *pSideGain;
+ Word16 c0, s0;
+ Word16 k_offset;
+ Word32 *pgIpd;
+ Word16 NFFT_inner;
+ Word16 gamma;
+ Word16 samp_ratio;
+ Word16 prev_bfi;
+ Word32 dmx_nrg;
+ Word16 idx_k0, idx_k1;
+ Word16 output_frame;
+ Word16 plocs[STEREO_DFT_RES_N_PEAKS_MAX];
+ Word16 num_plocs;
+ Word32 plocsi[STEREO_DFT_RES_N_PEAKS_MAX];
+ Word16 ftmp, coh;
+ Word32 N1, N2;
+ Word32 scale_fact0, scale_fact;
+ Word32 lev1, lev2, cna_level, *ptr_per;
+ Word16 q_cna_level;
+ HANDLE_FD_CNG_DEC hFdCngDec = st0->hFdCngDec;
+ HANDLE_FD_CNG_COM hFdCngCom = hFdCngDec->hFdCngCom;
+ Word16 *cna_seed = &( hFdCngCom->seed);
+ Word32 DFT_W, DFT_Y;
+ Word16 q_samp_ratio = Q15;
+
+ output_frame = (Word16) Mpy_32_32( L_add(st0->output_Fs , FRAMES_PER_SEC_BY_2), ONE_BY_FRAMES_PER_SEC);
+
+ /*------------------------------------------------------------------*
+ * Initialization
+ *-----------------------------------------------------------------*/
+
+ samp_ratio = (Word16)BASOP_Util_Divide3232_Scale(st0->sr_core, st0->output_Fs, &q_samp_ratio);
+ samp_ratio = shr(samp_ratio , sub(Q15 - Q12, q_samp_ratio));
+
+
+ stop = shr(STEREO_DFT32MS_N_32k , 1);
+
+ /* Analyze nature of current frame */
+ hStereoDft->trans = (Word16)( ( EQ_16( st0->clas_dec, ONSET ) || EQ_16( st0->clas_dec, SIN_ONSET ) || EQ_16( st0->clas_dec, UNVOICED_CLAS ) || EQ_16( st0->clas_dec, UNVOICED_TRANSITION ) ) || LE_16( st0->stab_fac_fx, (Word16)0x2000 ) ) ||
+ ( (EQ_16(st0->core, TCX_20_CORE) && ( EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) || EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, HALF_OVERLAP ) ) ) || EQ_16( st0->core, TCX_10_CORE ));
+ move16();
+
+ /* Initialization */
+ k_offset = 1;
+ move16();
+ N_div = STEREO_DFT_NBDIV;
+ move16();
+ prev_bfi = st0->prev_old_bfi; /* The core decoding is already completed here and the prev_bfi has been updated for the next frame.
+ The prev_old_bfi still holds the prev_bfi for the current frame. */
+ /* make sure number of bands corresponds to output bwidth in case it is lower than parameter bwidth */
+ move16();
+ IF ( LT_16(output_frame, inner_frame_tbl[st0->bwidth]) && EQ_16(sba_dirac_stereo_flag, 0) )
+ {
+ hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], hStereoDft->NFFT, DEC );
+ }
+
+ IF ( EQ_16(st0->bfi, 0) )
+ {
+ /* Smoothing for the current frame */
+ IF ( sba_dirac_stereo_flag )
+ {
+ ivas_sba_dirac_stereo_smooth_parameters_fx( hStereoDft, hMdDec, cross_fade_start_offset, output_Fs, num_md_sub_frames );
+ }
+ ELSE
+ {
+ stereo_dft_dec_smooth_parameters_fx( hStereoDft, hStereoCng->prev_sid_nodata, hStereoCng->active_frame_counter, st0->element_brate );
+ }
+ }
+
+ dmx_nrg = 0;
+ move32();
+ IF ( prev_bfi )
+ {
+ dmx_nrg = stereo_dft_dmx_swb_nrg_fx( DFT[0], DFT[0] + STEREO_DFT32MS_N_MAX, min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
+ }
+
+
+#ifdef DEBUG_PRINT
+ printf( "\nframe: %d\n", frame );
+#endif
+ FOR ( k = 0; k < N_div; k++ )
+ {
+ pDFT_DMX = DFT[0] + i_mult(k , STEREO_DFT32MS_N_MAX);
+ pDFT_RES = DFT[1] + i_mult(k , STEREO_DFT32MS_N_MAX);
+ pDFT_DMX1 = 0;
+ IF ( GT_16(nchan_transport, 1) )
+ {
+ pDFT_DMX1 = DFT[1] + i_mult(k , STEREO_DFT32MS_N_MAX);
+ }
+
+ /*Apply Stereo*/
+ IF ( hStereoDft->hConfig->dmx_active )
+ {
+ g = MAX_16;
+ move16();
+ c0 = MAX_16;
+ move16();
+ s0 = 0;
+ move16();
+
+ /* since delay is just 3.125ms, the parameters received are used for the second window */
+ pSideGain = hStereoDft->side_gain_fx + i_mult(add( k , k_offset ) , STEREO_DFT_BAND_MAX);
+ pgIpd = hStereoDft->gipd_fx + add( k , k_offset );
+ pPredGain = hStereoDft->res_pred_gain_fx + i_mult(add( k , k_offset ) , STEREO_DFT_BAND_MAX);
+
+#ifdef DEBUG_PRINT
+ if ( k == 0 )
+ {
+ printf( "Window0\n" );
+ }
+ else
+ {
+ printf( "Window1\n" );
+ }
+ for ( b = 0; b < hStereoDft->nbands; b++ )
+ printf( "%.6f ", pSideGain[b] );
+ printf( "\n" );
+ for ( b = 0; b < hStereoDft->nbands; b++ )
+ printf( "%.6f ", pPredGain[b] );
+ printf( "\n" );
+#endif
+
+ /* Use coarse band partition in inactive frames */
+ IF ( hStereoDft->frame_sid_nodata && !sba_dirac_stereo_flag )
+ {
+ NFFT_inner = i_mult((STEREO_DFT32MS_N_MAX / L_FRAME48k), inner_frame_tbl[st0->bwidth]);
+ hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, 2, NFFT_inner, DEC );
+ }
+
+
+ IF ( st0->bfi )
+ {
+ hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + STEREO_DFT_PAST_MAX - 1 ) % STEREO_DFT_PAST_MAX;
+ }
+
+ IF ( !( sba_dirac_stereo_flag && GE_16(nchan_transport, 2) ) )
+ {
+ stereo_dft_generate_res_pred_fx( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi );
+ }
+
+ IF ( GT_16(hStereoDft->res_cod_band_max, 0) )
+ {
+ IF ( !st0->bfi )
+ {
+ IF ( EQ_16(k, 1) )
+ {
+ Copy32( pDFT_RES, hStereoDft->res_mem_fx, 2 * hStereoDft->band_limits[hStereoDft->res_cod_band_max] );
+ hStereoDft->time_offs = 0;
+ move16();
+ }
+ }
+ ELSE
+ {
+ stereo_dft_res_ecu_fx( hStereoDft, pDFT_RES, DFT_PRED_RES, k, output_frame, prev_bfi, dmx_nrg, &num_plocs, plocs, plocsi, input_mem );
+ }
+ }
+
+ /* Apply active DMX */
+ /* pDFT_RES is used for the second channel in inactive frames */
+ IF ( hStereoDft->frame_sid_nodata && !sba_dirac_stereo_flag )
+ {
+ DFT_L[0] = pDFT_DMX[0];
+ move32();
+ DFT_R[0] = pDFT_RES[0];
+ move32();
+ }
+ ELSE
+ {
+ DFT_L[0] = pDFT_DMX[0];
+ move32();
+ DFT_R[0] = pDFT_DMX[0];
+ move32();
+ }
+
+ IF ( hStereoDft->frame_sid_nodata || EQ_16(st0->VAD, 0) )
+ {
+ hFdCngDec->cna_nbands = 0;
+ move16();
+ }
+
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ g = extract_h(pSideGain[b]);
+ move16();
+ IF ( hStereoDft->frame_sid_nodata && !sba_dirac_stereo_flag )
+ {
+ g = hStereoDft->g_state_fx[b];
+ move16();
+ }
+
+ /* store side gains from inactive frames for later use by the stereo CNA */
+ IF ( LT_16(hStereoDft->band_limits[b], L_FRAME16k) && ( hStereoDft->frame_sid_nodata || EQ_16(st0->VAD, 0) ) )
+ {
+ hFdCngDec->cna_nbands = add(b , 1);
+ move16();
+ hFdCngDec->cna_band_limits[b] = hStereoDft->band_limits[b];
+ move16();
+ hFdCngDec->cna_g_state_fx[b] = g;
+ move16();
+ }
+
+ /* No residual coding in inactive frames, instead pDFT_RES is used for the second channel */
+ IF ( GE_16(b, hStereoDft->res_cod_band_max) && !hStereoDft->frame_sid_nodata && !( sba_dirac_stereo_flag && hMdDec ) )
+ {
+ /*filter non-coded frequencies. It removes some MDCT frequency aliasing*/
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ pDFT_RES[2 * i] = 0;
+ move32();
+ pDFT_RES[2 * i + 1] = 0;
+ move32();
+ }
+ }
+
+ IF ( hStereoDft->frame_sid_nodata && !sba_dirac_stereo_flag )
+ {
+ /* Low pass filter coherence */
+ /* store coherence from inactive frames for later use by the stereo CNA */
+ hFdCngDec->cna_cm_fx[b] = hStereoCng->cm_fx[b];
+ move16();
+
+ /* Calculate gamma */
+ IF ( LT_16(hStereoCng->cm_fx[b], (Word16)0x7333) )
+ {
+ Word32 op1, op2, l_gamma;
+ Word16 q_loc1, q_loc2;
+ gamma = hStereoCng->cm_fx[b];
+ move16();
+ gamma = BASOP_Util_Divide3232_Scale(gamma , sub( MAX_16, gamma), &q_loc1);
+ l_gamma = L_deposit_l(gamma);
+ op1 = L_add(l_gamma, L_shr(L_deposit_l(sub(MAX_16 , mult(g, g))), q_loc1));
+ q_loc1 = Q16 + q_loc1;
+ q_loc2 = q_loc1;
+ op1 = Sqrt32(op1, &q_loc1);
+ op2 = Sqrt32(l_gamma, &q_loc2);
+ IF (NE_16(q_loc1, q_loc2))
+ {
+ op2 = L_shl(op2, sub(q_loc2, q_loc1));
+ q_loc2 = q_loc1;
+ }
+ gamma = extract_h(L_sub( op1, op2));
+ gamma = shl(gamma, q_loc2);
+ }
+ ELSE
+ {
+ gamma = 0;
+ move16();
+ }
+
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ /* Create L and R signals with the correct coherence by mixing channel 0 (pDFT_DMX) and channel 1 (pDFT_RES) */
+ DFT_L[2 * i] = Madd_32_16(Madd_32_16(pDFT_DMX[2 * i], pDFT_DMX[2 * i], g ) , pDFT_RES[2 * i], gamma);
+ move32();
+ DFT_R[2 * i] = Msub_32_16(Msub_32_16(pDFT_DMX[2 * i], pDFT_DMX[2 * i], g ) , pDFT_RES[2 * i], gamma);
+ move32();
+
+ DFT_L[2 * i + 1] = Madd_32_16(Madd_32_16(pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1], g) , pDFT_RES[2 * i + 1], gamma);
+ move32();
+ DFT_R[2 * i + 1] = Msub_32_16(Msub_32_16(pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1], g) , pDFT_RES[2 * i + 1], gamma);
+ move32();
+ }
+
+ IF ( NE_32(pgIpd[0] , 0) )
+ {
+ Word32 theta = pgIpd[0];
+ WHILE(GT_32(theta , EVS_2PI_FX))
+ {
+ theta = L_sub(theta, EVS_2PI_FX);
+ }
+ WHILE(LT_32(theta , -EVS_2PI_FX))
+ {
+ theta = L_add(theta, EVS_2PI_FX);
+ }
+ c0 = getCosWord16( extract_l(theta));
+ IF (EQ_16(c0, ONE_IN_Q14))
+ {
+ c0 = MAX_16;
+ }
+ ELSE
+ {
+ c0 = shl(c0, 1);
+ }
+ s0 = getSinWord16( extract_l(theta));
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ /*rotate L*/
+ tmp = Msub_32_16(Mpy_32_16_1(DFT_L[2 * i], c0), DFT_L[2 * i + 1], s0);
+ DFT_L[2 * i + 1] = Madd_32_16(Mpy_32_16_1(DFT_L[2 * i], s0), DFT_L[2 * i + 1], c0);
+ move32();
+ DFT_L[2 * i] = tmp;
+ move32();
+ }
+ }
+ }
+ ELSE IF ( sba_dirac_stereo_flag && hMdDec )
+ {
+
+ IF ( EQ_16(nchan_transport , 1) )
+ {
+ IF ( sba_mono_flag )
+ {
+ IF ( EQ_16(b , 0) )
+ {
+ i = 0;
+ move16();
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS], pDFT_DMX[2 * i]);
+ move32();
+ DFT_L[2 * i] = DFT_W;
+ move32();
+ DFT_R[2 * i] = 0;
+ move32();
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS], pDFT_DMX[2 * i + 1]);
+ move32();
+ DFT_L[2 * i + 1] = DFT_W;
+ move32();
+ DFT_R[2 * i + 1] = 0;
+ move32();
+ }
+ FOR ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ )
+ {
+ DFT_W = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]),
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[0][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i]);
+ DFT_L[2 * i] = DFT_W;
+ move32();
+ DFT_R[2 * i] = 0;
+ move32();
+
+ DFT_W = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]),
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[0][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i + 1]);
+ DFT_L[2 * i + 1] = DFT_W;
+ move32();
+ DFT_R[2 * i + 1] = 0;
+ move32();
+ }
+ FOR ( ; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+ DFT_L[2 * i] = DFT_W;
+ move32();
+ DFT_R[2 * i] = 0;
+ move32();
+
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+ DFT_L[2 * i + 1] = DFT_W;
+ move32();
+ DFT_R[2 * i + 1] = 0;
+ move32();
+ }
+ }
+ ELSE
+ {
+ IF ( EQ_16(b , 0) )
+ {
+ i = 0;
+ move16();
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+ DFT_Y = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+
+ DFT_L[2 * i] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i] = L_sub(DFT_W , DFT_Y);
+ move32();
+
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+ DFT_Y = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(DFT_W , DFT_Y);
+ move32();
+ }
+ FOR ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ )
+ {
+ DFT_W = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]) ,
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[0][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i]);
+ DFT_Y = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]) ,
+ L_add( hStereoDft->mixer_mat_smooth_fx[1][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[1][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i]);
+
+ DFT_L[2 * i] = L_add(DFT_W, DFT_Y);
+ move32();
+ DFT_R[2 * i] = L_sub(DFT_W, DFT_Y);
+ move32();
+
+ DFT_W = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]) ,
+ L_add( hStereoDft->mixer_mat_smooth_fx[0][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[0][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[0][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i + 1]);
+ DFT_Y = Madd_32_32(Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]) ,
+ L_add( hStereoDft->mixer_mat_smooth_fx[1][1][b + k * IVAS_MAX_NUM_BANDS] ,
+ L_add(hStereoDft->mixer_mat_smooth_fx[1][2][b + k * IVAS_MAX_NUM_BANDS] ,
+ hStereoDft->mixer_mat_smooth_fx[1][3][b + k * IVAS_MAX_NUM_BANDS])),
+ DFT_PRED_RES[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(DFT_W , DFT_Y);
+ move32();
+ }
+ FOR ( ; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+ DFT_Y = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+
+ DFT_L[2 * i] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i] = L_sub(DFT_W , DFT_Y);
+ move32();
+
+ DFT_W = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[0][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+ DFT_Y = Mpy_32_32(hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(DFT_W , DFT_Y);
+ move32();
+ }
+ }
+ }
+ ELSE IF ( GE_16(nchan_transport , 2) )
+ {
+ IF ( EQ_16(b , 0) )
+ {
+ i = 0;
+ move32();
+
+ DFT_W = pDFT_DMX[2 * i];
+ move32();
+ DFT_Y = Madd_32_32(pDFT_DMX1[2 * i], hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+
+ DFT_L[2 * i] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i] = L_sub(DFT_W , DFT_Y);
+ move32();
+
+ DFT_W = pDFT_DMX[2 * i + 1];
+ move32();
+ DFT_Y = Madd_32_32(pDFT_DMX1[2 * i + 1], hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(DFT_W , DFT_Y);
+ move32();
+ }
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ DFT_W = pDFT_DMX[2 * i];
+ move32();
+ DFT_Y = Madd_32_32(pDFT_DMX1[2 * i], hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i]);
+
+ DFT_L[2 * i] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i] = L_sub(DFT_W , DFT_Y);
+ move32();
+
+ DFT_W = pDFT_DMX[2 * i + 1];
+ move32();
+ DFT_Y = Madd_32_32(pDFT_DMX1[2 * i + 1], hStereoDft->mixer_mat_smooth_fx[1][0][b + k * IVAS_MAX_NUM_BANDS] , pDFT_DMX[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(DFT_W , DFT_Y);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(DFT_W , DFT_Y);
+ move32();
+ }
+ }
+ ELSE
+ {
+ assert( "nhcan_transport must be 1 or 1!" );
+ }
+ }
+ ELSE
+ {
+ FOR ( i = hStereoDft->band_limits[b]; i < min( stop, hStereoDft->band_limits[b + 1] ); i++ )
+ {
+ tmp = L_add(Madd_32_16(pDFT_RES[2 * i], pDFT_DMX[2 * i], g) , DFT_PRED_RES[2 * i]);
+
+ DFT_L[2 * i] = L_add(pDFT_DMX[2 * i] , tmp);
+ move32();
+ DFT_R[2 * i] = L_sub(pDFT_DMX[2 * i] , tmp);
+ move32();
+
+ tmp = L_add(Madd_32_16(pDFT_RES[2 * i + 1], pDFT_DMX[2 * i + 1], g) , DFT_PRED_RES[2 * i + 1]);
+
+ DFT_L[2 * i + 1] = L_add(pDFT_DMX[2 * i + 1] , tmp);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(pDFT_DMX[2 * i + 1] , tmp);
+ move32();
+
+ }
+
+ FOR ( ; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ tmp = Madd_32_16(pDFT_RES[2 * i], pDFT_DMX[2 * i], g);
+
+ DFT_L[2 * i] = L_add(pDFT_DMX[2 * i] , tmp);
+ move32();
+ DFT_R[2 * i] = L_sub(pDFT_DMX[2 * i] , tmp);
+ move32();
+
+ tmp = Madd_32_16(pDFT_RES[2 * i + 1], pDFT_DMX[2 * i + 1], g);
+
+ DFT_L[2 * i + 1] = L_add(pDFT_DMX[2 * i + 1] , tmp);
+ move32();
+ DFT_R[2 * i + 1] = L_sub(pDFT_DMX[2 * i + 1] , tmp);
+ move32();
+
+ }
+
+ /* Active Upmix */
+ IF ( NE_32(pgIpd[0] , 0) )
+ {
+ Word32 theta = pgIpd[0];
+ WHILE(GT_32(theta , EVS_2PI_FX))
+ {
+ theta = L_sub(theta, EVS_2PI_FX);
+ }
+ WHILE(LT_32(theta , -EVS_2PI_FX))
+ {
+ theta = L_add(theta, EVS_2PI_FX);
+ }
+ c0 = getCosWord16( extract_l(theta) );
+ IF (EQ_16(c0, ONE_IN_Q14))
+ {
+ c0 = MAX_16;
+ }
+ ELSE
+ {
+ c0 = shl(c0, 1);
+ }
+ s0 = getSinWord16( extract_l(theta) );
+ FOR ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
+ {
+ /*rotate L*/
+ tmp = Msub_32_16(Mpy_32_16_1(DFT_L[2 * i], c0), DFT_L[2 * i + 1], s0);
+ DFT_L[2 * i + 1] = Madd_32_16(Mpy_32_16_1(DFT_L[2 * i], s0), DFT_L[2 * i + 1], c0);
+ move32();
+ DFT_L[2 * i] = tmp;
+ move32();
+ }
+ }
+ }
+ }
+
+ IF ( hStereoDft->frame_sid_nodata || EQ_16(st0->VAD , 0) )
+ {
+ hFdCngDec->cna_band_limits[hFdCngDec->cna_nbands] = hStereoDft->band_limits[hFdCngDec->cna_nbands];
+ move16();
+ }
+
+ IF ( hStereoDft->frame_sid_nodata && !sba_dirac_stereo_flag )
+ {
+ hStereoCng->first_SID = 0;
+ move16();
+ hStereoCng->first_SID_after_TD = 0;
+ move16();
+ }
+
+ FOR ( i = hStereoDft->band_limits[b]; i < shr(hStereoDft->NFFT , 1); i++ )
+ {
+ DFT_L[2 * i] = 0;
+ move32();
+ DFT_L[2 * i + 1] = 0;
+ move32();
+ DFT_R[2 * i] = 0;
+ move32();
+ DFT_R[2 * i + 1] = 0;
+ move32();
+ }
+
+ /*Nyquist Freq.*/
+ IF ( EQ_16(hStereoDft->band_limits[b] , shr(hStereoDft->NFFT , 1 )))
+ {
+ DFT_L[1] = L_add(pDFT_DMX[1] , Mpy_32_16_1(pDFT_DMX[1], g));
+ move32();
+ DFT_R[1] = L_sub(pDFT_DMX[1] , Mpy_32_16_1(pDFT_DMX[1], g));
+ move32();
+ DFT_L[1] = Mpy_32_16_1(DFT_L[1], INV_SQRT_2_FX);
+ move32();
+ DFT_R[1] = Mpy_32_16_1(DFT_R[1], INV_SQRT_2_FX);
+ move32();
+ }
+ ELSE
+ {
+ DFT_L[1] = 0;
+ move32();
+ DFT_R[1] = 0;
+ move32();
+ }
+ }
+ ELSE
+ {
+ pPredGain = NULL; /* to avoid compilation warnings */
+ pSideGain = NULL;
+
+ /* Dummy upmix-> mono binauralization */
+ FOR ( i = 0; i < hStereoDft->NFFT; i++ )
+ {
+ DFT_L[i] = L_add( pDFT_DMX[i] , pDFT_RES[i] );
+ move32();
+ DFT_R[i] = L_sub( pDFT_DMX[i] , pDFT_RES[i] );
+ move32();
+ }
+ }
+
+ /* Comfort Noise Addition */
+ IF ( st0->flag_cna )
+ {
+ ptr_per = &hFdCngDec->smoothed_psd_fx[hFdCngCom->startBand];
+
+ scale_fact0 = 0;
+ move16();
+ IF ( GT_16(hFdCngDec->cna_rescale_fact_fx , 0) )
+ {
+ Word16 q_scale_fact0 = 0;
+ Word16 op = Sqrt16( shr(hFdCngDec->cna_rescale_fact_fx, 1), &q_scale_fact0);
+ move16();
+ scale_fact0 = L_mult0(shr(output_frame , 1) , op);
+ IF (GT_16(q_scale_fact0, 0))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ scale_fact0 = L_shl(scale_fact0, q_scale_fact0);
+ }
+ }
+
+ FOR ( b = 0; b < hFdCngDec->cna_nbands; b++ )
+ {
+ /* calculate gamma factor reflecting inter-channel correlation and side gain (ILD) */
+ coh = hFdCngDec->cna_cm_fx[b];
+ move16();
+ g = hFdCngDec->cna_g_state_fx[b];
+ move16();
+ IF ( LT_16(coh , (Word16)(0x7333)) )
+ {
+ Word32 op1, op2, l_gamma;
+ Word16 q_loc1, q_loc2, q_gamma;
+ gamma = coh;
+ move16();
+ gamma = BASOP_Util_Divide3232_Scale(gamma , sub( (Word16)0x7FFF, gamma), &q_gamma);
+ IF (EQ_16(gamma, 0))
+ {
+ q_gamma = 0;
+ }
+ l_gamma = L_deposit_l(gamma);
+ op1 = L_add(l_gamma, L_shr(L_deposit_l(sub(MAX_16 , mult(g, g))), q_gamma));
+ q_loc2 = Q16 + q_gamma;
+ q_loc1 = q_loc2;
+ op1 = Sqrt32(op1, &q_loc1);
+ op2 = Sqrt32(l_gamma, &q_loc2);
+ IF (NE_32(op2, 0))
+ {
+ IF (NE_16(q_loc1, q_loc2))
+ {
+ op2 = L_shl(op2, sub(q_loc2, q_loc1));
+ q_loc2 = q_loc1;
+ }
+ gamma = extract_h(L_sub( op1, op2));
+ gamma = shl(gamma, q_loc2);
+ }
+ ELSE
+ {
+ gamma = extract_h(L_shl(op1, q_loc1));
+ }
+ }
+ ELSE
+ {
+ gamma = 0;
+ }
+
+ FOR ( i = s_max( hFdCngDec->cna_band_limits[b], shr(hFdCngCom->startBand , 2) ); i < s_min( hFdCngDec->cna_band_limits[b + 1], (L_FRAME16k) >> 1 ); i++ )
+ {
+ Word32 l_tmp;
+ lev1 = *ptr_per++;
+ move32();
+ lev2 = *ptr_per++;
+ move32();
+
+ IF ( GT_32(lev1 , 0) && GT_32(lev2 , 0) && GT_32( Mpy_32_16_1(L_max( lev1, lev2 ), (Word16)0x6AAB) , L_min( lev1, lev2 )))
+ {
+ /* take the minimum of two adjacent frequency bins */
+ cna_level = L_min( lev1, lev2 );
+ }
+ ELSE
+ {
+ /* take the average of two adjacent frequency bins */
+ cna_level = L_add(L_shr( lev1, 1) , L_shr(lev2 , 1));
+ }
+ q_cna_level = sub(Q31 , hFdCngDec->q_smoothed_psd);
+ move16();
+ l_tmp = Sqrt32( cna_level, &q_cna_level);
+ scale_fact = Mpy_32_32(l_tmp, scale_fact0);
+ /*
+ scale_fact0 will be in Q15 by the time the above operation is performed
+ so the q of scale_fact represented now by q_cna_level has to be updated
+ */
+ q_cna_level = sub(Q31, add(q_cna_level, Q16));
+
+ /* generate comfort noise from gaussian noise and add to the decoded DFT spectrum */
+ N1 = L_shl(Mpy_32_16_1(scale_fact , rand_gauss_fix( &ftmp, cna_seed )), Q2);
+ N2 = L_shl(Mpy_32_16_1(scale_fact , rand_gauss_fix( &ftmp, cna_seed )), Q2);
+ l_tmp = L_add(Madd_32_16(N1, N1, g) , Mpy_32_16_1(N2, gamma));
+ l_tmp = L_shr(l_tmp, sub(q_cna_level, hStereoDft->q_dft));
+ DFT_L[2 * i] = L_add(DFT_L[2 * i], l_tmp);
+ move32();
+ l_tmp = L_sub(Msub_32_16(N1, N1, g) , Mpy_32_16_1(N2, gamma));
+ l_tmp = L_shr(l_tmp, sub(q_cna_level, hStereoDft->q_dft));
+ DFT_R[2 * i] = L_add(DFT_R[2 * i], l_tmp);
+ move32();
+
+ N1 = L_shl(Mpy_32_16_1(scale_fact , rand_gauss_fix( &ftmp, cna_seed )), Q2);
+ N2 = L_shl(Mpy_32_16_1(scale_fact , rand_gauss_fix( &ftmp, cna_seed )), Q2);
+ l_tmp = L_add(Madd_32_16(N1, N1, g) , Mpy_32_16_1(N2, gamma));
+ l_tmp = L_shr(l_tmp, sub(q_cna_level, hStereoDft->q_dft));
+ DFT_L[2 * i + 1] = L_add(DFT_L[2 * i + 1] , l_tmp);
+ move32();
+ l_tmp = L_sub(Msub_32_16(N1, N1, g) , Mpy_32_16_1(N2, gamma));
+ l_tmp = L_shr(l_tmp, sub(q_cna_level, hStereoDft->q_dft));
+ DFT_R[2 * i + 1] = L_add(DFT_R[2 * i + 1] , l_tmp);
+ move32();
+ }
+ }
+
+ /* update CNA re-scaling factor */
+ hFdCngDec->cna_rescale_fact_fx = extract_l(L_shr(L_mult0((Word16)0x6666, hFdCngDec->cna_act_fact_fx), Q15));
+ IF ( !hFdCngDec->first_cna_noise_updated )
+ {
+ hFdCngDec->cna_rescale_fact_fx = 0;
+ move16();
+ }
+ }
+
+ /* Update memories */
+ hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + 1 ) & (STEREO_DFT_PAST_MAX - 1);
+ Copy32( pDFT_DMX, hStereoDft->DFT_past_DMX_fx[hStereoDft->past_DMX_pos], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
+ hStereoDft->q_past_dft = hStereoDft->q_dft;
+ IF ( pPredGain )
+ {
+ stereo_dft_adapt_sf_delay_fx( hStereoDft, pPredGain );
+ }
+
+ Copy32( DFT_L, DFT[0] + k * STEREO_DFT32MS_N_MAX, hStereoDft->NFFT );
+ Copy32( DFT_R, DFT[1] + k * STEREO_DFT32MS_N_MAX, hStereoDft->NFFT );
+ }
+
+ IF ( st0->bfi && !prev_bfi )
+ {
+ Word16 q_shift = shl(sub(hStereoDft->q_dft, hStereoDft->q_past_dft), 1);
+ idx_k0 = add( hStereoDft->past_DMX_pos , STEREO_DFT_PAST_MAX - 1 ) & (STEREO_DFT_PAST_MAX - 1);
+ idx_k1 = add( idx_k0 , 1 ) & (STEREO_DFT_PAST_MAX - 1);
+ /*dmx energy memory*/
+ hStereoDft->past_dmx_nrg_fx = stereo_dft_dmx_swb_nrg_fx( hStereoDft->DFT_past_DMX_fx[idx_k0], hStereoDft->DFT_past_DMX_fx[idx_k1], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
+ hStereoDft->past_dmx_nrg_fx = L_shr(hStereoDft->past_dmx_nrg_fx, q_shift);
+ }
+
+ stereo_dft_compute_td_stefi_params_fx( hStereoDft, samp_ratio );
+
+ return;
+}
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_compute_td_stefi_params_fx()
+ *
+ *
+ *-------------------------------------------------------------------------*/
+
+static void stereo_dft_compute_td_stefi_params_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 samp_ratio /* i : sampling ratio */
+)
+{
+ Word16 pdmx_ind;
+ Word32 g2;
+ Word16 bin0;
+ Word16 band0;
+ Word16 b;
+ Word16 nbands;
+ Word16 bres;
+ Word32 wsum;
+ Word32 pred_gain_avg, pred_g;
+ Word16 shift_g;
+ Word16 q_pred_g, q_pred_gain_avg;
+ Word32 nrg_DMX, nrg_pred_DMX;
+ Word32 op1;
+ Word16 q_div, q_sqrt;
+
+ pdmx_ind = hStereoDft->past_DMX_pos;
+ move16();
+ bres = hStereoDft->band_res[1];
+ move16();
+
+ IF ( NE_16(hStereoDft->core_hist[1], ACELP_CORE) || hStereoDft->wasTransient )
+ {
+ hStereoDft->td_gain_fx[0] = 0;
+ move32();
+ hStereoDft->q_td_gain[0] = 0;
+ move16();
+ return;
+ }
+
+ bin0 = extract_l( L_shr_r(Mpy_32_16_1((Word32)hStereoDft->NFFT, samp_ratio), 1) );
+ bin0 = shl(bin0, Q3);
+ bin0 = s_min( bin0, hStereoDft->band_limits[hStereoDft->nbands] );
+ b = hStereoDft->nbands;
+ move16();
+ WHILE ( GT_16(hStereoDft->band_limits[b], bin0) )
+ {
+ b--;
+ }
+ band0 = b;
+
+ /* calculate averages over high bands */
+ pred_g = pred_gain_avg = 0;
+ move32(); move32();
+ nbands = 0;
+ move16();
+ wsum = 0;
+ move32();
+ shift_g = Q15 - norm_s(sub(hStereoDft->nbands, band0));
+ FOR ( b = band0; b < hStereoDft->nbands; b++ )
+ {
+ IF ( LT_32(L_min( hStereoDft->past_res_pred_gain_fx[STEFI_DELAY_IND( STEREO_DFT_TD_STEFI_SUBFR_DELAY + 1, pdmx_ind )][b], hStereoDft->past_res_pred_gain_fx[STEFI_DELAY_IND( STEREO_DFT_TD_STEFI_SUBFR_DELAY + 2, pdmx_ind )][b] ), 0) )
+ {
+ hStereoDft->td_gain_fx[0] = 0;
+ move32();
+ hStereoDft->q_td_gain[0] = 0;
+ move16();
+ return;
+ }
+ pred_g = L_add(pred_g, L_shr(Mpy_32_16_1(L_add( L_shr(hStereoDft->res_pred_gain_fx[b + STEREO_DFT_BAND_MAX], 1) ,
+ L_shr(hStereoDft->res_pred_gain_fx[b + 2 * STEREO_DFT_BAND_MAX], 1) ),
+ dft_res_pred_weights_fx[bres][b - band0]), shift_g));
+ pred_gain_avg = L_add(pred_gain_avg, L_shr(Mpy_32_16_1( L_add(L_shr(hStereoDft->past_res_pred_gain_fx[STEFI_DELAY_IND( STEREO_DFT_TD_STEFI_SUBFR_DELAY + 2, pdmx_ind )][b] , 1),
+ L_shr(hStereoDft->past_res_pred_gain_fx[STEFI_DELAY_IND( STEREO_DFT_TD_STEFI_SUBFR_DELAY + 1, pdmx_ind )][b] , 1 )),
+ dft_res_pred_weights_fx[bres][b - band0]), shift_g));
+
+ nbands++;
+ wsum = L_add(wsum, dft_res_pred_weights_fx[bres][b - band0]);
+#ifdef DBG_TD_STEFI
+ printf( "frame: %d\tband: %-2d\tpred_gain1: %f\tpred_gain2: %f\tppg1: %f\tppg2: %f\n", frame, b, hStereoDft->res_pred_gain[b + STEREO_DFT_BAND_MAX], hStereoDft->res_pred_gain[b + 2 * STEREO_DFT_BAND_MAX], hStereoDft->past_res_pred_gain[STEREO_DFT_TD_STEFI_SUBFR_DELAY - 2][b], hStereoDft->past_res_pred_gain[d_short - 1][b] );
+#endif
+ }
+
+ IF ( EQ_16(nbands, 0) )
+ {
+ /* apparently, there is nothing to do here */
+ hStereoDft->td_gain_fx[0] = 0;
+ move32();
+ hStereoDft->q_td_gain[0] = 0;
+ move16();
+ return;
+ }
+ wsum = L_shl(wsum, sub(Q16 , shift_g));
+ pred_g = BASOP_Util_Divide3232_Scale(pred_g, wsum, &q_div);
+ IF (GT_16(q_div, 16))
+ {
+ pred_g = L_shl(pred_g, 16);
+ q_pred_g = sub(q_div , 16);
+ }
+ ELSE
+ {
+ pred_g = L_shl(pred_g, q_div);
+ q_pred_g = 0;
+ }
+ pred_gain_avg = BASOP_Util_Divide3232_Scale(pred_gain_avg, wsum, &q_div);
+ IF (GT_16(q_div, 16))
+ {
+ pred_gain_avg = L_shl(pred_gain_avg, 16);
+ q_pred_gain_avg = sub(q_div , 16);
+ }
+ ELSE
+ {
+ pred_gain_avg = L_shl(pred_gain_avg, q_div);
+ q_pred_gain_avg = 0;
+ }
+ nrg_DMX = hStereoDft->hb_nrg_fx[0];
+ nrg_pred_DMX = hStereoDft->hb_nrg_fx[1];
+
+ op1 = BASOP_Util_Divide3232_Scale(L_add( EPSILON_FIX , nrg_DMX ) , L_add( EPSILON_FIX , nrg_pred_DMX ), &q_div);
+ q_sqrt = Q16 + q_div;
+ op1 = Sqrt32(op1, &q_sqrt);
+ g2 = Mpy_32_32(pred_g , op1);
+ IF (LT_16(q_sqrt, 0))
+ {
+ g2 = L_shl(g2, q_sqrt);
+ q_sqrt = 0;
+ }
+ ELSE IF ( NE_16(q_sqrt, 0))
+ {
+ IF (LT_32(L_shr(pred_gain_avg, q_sqrt), g2))
+ {
+ g2 = pred_gain_avg;
+ }
+ ELSE
+ {
+ g2 = L_min( Mpy_32_16_1(L_shr(pred_gain_avg, q_sqrt) , STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(L_shr(pred_gain_avg, q_sqrt) , sub( (Word16)0x7FFF , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )),
+ g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+ g2 = L_shl(g2, q_sqrt);
+ }
+ }
+ ELSE
+ {
+ g2 = L_min( Mpy_32_16_1(pred_gain_avg , STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(pred_gain_avg , sub( (Word16)0x7FFF , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )),
+ g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+ }
+
+ hStereoDft->td_gain_fx[0] = g2;
+ move32();
+ if (q_pred_gain_avg != 0)
+ hStereoDft->q_td_gain[0] = q_pred_gain_avg;
+ move16();
+
+#ifdef DBG_TD_STEFI
+ printf( "frame: %d\tpred_gain: %f\tpred_gain_avg: %f\tg2_0: %f\tgain: %f\n", frame, pred_gain, pred_gain_avg, g2, hStereoDft->td_gain[0] );
+ printf( "nrg_DMX: %f\tnrd_pred_DMX: %f\tnbands: %d\tbin0: %d\n", nrg_DMX, nrg_pred_DMX, hStereoDft->nbands, bin0 );
+ /*printf( "td_gain: %f\n", hStereoDft->td_gain[0] );*/
+#endif
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * stereo_dft_generate_res_pred_fx()
+ *
+ *
+ *-------------------------------------------------------------------------*/
+void stereo_dft_generate_res_pred_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */
+ const Word16 samp_ratio, /* i : sampling ratio */
+ Word32 *pDFT_DMX, /* i : downmix signal */
+ Word32 *DFT_PRED_RES, /* o : residual prediction signal */
+ Word32 *pPredGain, /* i : residual prediction gains */
+ const Word16 k, /* i : subframe index */
+ Word32 *ap_filt_DMX, /* i : enhanced stereo filling signal */
+ Word16 *stop, /* o : last FD stereo filling bin */
+ const Word16 bfi /* i : BFI flag */
+)
+{
+ /* general variables */
+ Word16 i, b;
+ Word16 begin, end;
+ Word16 bin0, band0; /* ESF->Stefi crossover bin/band */
+ Word16 lb_stefi_start_band;
+
+ /* variables for enhanced stereo filling */
+ Word16 norm_fac, q_norm_fac = 0, lim_norm_fac;
+ Word16 q_sqrt;
+ Word16 alpha, gain_limit;
+
+ /* variables for stereo filling */
+ Word16 d_long, d_short, d_long_ind, d_short_ind;
+ Word16 g_short, g_long;
+ Word32 dmx_nrg, rev_nrg;
+ Word32 past_dmx_nrg;
+ Word32 pred_gain_avg;
+ Word32 g2;
+ Word16 nbands_respred;
+
+ push_wmops( "gen_respred" );
+
+ /* smoothing and limiting parameters */
+ alpha = hStereoDft->wasTransient ? 0 : (Word16)(0x199A); /* no smoothing after transients */
+ gain_limit = 0x7FFF; // 2.0 in Q14
+ move16();
+
+ /* residual prediction only used up to 16 kHz (SWB) */
+ nbands_respred = s_min( hStereoDft->nbands, STEREO_DFT_RES_PRED_BAND_MAX );
+
+ /* In ACELP mode the downmix signal is not available in bandwidth extension area. *
+ * Therefore, the downmix energy in the corresponding subbands is estimated. */
+ bin0 = (Word16) (L_shr(L_add(L_mult0(hStereoDft->NFFT, samp_ratio), ONE_IN_Q12), Q12 + 1));
+ move16();
+ bin0 = s_min( bin0, hStereoDft->band_limits[hStereoDft->nbands] );
+ b = hStereoDft->nbands;
+ move16();
+ WHILE ( GE_16(hStereoDft->band_limits[b], bin0) )
+ {
+ b--;
+ }
+ band0 = b;
+ move16();
+
+ IF ( LT_16(hStereoDft->res_pred_mode[k + STEREO_DFT_OFFSET], STEREO_DFT_RESPRED_ESF) )
+ {
+ /* no ESF signal available, use stereo filling over whole spectrum */
+ lb_stefi_start_band = s_max( hStereoDft->res_pred_band_min, hStereoDft->res_cod_band_max );
+ }
+ ELSE
+ {
+ /* ESF signal available, use ESF in lowband, stereo filling in highband */
+ lb_stefi_start_band = s_max( band0, hStereoDft->res_cod_band_max );
+ }
+
+ IF ( bfi )
+ {
+ lb_stefi_start_band = 0;
+ move16();
+ }
+
+ /* lowband: use ESF if available, else use stereo filling */
+ IF ( EQ_16(hStereoDft->res_pred_mode[k + STEREO_DFT_OFFSET], STEREO_DFT_RESPRED_ESF) )
+ {
+ /* ESF in lowband */
+ /* main loop over core region*/
+ FOR ( b = hStereoDft->res_cod_band_max; b <= band0; b++ )
+ {
+ dmx_nrg = EPSILON_FIX;
+ move32();
+ rev_nrg = EPSILON_FIX;
+ move32();
+
+ /* calculate band energies (low band only in case of ACELP) */
+ FOR ( i = hStereoDft->band_limits[b]; i < s_min( hStereoDft->band_limits[b + 1], bin0 ); i++ )
+ {
+ dmx_nrg = L_add(dmx_nrg,
+ Madd_32_32(Mpy_32_32(pDFT_DMX[2 * i], pDFT_DMX[2 * i]),
+ pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1]));
+ rev_nrg = L_add(rev_nrg,
+ Madd_32_32(Mpy_32_32(ap_filt_DMX[2 * i], ap_filt_DMX[2 * i]),
+ ap_filt_DMX[2 * i + 1], ap_filt_DMX[2 * i + 1]));
+ }
+ IF (LT_16(hStereoDft->q_smoothed_nrg , hStereoDft->q_dft))
+ {
+ rev_nrg = L_shr(rev_nrg, shl(sub(hStereoDft->q_dft, hStereoDft->q_smoothed_nrg), 1));
+ dmx_nrg = L_shr(dmx_nrg, shl(sub(hStereoDft->q_dft, hStereoDft->q_smoothed_nrg), 1));
+ }
+ ELSE IF (GT_16(hStereoDft->q_smoothed_nrg , hStereoDft->q_dft))
+ {
+ hStereoDft->smooth_res_nrg_fx[b] = L_shr(hStereoDft->smooth_res_nrg_fx[b], shl(sub(hStereoDft->q_smoothed_nrg, hStereoDft->q_dft), 1));
+ hStereoDft->smooth_dmx_nrg_fx[b] = L_shr(hStereoDft->smooth_dmx_nrg_fx[b], shl(sub(hStereoDft->q_smoothed_nrg, hStereoDft->q_dft), 1));
+ }
+ /* smoothing */
+ hStereoDft->smooth_res_nrg_fx[b] = Madd_32_16(Mpy_32_16_1(hStereoDft->smooth_res_nrg_fx[b], alpha), rev_nrg, sub( (Word16)(0x7FFF), alpha )) ;
+ move32();
+ hStereoDft->smooth_dmx_nrg_fx[b] = Madd_32_16(Mpy_32_16_1(hStereoDft->smooth_dmx_nrg_fx[b], alpha), dmx_nrg, sub( (Word16)(0x7FFF), alpha )) ;
+ move32();
+
+ /* normalization factor */
+ IF (NE_32(hStereoDft->smooth_res_nrg_fx[b], 0))
+ {
+ norm_fac = BASOP_Util_Divide3232_Scale(hStereoDft->smooth_dmx_nrg_fx[b], hStereoDft->smooth_res_nrg_fx[b], &q_norm_fac);
+ norm_fac = Sqrt16(norm_fac, &q_norm_fac);
+ IF (NE_16(norm_fac, 0))
+ {
+ /* gain compressor */
+ IF (LE_16(q_norm_fac, -Q1) || (EQ_16(q_norm_fac, Q1) && GT_16((Word16)0x3333, norm_fac)) || (EQ_16(q_norm_fac, 0) && GT_16((Word16)0x6666, norm_fac)))
+ {
+ lim_norm_fac = (Word16)0x5000;
+ }
+ ELSE IF (GT_16(q_norm_fac, Q1) || (EQ_16(q_norm_fac, Q1) && LT_16((Word16)0x5000, norm_fac)) || (EQ_16(q_norm_fac, 0) && GT_16((Word16)0x6666, norm_fac)))
+ {
+ lim_norm_fac = (Word16)0x3333;
+ }
+ ELSE
+ {
+ lim_norm_fac = norm_fac;
+ }
+ IF (EQ_16(lim_norm_fac, norm_fac))
+ {
+ norm_fac = ONE_IN_Q14;
+ q_norm_fac = Q1;
+ }
+ ELSE
+ {
+ norm_fac = extract_l(L_shr(L_mult0(norm_fac, lim_norm_fac), Q15));
+ q_norm_fac = add(q_norm_fac, 1);
+ IF (LT_16(q_norm_fac, 0 ))
+ {
+ norm_fac = shl(norm_fac, q_norm_fac);
+ q_norm_fac = 0;
+ }
+ ELSE IF (GT_16(q_norm_fac, 2) && LT_16(norm_s(norm_fac) , sub(q_norm_fac, Q1)))
+ {
+ norm_fac = MAX_16;
+ q_norm_fac = Q1;
+ }
+ }
+ }
+ }
+ ELSE
+ {
+ norm_fac = MAX_16;
+ q_norm_fac = Q1;
+ }
+
+ FOR ( i = hStereoDft->band_limits[b]; i < s_min( hStereoDft->band_limits[b + 1], bin0 ); i++ )
+ {
+ DFT_PRED_RES[2 * i] = L_shl(Mpy_32_32(Mpy_32_16_1(pPredGain[b], norm_fac), ap_filt_DMX[2 * i]), q_norm_fac);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = L_shl(Mpy_32_32(Mpy_32_16_1(pPredGain[b], norm_fac), ap_filt_DMX[2 * i + 1]), q_norm_fac);
+ move32();
+ }
+ }
+ IF (GT_16(hStereoDft->q_smoothed_nrg , hStereoDft->q_dft))
+ {
+ hStereoDft->q_smoothed_nrg = hStereoDft->q_dft;
+ }
+ }
+ ELSE IF ( EQ_16(hStereoDft->res_pred_mode[k + STEREO_DFT_OFFSET], STEREO_DFT_RESPRED_STEFI) )
+ {
+ /* stefi in lowband */
+ set_l( DFT_PRED_RES, 0, 2 * hStereoDft->band_limits[lb_stefi_start_band] );
+
+ FOR ( b = lb_stefi_start_band; b <= band0; b++ )
+ {
+ d_short_ind = add(sub(STEREO_DFT_PAST_MAX, STEREO_DFT_STEFFI_DELAY_SHORT), b & 1);
+ /* ToDo:Change the float operation here */
+ d_long_ind = max( 4, (int16_t) ( ( STEREO_DFT_PAST_MAX + 4 - 1 ) * ( (float) b / ( hStereoDft->nbands - 1 ) ) + 0.5f ) ) - 4;
+ move16();
+ /* make sure d_short really corresponds to a shorter or equally long delay than d_long (e.g. not always the case for
+ * STEREO_DFT_STEFFI_DELAY_SHORT=3 and STEREO_DFT_STEFFI_DELAY_LONG=4)*/
+ d_short_ind = max( d_short_ind, d_long_ind );
+ move16();
+
+ /* Even number of window sliding (assymmetric OLA) */
+ d_short_ind = shl( shr(d_short_ind, 1), 1 );
+ d_long_ind = shl(shr( d_long_ind, 1), 1 );
+
+ d_short = sub(STEREO_DFT_PAST_MAX, d_short_ind);
+ d_long = sub(STEREO_DFT_PAST_MAX, d_long_ind);
+
+ d_short_ind = add(add(d_short_ind, hStereoDft->past_DMX_pos), 1 ) % STEREO_DFT_PAST_MAX;
+ d_long_ind = add(add(d_long_ind, hStereoDft->past_DMX_pos), 1) % STEREO_DFT_PAST_MAX;
+
+ g_short = hStereoDft->stefi_short_gain_fx;
+ move16();
+ g_long = hStereoDft->stefi_long_gain_fx;
+ move16();
+
+ /* change mixing ratio if long and short delay are the same */
+ IF ( EQ_16(d_short, d_long) )
+ {
+ g_short = MAX_16;
+ move16();
+ g_long = 0;
+ move16();
+ }
+
+ /* Avoid transient components */
+ IF ( EQ_32(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], EVS_LW_MIN) && EQ_32(hStereoDft->past_res_pred_gain_fx[d_long_ind][b], EVS_LW_MIN) )
+ {
+ g_long = 0;
+ move16();
+ g_short = 0;
+ move16();
+ }
+ ELSE IF ( EQ_32(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], EVS_LW_MIN) )
+ {
+ g_long = MAX_16;
+ move16();
+ g_short = 0;
+ move16();
+ }
+ ELSE IF ( EQ_32(hStereoDft->past_res_pred_gain_fx[d_long_ind][b], EVS_LW_MIN) )
+ {
+ g_long = 0;
+ move16();
+ g_short = MAX_16;
+ move16();
+ }
+
+ IF ( GT_16(s_max( g_short, g_long ), 0) )
+ {
+ Word16 q_shift = sub(hStereoDft->q_dft, hStereoDft->q_past_dft);
+ past_dmx_nrg = EPSILON_FIX;
+ move32();
+ dmx_nrg = EPSILON_FIX;
+ move32();
+ FOR ( i = hStereoDft->band_limits[b]; i < min( bin0, hStereoDft->band_limits[b + 1] ); i++ )
+ {
+ dmx_nrg = Madd_32_32(Madd_32_32(dmx_nrg, pDFT_DMX[2 * i], pDFT_DMX[2 * i]), pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1]);
+
+ DFT_PRED_RES[2 * i] = L_shr(Madd_32_16(Mpy_32_16_1(hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i] , g_short), hStereoDft->DFT_past_DMX_fx[d_long_ind][2 * i], g_long ), q_shift);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = L_shr(Madd_32_16(Mpy_32_16_1(hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i + 1] , g_short), hStereoDft->DFT_past_DMX_fx[d_long_ind][2 * i + 1], g_long ), q_shift);
+ move32();
+ past_dmx_nrg = Madd_32_32(Madd_32_32(past_dmx_nrg, DFT_PRED_RES[2 * i], DFT_PRED_RES[2 * i]), DFT_PRED_RES[2 * i + 1], DFT_PRED_RES[2 * i + 1]);
+ }
+ IF (GT_16(hStereoDft->q_dft, hStereoDft->q_past_dft))
+ {
+ past_dmx_nrg = L_shl(past_dmx_nrg, shl(sub(hStereoDft->q_dft , hStereoDft->q_past_dft), 1));
+ }
+ ELSE
+ {
+ dmx_nrg = L_shl(dmx_nrg, shl(sub(hStereoDft->q_past_dft , hStereoDft->q_dft), 1));
+ }
+ IF ( !bfi || GE_16(b, hStereoDft->res_cod_band_max) )
+ {
+ Word16 q_div;
+ Word16 op;
+ op = BASOP_Util_Divide3232_Scale(( 1 + dmx_nrg ), ( 1 + past_dmx_nrg ), &q_div);
+ q_sqrt = q_div;
+ norm_fac = Sqrt16( op, &q_sqrt);
+ g2 = Mpy_32_16_1(pPredGain[b], norm_fac);
+ IF (LE_32(q_sqrt, norm_l(g2)))
+ {
+ g2 = L_shl(g2, q_sqrt);
+ pred_gain_avg = Madd_32_16(Mpy_32_16_1(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], g_short),
+ hStereoDft->past_res_pred_gain_fx[d_long_ind][b], g_long);
+
+ g2 = min( Mpy_32_16_1(pred_gain_avg, STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(pred_gain_avg, sub( MAX_16, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )),
+ g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+ }
+ ELSE
+ {
+ /* Multiplication with STEREO_DFT_STEFFI_GAIN_AMP_FX is avodided since the float value of
+ this constant is 1.0f */
+ g2 = Madd_32_16(Mpy_32_16_1(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], g_short),
+ hStereoDft->past_res_pred_gain_fx[d_long_ind][b], g_long);
+ }
+
+ FOR ( i = hStereoDft->band_limits[b]; i < min( bin0, hStereoDft->band_limits[b + 1] ); i++ )
+ {
+ DFT_PRED_RES[2 * i] = Mpy_32_32(g2, DFT_PRED_RES[2 * i]);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = Mpy_32_32(g2, DFT_PRED_RES[2 * i + 1]);
+ move32();
+ }
+ }
+ }
+ ELSE
+ {
+ set32_fx( DFT_PRED_RES + shl(hStereoDft->band_limits[b], 1), 0, shl( sub(min( bin0, hStereoDft->band_limits[b + 1] ), hStereoDft->band_limits[b]), 1) );
+ }
+ }
+ }
+
+ IF ( GT_16(hStereoDft->band_limits[nbands_respred], bin0) )
+ {
+ /* apply stereo filling in ACELP BWE region */
+ IF ( EQ_16(hStereoDft->core_hist[0], ACELP_CORE) && EQ_16(hStereoDft->core_hist[STEREO_DFT_STEFFI_DELAY_SHORT / 2], ACELP_CORE) )
+ {
+ /* ACELP -> ACELP: nothing to do */
+ *stop = bin0;
+ move16();
+ }
+ ELSE IF ( EQ_16(hStereoDft->core_hist[STEREO_DFT_STEFFI_DELAY_SHORT / 2], ACELP_CORE) )
+ {
+ /* ACELP -> TCX/HQ core transition */
+ /* calculate high band energy only */
+ dmx_nrg = EPSILON_FIX;
+ move32();
+ FOR ( i = bin0; i < shr(hStereoDft->NFFT, 1); i++ )
+ {
+ dmx_nrg = L_add(dmx_nrg, Madd_32_32(Mpy_32_32(pDFT_DMX[2 * i], pDFT_DMX[2 * i]), pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1]));
+ }
+
+ hStereoDft->hb_nrg_fx[0] = Mpy_32_32(dmx_nrg , L_shr(hStereoDft->NFFT, 1));
+ *stop = bin0;
+ move16();
+ }
+ ELSE IF ( EQ_16(hStereoDft->core_hist[0], ACELP_CORE) )
+ {
+ /* TCX/HQ core -> ACELP transition */
+ /* apply short delay only and blend to long/short gain */
+ dmx_nrg = hStereoDft->hb_nrg_subr_fx[k];
+ d_short_ind = STEREO_DFT_PAST_MAX - STEREO_DFT_TD_STEFI_SUBFR_DELAY;
+
+ d_short_ind = add( d_short_ind , add(hStereoDft->past_DMX_pos , 1) ) & (STEREO_DFT_PAST_MAX - 1);
+
+ /* calculate high band energy of past dmx */
+ past_dmx_nrg = EPSILON_FIX;
+ FOR ( i = bin0; i < s_min( shr(hStereoDft->NFFT , 1), STEREO_DFT32MS_N_32k / 2 ); i++ )
+ {
+ past_dmx_nrg = L_add(past_dmx_nrg, Madd_32_32(Mpy_32_32(hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i] , hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i]) , hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i + 1] , hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i + 1]));
+ }
+
+ FOR ( b = band0; b < nbands_respred; b++ )
+ {
+ g_short = LT_32(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], 0) ? 0 : add( ONE_IN_Q14, shr(hStereoDft->stefi_short_gain_fx, 1));
+
+ IF ( GT_16(g_short , 0) )
+ {
+ Word16 q_nrom_fac, q_divide, q_shift;
+ Word32 op = BASOP_Util_Divide3232_Scale( (EPSILON_FIX + dmx_nrg ) , ( EPSILON_FIX + past_dmx_nrg ) , &q_divide);
+ q_norm_fac = Q16 + q_divide + hStereoDft->q_hb_nrg_subr;
+ op = Sqrt32( op, &q_nrom_fac);
+ g2 = Mpy_32_32(pPredGain[b], op);
+ pred_gain_avg = Mpy_32_16_1(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], g_short);
+ IF ( NE_16(q_norm_fac, 0))
+ {
+ IF (LT_32(L_shr(pred_gain_avg, q_norm_fac), g2))
+ {
+ g2 = pred_gain_avg;
+ }
+ ELSE
+ {
+ g2 = L_min( Mpy_32_16_1(L_shr(pred_gain_avg, q_norm_fac) , STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(L_shr(pred_gain_avg, q_norm_fac) , sub( (Word16)0x7FFF , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )),
+ g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+ g2 = L_shl(g2, q_norm_fac);
+ }
+ }
+ ELSE
+ {
+ g2 = L_min( Mpy_32_16_1(pred_gain_avg , STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(pred_gain_avg , sub( (Word16)0x7FFF , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )),
+ g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+ }
+ q_shift = sub(hStereoDft->q_dft, hStereoDft->q_past_dft);
+ move16();
+ FOR ( i = max( hStereoDft->band_limits[b], bin0 ); i < min( hStereoDft->band_limits[b + 1], STEREO_DFT32MS_N_32k / 2 ); i++ )
+ {
+ DFT_PRED_RES[2 * i] = L_shr(Mpy_32_32(g2 , hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i]), q_shift);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = L_shr(Mpy_32_32(g2 , hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i + 1]), q_shift);
+ move32();
+ }
+ }
+ ELSE
+ {
+ begin = max( hStereoDft->band_limits[b], bin0 );
+ move16();
+ end = min( hStereoDft->band_limits[b + 1], STEREO_DFT32MS_N_32k / 2 );
+ move16();
+ set_l( DFT_PRED_RES + 2 * begin, 0, 2 * ( end - begin ) );
+ }
+ }
+ }
+ ELSE
+ {
+ FOR ( b = band0; b < nbands_respred; b++ )
+ {
+ /* TCX/HQ core -> TCX/HQ core: business as usual */
+ d_short_ind = STEREO_DFT_PAST_MAX - STEREO_DFT_STEFFI_DELAY_SHORT + b & 1;
+ move16();
+ d_long_ind = max( 4, (int16_t) ( ( STEREO_DFT_PAST_MAX + 4 - 1 ) * ( (float) b / ( hStereoDft->nbands - 1 ) ) + 0.5f ) ) - 4;
+ move16();
+ /* make sure d_short really corresponds to a shorter or equally long delay than d_long (e.g. not always the case for
+ * STEREO_DFT_STEFFI_DELAY_SHORT=3 and STEREO_DFT_STEFFI_DELAY_LONG=4)*/
+ d_short_ind = s_max( d_short_ind, d_long_ind );
+
+ /* Even number of window sliding (assymmetric OLA) */
+ d_short_ind = d_short_ind & (Word16)(0xFFFE);
+ move16();
+ d_long_ind = d_long_ind & (Word16)(0xFFFE);
+ move16();
+
+ d_short = sub(STEREO_DFT_PAST_MAX , d_short_ind);
+ move16();
+ d_long = sub(STEREO_DFT_PAST_MAX , d_long_ind);
+ move16();
+
+ /* Works as long as STEREO_DFT_PAST_MAX is a power of 2*/
+ d_short_ind = ( add(d_short_ind, add(hStereoDft->past_DMX_pos, 1)) ) & (STEREO_DFT_PAST_MAX - 1);
+ move16();
+ d_long_ind = ( add(d_long_ind, add(hStereoDft->past_DMX_pos, 1)) ) & (STEREO_DFT_PAST_MAX - 1);
+ move16();
+
+ g_short = hStereoDft->stefi_short_gain_fx;
+ move16();
+ g_long = hStereoDft->stefi_long_gain_fx;
+ move16();
+
+ /* change mixing ratio if long and short delay are the same */
+ IF ( EQ_16(d_short , d_long) )
+ {
+ g_short = MAX_16;
+ move16();
+ g_long = 0;
+ move16();
+ }
+
+ /* Avoid transient components */
+ IF ( EQ_32(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], MIN_32) &&
+ EQ_32(hStereoDft->past_res_pred_gain_fx[d_long_ind][b], MIN_32))
+ {
+ g_long = 0;
+ move16();
+ g_short = 0;
+ move16();
+ }
+ ELSE IF( EQ_32(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], MIN_32) )
+ {
+ g_long = MAX_16;
+ move16();
+ g_short = 0;
+ move16();
+ }
+ ELSE IF ( EQ_32(hStereoDft->past_res_pred_gain_fx[d_long_ind][b], MIN_32) )
+ {
+ g_long = 0;
+ move16();
+ g_short = MAX_16;
+ move16();
+ }
+ IF ( EQ_32(hStereoDft->core_hist[d_short / 2], ACELP_CORE) )
+ {
+ g_short = 0;
+ move16();
+ }
+ IF ( EQ_32(hStereoDft->core_hist[d_long / 2] , ACELP_CORE) )
+ {
+ g_long = 0;
+ move16();
+ }
+
+ IF ( GT_16(s_max( g_short, g_long ) , 0) )
+ {
+ Word16 q_div;
+ Word32 op1;
+ Word16 q_shift = sub(hStereoDft->q_dft, hStereoDft->q_past_dft);
+ past_dmx_nrg = EPSILON_FIX;
+ move32();
+ dmx_nrg = EPSILON_FIX;
+ move32();
+ FOR ( i = max( hStereoDft->band_limits[b], bin0 ); i < min( hStereoDft->band_limits[b + 1], STEREO_DFT32MS_N_32k / 2 ); i++ )
+ {
+ dmx_nrg = L_add(dmx_nrg, Madd_32_32(Mpy_32_32(pDFT_DMX[2 * i] , pDFT_DMX[2 * i]) , pDFT_DMX[2 * i + 1] , pDFT_DMX[2 * i + 1]));
+
+ DFT_PRED_RES[2 * i] = L_shr(Madd_32_16(Mpy_32_16_1(hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i], g_short) , hStereoDft->DFT_past_DMX_fx[d_long_ind][2 * i], g_long ), q_shift);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = L_shr(Madd_32_16(Mpy_32_16_1(hStereoDft->DFT_past_DMX_fx[d_short_ind][2 * i + 1], g_short) , hStereoDft->DFT_past_DMX_fx[d_long_ind][2 * i + 1] , g_long ), q_shift);
+ move32();
+
+ past_dmx_nrg = L_add(past_dmx_nrg, Madd_32_32(Mpy_32_32(DFT_PRED_RES[2 * i] , DFT_PRED_RES[2 * i]) , DFT_PRED_RES[2 * i + 1] , DFT_PRED_RES[2 * i + 1]));
+ }
+ IF (GT_16(hStereoDft->q_dft, hStereoDft->q_past_dft))
+ {
+ past_dmx_nrg = L_shl(past_dmx_nrg, shl(sub(hStereoDft->q_dft , hStereoDft->q_past_dft), 1));
+ }
+ ELSE
+ {
+ dmx_nrg = L_shl(dmx_nrg, shl(sub(hStereoDft->q_past_dft , hStereoDft->q_dft), 1));
+ }
+ op1 = L_deposit_h(BASOP_Util_Divide3232_Scale( (EPSILON_FIX + dmx_nrg ) , ( EPSILON_FIX + past_dmx_nrg ), &q_div));
+ q_norm_fac = q_div;
+ op1 = Sqrt32( op1, &q_norm_fac);
+ IF (GT_16(q_norm_fac , 16))
+ {
+ assert(0);
+ }
+ norm_fac = extract_h(op1);
+ q_norm_fac = sub(q_norm_fac, Q16);
+ g2 = Mpy_32_16_1(pPredGain[b], norm_fac);
+ pred_gain_avg = Madd_32_16(Mpy_32_16_1(hStereoDft->past_res_pred_gain_fx[d_short_ind][b], g_short) , hStereoDft->past_res_pred_gain_fx[d_long_ind][b] , g_long);
+
+ g2 = L_min( Mpy_32_16_1(pred_gain_avg , STEREO_DFT_STEFFI_GAIN_AMP_FX),
+ Madd_32_16(Mpy_32_16_1(pred_gain_avg , sub( (Word16)(0x7FFF) , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )) , g2 , STEREO_DFT_STEFFI_GAIN_REST_AMT_FX ));
+
+ FOR ( i = max( hStereoDft->band_limits[b], bin0 ); i < min( hStereoDft->band_limits[b + 1], STEREO_DFT32MS_N_32k / 2 ); i++ )
+ {
+ DFT_PRED_RES[2 * i] = Mpy_32_32(g2, DFT_PRED_RES[2 * i]);
+ move32();
+ DFT_PRED_RES[2 * i + 1] = Mpy_32_32(g2, DFT_PRED_RES[2 * i + 1]);
+ move32();
+ }
+ }
+ ELSE
+ {
+ begin = s_max( hStereoDft->band_limits[b], bin0 );
+ end = s_min( hStereoDft->band_limits[b + 1], STEREO_DFT32MS_N_32k / 2 );
+ set_l( DFT_PRED_RES + 2 * begin, 0, 2 * ( end - begin ) );
+ }
+ }
+ }
+ }
+
+ /* update buffers */
+ FOR ( b = hStereoDft->res_pred_band_min; b < hStereoDft->nbands; b++ )
+ {
+ IF ( hStereoDft->attackPresent || hStereoDft->wasTransient )
+ {
+ hStereoDft->past_res_pred_gain_fx[( hStereoDft->past_DMX_pos + 1 ) & (STEREO_DFT_PAST_MAX - 1)][b] = MIN_32;
+ move32();
+ }
+ ELSE
+ {
+ hStereoDft->past_res_pred_gain_fx[( hStereoDft->past_DMX_pos + 1 ) & (STEREO_DFT_PAST_MAX - 1)][b] = pPredGain[b];
+ move32();
+ }
+ }
+
+ pop_wmops();
+ return;
+}
+
+/*---------------------------------------------------------------
+ * stereo_dft_adapt_sf_delay_fx()
+ *
+ *
+ * ---------------------------------------------------------------*/
+
+static void stereo_dft_adapt_sf_delay_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft,
+ Word32 *pPredGain )
+{
+ Word32 var_mean_ratio;
+ Word32 new_variation;
+ Word32 target_delay;
+ Word32 max_pg, sum_pg;
+ Word32 alpha_up, alpha_down;
+ Word16 b;
+ Word16 q_sqrt;
+ Word16 q_div;
+ Word16 q_guard;
+ Word16 op;
+
+ max_pg = 0;
+ move32();
+ sum_pg = 0;
+ move32();
+ q_sqrt = 0;
+ move32();
+ q_guard = sub(15 , norm_s(hStereoDft->nbands));
+
+ /* find sum and maximum of prediction gains */
+ FOR ( b = hStereoDft->res_pred_band_min; b < hStereoDft->nbands; b++ )
+ {
+ IF ( GT_32(pPredGain[b], max_pg) )
+ {
+ max_pg = pPredGain[b];
+ move16();
+ }
+ sum_pg = L_add(sum_pg, L_shr(pPredGain[b], q_guard));
+ }
+ IF (GT_16(q_guard, hStereoDft->q_lt_pred_gain))
+ {
+ hStereoDft->lt_pred_gain_fx = L_shr(hStereoDft->lt_pred_gain_fx, sub(q_guard, hStereoDft->q_lt_pred_gain));
+ hStereoDft->q_lt_pred_gain = q_guard;
+ }
+ ELSE
+ {
+ sum_pg = L_shr(sum_pg, sub(hStereoDft->q_lt_pred_gain, q_guard));
+ q_guard = hStereoDft->q_lt_pred_gain;
+ }
+ IF ( GT_32(sum_pg, 0) )
+ {
+ /* Calculate mean of the prediction gain */
+ hStereoDft->lt_pred_gain_fx = Madd_32_16(Mpy_32_16_1( sum_pg, STEREO_DFT_LT_PREDGAIN_UPD_FX), hStereoDft->lt_pred_gain_fx, sub( MAX_16, STEREO_DFT_LT_PREDGAIN_UPD_FX ));
+
+ /* Calculate the variation of the prediction gain */
+ new_variation = L_abs( L_sub(sum_pg , hStereoDft->lt_pred_gain_fx) );
+ hStereoDft->lt_pred_gain_variation_fx = Madd_32_16(Mpy_32_16_1(new_variation , STEREO_DFT_VR_PREDGAIN_UPD_FX) , hStereoDft->lt_pred_gain_variation_fx, sub( MAX_16 , STEREO_DFT_VR_PREDGAIN_UPD_FX ));
+ }
+
+ /* Calculate ratio of variation and mean of prediction gain */
+ var_mean_ratio = STEREO_DFT_RES_RATIO_LIMIT_FX;
+ move16();
+
+ IF ( GT_32(hStereoDft->lt_pred_gain_fx, 0) )
+ {
+ Word32 opr2 = L_deposit_h(BASOP_Util_Divide3232_Scale(hStereoDft->lt_pred_gain_variation_fx , hStereoDft->lt_pred_gain_fx, &q_div));
+ IF ( LT_16(q_div, 0) )
+ {
+ opr2 = L_shl(opr2, q_div);
+ q_div = 0;
+ move16();
+ }
+ IF ( LT_32(L_shr(STEREO_DFT_RES_RATIO_LIMIT_FX_3_BY_2, q_div), opr2))
+ {
+ var_mean_ratio = STEREO_DFT_RES_RATIO_LIMIT_FX_3_BY_2;
+ }
+ ELSE
+ {
+ var_mean_ratio = L_shl(opr2, q_div);
+ }
+ }
+
+ IF ( GT_32(max_pg , STEREO_DFT_STEFFI_PG_THRESHOLD_FX) )
+ {
+ /* slow upwards */
+ alpha_up = STEREO_DFT_STEFFI_RATIO_UP_HIGH_FX;
+ move16();
+ alpha_down = STEREO_DFT_STEFFI_RATIO_DOWN_HIGH_FX;
+ move16();
+ }
+ ELSE
+ {
+ /* slow downwards */
+ alpha_up = STEREO_DFT_STEFFI_RATIO_UP_LOW_FX;
+ move16();
+ alpha_down = STEREO_DFT_STEFFI_RATIO_DOWN_LOW_FX;
+ move16();
+ }
+
+ IF ( GT_16(extract_h(var_mean_ratio) , extract_h(hStereoDft->lt_var_mean_ratio_fx)) )
+ {
+ hStereoDft->lt_var_mean_ratio_fx = Madd_32_32(Mpy_32_32(var_mean_ratio, alpha_up) , hStereoDft->lt_var_mean_ratio_fx, L_sub( MAX_32 , alpha_up ));
+ }
+ ELSE
+ {
+ hStereoDft->lt_var_mean_ratio_fx = Madd_32_32(Mpy_32_32(var_mean_ratio, alpha_down) , hStereoDft->lt_var_mean_ratio_fx, L_sub( MAX_32 , alpha_down ));
+ }
+
+ /* Calculate a target delay for the stereo filling. Set the stereo filling delay lower when the prediction gain
+ variation is relatively high compared to the mean */
+ IF ( GE_16(extract_h(hStereoDft->lt_var_mean_ratio_fx) , extract_h(STEREO_DFT_RES_RATIO_LIMIT_FX)) )
+ {
+ target_delay = L_shl(STEREO_DFT_STEFFI_DELAY_SHORT, Q15);
+ move32();
+ }
+ ELSE
+ {
+ target_delay = L_min( L_shl(STEREO_DFT_STEFFI_DELAY_LONG, Q15),
+ L_add(L_shl(STEREO_DFT_STEFFI_DELAY_SHORT, Q15) ,
+ L_mult0(( STEREO_DFT_STEFFI_DELAY_OFFSET + STEREO_DFT_STEFFI_DELAY_LONG - STEREO_DFT_STEFFI_DELAY_SHORT ) ,
+ sub( MAX_16 , extract_h(L_shl(Mpy_32_16_1(hStereoDft->lt_var_mean_ratio_fx , ONE_STEREO_DFT_RES_RATIO_LIMIT_Q12), Q3)))
+ )
+ )
+ );
+ }
+
+ /* Adapt the stereo filling delay by interpolating between two delay taps, one at the shortest delay and one at the longest delay */
+ hStereoDft->stefi_short_gain_fx = extract_l(L_shr(L_sub(L_shl(STEREO_DFT_STEFFI_DELAY_LONG, Q15), target_delay), 1));
+ q_sqrt = 0;
+ IF (hStereoDft->stefi_short_gain_fx == MIN_16)
+ {
+ hStereoDft->stefi_short_gain_fx = MAX_16;
+ hStereoDft->stefi_long_gain_fx = 0;
+ }
+ ELSE
+ {
+ op = hStereoDft->stefi_short_gain_fx;
+ hStereoDft->stefi_long_gain_fx = Sqrt16( sub(MAX_16 , mult(op, op)), &q_sqrt);
+ IF (NE_16(q_sqrt, 0))
+ {
+ hStereoDft->stefi_long_gain_fx = shl(hStereoDft->stefi_long_gain_fx, q_sqrt);
+ }
+ }
+
+ return;
+}
+#endif
\ No newline at end of file
diff --git a/lib_dec/ivas_stereo_dft_plc_fx.c b/lib_dec/ivas_stereo_dft_plc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..dad8245a49c8236361b6e0fd23482d8c7bfa6017
--- /dev/null
+++ b/lib_dec/ivas_stereo_dft_plc_fx.c
@@ -0,0 +1,995 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "ivas_cnst.h"
+#include "ivas_prot.h"
+#include "ivas_prot_fx.h"
+#include "math.h"
+#include "wmc_auto.h"
+#include "basop_util.h"
+
+/*---------------------------------------------------------------
+ * Local constants
+ * ---------------------------------------------------------------*/
+
+#define ZP8k 15 /* zero padding in 8kHz DFT analysis */
+#define OFFSET8k 55 /* offset in 8 kHz */
+#define STEREO_DFT_PLC_STEP21 ( L_FRAME8k - OFFSET8k ) /* Step from subframe 2 in frame n to subframe 1 in frame n+1 */
+#define STEREO_DFT_PLC_PH_C_FX (Word16)( 0x0A8D ) /* Phase estimation constant, for estimating phase of fractional frequency */
+
+
+#ifdef IVAS_FLOAT_FIXED
+
+/*---------------------------------------------------------------
+ * stereo_dft_res_ecu_fx()
+ *
+ * Error concealment of DFT Stereo residual, including memory
+ * updates of DFT analysis memory and IMDCT OLA
+ * ---------------------------------------------------------------*/
+
+void stereo_dft_res_ecu_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal */
+ Word32 *const DFT_PRED_RES, /* i/o: residual prediction signal */
+ const Word16 k, /* i : Subframe index */
+ const Word16 output_frame, /* i : Output frame length */
+ const Word16 prev_bfi, /* i : Previous BFI */
+ const Word32 dmx_nrg, /* i : Down-mix energy */
+ Word16 *num_plocs, /* i/o: Number of peak locations */
+ Word16 *plocs, /* i/o: Peak locations (bin) */
+ Word32 *plocsi, /* i/o: Peak locations (fractional) */
+ Word32 *input_mem /* o : Residual DFT buffer input mem */
+)
+{
+ Word32 res_buf[L_FRAME8k];
+ Word16 i;
+ Word16 L_res;
+ Word16 step;
+ Word16 fac;
+ Word16 trigo_dec[STEREO_DFT32MS_N_8k / 2 + 1];
+ Word16 trigo_step;
+ Word16 q_fac;
+
+ set_l( pDFT_RES, 0, L_FRAME8k );
+
+ L_res = hStereoDft->band_limits[hStereoDft->res_cod_band_max];
+ move16();
+
+ stereo_dft_res_subst_spec_fx( hStereoDft, pDFT_RES, DFT_PRED_RES, hStereoDft->time_offs, L_res, L_FRAME8k, k, num_plocs, plocs, plocsi, k == 0 );
+
+ fac = BASOP_Util_Divide3232_Scale( L_FRAME8k , hStereoDft->NFFT, &q_fac);
+ IF (GT_16(q_fac, 0))
+ {
+ assert(0);
+ }
+ ELSE
+ {
+ fac = L_shl(fac, q_fac);
+ }
+
+ IF ( EQ_16(hStereoDft->core_hist[0] , ACELP_CORE) )
+ {
+ fac = extract_l(L_shr(L_mult0(fac, 0x2000), 15));
+ }
+
+ trigo_step = STEREO_DFT_TRIGO_SRATE_8k_STEP * STEREO_DFT_TRIGO_DEC_STEP;
+ move16();
+ FOR ( i = 0; i < STEREO_DFT32MS_N_8k / 4; i++ )
+ {
+ trigo_dec[i] = hStereoDft->dft_trigo_8k_fx[i * trigo_step];
+ move16();
+ trigo_dec[STEREO_DFT32MS_N_8k / 2 - i] = hStereoDft->dft_trigo_8k_fx[i * trigo_step];
+ move16();
+ }
+ trigo_dec[STEREO_DFT32MS_N_8k / 4] = hStereoDft->dft_trigo_8k_fx[STEREO_DFT32MS_N_8k / 4 * trigo_step];
+ move16();
+
+ /* estimation of res_cod_mem (ola part in imdct residual signal) and input_mem (memory for buffer in DFT analysis)*/
+ IF ( EQ_16(k , 0) )
+ {
+ Copy32( pDFT_RES, res_buf, L_FRAME8k );
+ stereo_dft_res_subst_spec_fx( hStereoDft, res_buf, DFT_PRED_RES, hStereoDft->time_offs + output_frame, L_res, L_FRAME8k, k, num_plocs, plocs, plocsi, FALSE );
+
+ rfft_fx( res_buf, trigo_dec, L_FRAME8k, +1 );
+
+ v_multc_fixed_16( res_buf, fac, res_buf, L_FRAME8k );
+ Copy32( res_buf + ( OFFSET8k - ZP8k ), &hStereoDft->res_cod_mem_fx[0], STEREO_DFT_OVL_8k );
+
+ Copy32( res_buf + ZP8k, input_mem, NS2SA( 8000, STEREO_DFT32MS_OVL_NS ) ); /* Store memory for cross-fade to next frame, in case of good frame */
+ hStereoDft->q_ip_mem = hStereoDft->q_dft;
+ }
+ ELSE
+ {
+ Word16 scale_fac = getScaleFactor32(res_buf, L_FRAME8k);
+ Word16 q_shift = 8 - scale_fac;
+ //Copy32( pDFT_RES, res_buf, L_FRAME8k );
+ v_shr_32(pDFT_RES, res_buf, L_FRAME8k, q_shift);
+
+ rfft_fx( res_buf, trigo_dec, L_FRAME8k, +1 );
+
+ v_shr_32(res_buf, res_buf, L_FRAME8k, negate(q_shift));
+
+ v_multc_fixed( res_buf, fac, res_buf, L_FRAME8k );
+
+ /* Cross-fade memory */
+ fac = 0;
+ move16();
+ step = ONE_BY_NS2A_8K_ST_DFT32MS_OVL_NS;
+ move16();
+ FOR ( i = 0; i < NS2SA( 8000, STEREO_DFT32MS_OVL_NS ); i++ )
+ {
+ input_mem[i] = Madd_32_16(Mpy_32_16_1(res_buf[i + L_FRAME8k - NS2SA( 8000, STEREO_DFT32MS_OVL_NS ) - ZP8k], sub( MAX_16 , fac )) , input_mem[i], fac);
+ move32();
+ fac = add(fac, step);
+ }
+
+ /*in case of burst error*/
+ hStereoDft->time_offs = add(hStereoDft->time_offs, L_FRAME8k);
+ }
+
+ set_l( DFT_PRED_RES, 0, 2 * L_res );
+
+ IF ( prev_bfi )
+ {
+ stereo_dft_res_ecu_burst_att_fx( hStereoDft, pDFT_RES, dmx_nrg, L_res, L_FRAME8k );
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * imax_pos()
+ *
+ * Get interpolated maximum position
+ *-------------------------------------------------------------------*/
+
+/*! r: interpolated maximum position */
+Word32 imax_pos_fx(
+ const Word32 *y /* i : Input vector for peak interpolation */
+)
+{
+ Word32 posi, y1, y2, y3, y3_y1, y2i;
+ Word32 ftmp_den1, ftmp_den2;
+ Word16 q_div_2i, q_div_posi;
+ /* Seek the extrema of the parabola P(x) defined by 3 consecutive points so that P([-1 0 1]) = [y1 y2 y3] */
+ y1 = y[0];
+ y2 = y[1];
+ y3 = y[2];
+ y3_y1 = L_sub(y3 , y1);
+ ftmp_den1 = L_sub( L_add(y1 , y3) , L_shl(y2 , 1));
+ ftmp_den2 = L_shl(L_sub( L_sub(L_shl(y2, 1) , y1) , y3), 1);
+
+ IF ( EQ_32(ftmp_den2 , 0) || EQ_32(ftmp_den1 , 0) )
+ {
+ return ( 0 ); /* early exit with left-most value */
+ }
+
+ y2i = Mpy_32_16_1(Mpy_32_16_1(y3_y1, BASOP_Util_Divide3232_Scale( y3_y1 , ftmp_den1 , &q_div_2i)), (Word16)(0xF000));
+ IF (LT_16(q_div_2i, 0))
+ {
+ y2i = L_shl(y2i, q_div_2i);
+ q_div_2i = 0;
+ y2i = L_add(y2i, y2);
+ }
+ ELSE
+ {
+ y2i = L_add(y2i, L_shr(y2, q_div_2i));
+ }
+ /* their corresponding normalized locations */
+ posi = BASOP_Util_Divide3232_Scale(y3_y1 , ( ftmp_den2 ), &q_div_posi);
+ IF (NE_16(q_div_posi, 0))
+ {
+ posi = L_shl(posi, q_div_posi);
+ q_div_posi = 0;
+ }
+ /* Interpolated maxima if locations are not within [-1,1], calculated extrema are ignored */
+ IF ( GE_32(posi, L_shr(ONE_IN_Q15, q_div_posi)) || LE_32(posi , L_shr(MIN_16, q_div_posi)) )
+ {
+ posi = y3 > y1 ? ONE_IN_Q15 : MIN_16;
+ }
+ ELSE
+ {
+ IF ( GE_32(L_shr(y1, q_div_2i), y2i) )
+ {
+ posi = ( y1 > y3 ) ? MIN_16 : ONE_IN_Q15;
+ }
+ ELSE IF ( GE_32(L_shr(y3, q_div_2i) , y2i) )
+ {
+ posi = ONE_IN_Q15;
+ }
+ }
+
+ return L_add(posi , ONE_IN_Q15);
+}
+
+static void ivas_peakfinder_fx(
+ const Word32 *x0, /* i : vector from which the maxima will be found */
+ const Word16 len0, /* i : length of input vector */
+ Word16 *plocs, /* o : the indicies of the identified peaks in x0 */
+ Word16 *cInd, /* o : number of identified peaks */
+ const Word32 sel, /* i : The amount above surrounding data for a peak to be identified */
+ const Word16 endpoints /* i : Flag to include endpoints in peak search */
+)
+{
+ Word32 minMag, tempMag, leftMin;
+ Word32 dx0[L_PROT48k_2], x[L_PROT48k_2 + 1], peakMag[MAX_PLOCS];
+ Word16 k, i, len, tempLoc = 0, foundPeak, ii, xInd;
+ Word16 *ind, indarr[L_PROT48k_2 + 1], peakLoc[MAX_PLOCS];
+
+ ind = indarr;
+
+ /* Find derivative */
+ v_sub_32( x0 + 1, x0, dx0, len0 - 1 );
+
+ /* This is so we find the first of repeated values */
+ FOR ( i = 0; i < len0 - 1; i++ )
+ {
+ IF ( EQ_32(dx0[i] , 0) )
+ {
+ dx0[i] = -EPSILON_FX;
+ }
+ }
+
+ /* Find where the derivative changes sign
+ Include endpoints in potential peaks and valleys */
+ k = 0;
+
+ IF ( endpoints )
+ {
+ x[k] = x0[0];
+ ind[k++] = 0;
+ }
+
+ FOR ( i = 1; i < len0 - 1; i++ )
+ {
+ IF ( L_xor(dx0[i - 1] , dx0[i]) < 0 )
+ {
+ ind[k] = i;
+ x[k++] = x0[i];
+ }
+ }
+
+ IF ( endpoints )
+ {
+ ind[k] = sub(len0 , 1);
+ x[k++] = x0[len0 - 1];
+ }
+ /* x only has the peaks, valleys, and endpoints */
+ len = k;
+ minimum_l( x, len, &minMag );
+
+ IF ( ( len > 2 ) || ( !endpoints && ( len > 0 ) ) )
+ {
+ /* Set initial parameters for loop */
+ tempMag = minMag;
+ foundPeak = 0;
+ leftMin = minMag;
+
+ IF ( endpoints )
+ {
+ /* Deal with first point a little differently since tacked it on
+ Calculate the sign of the derivative since we taked the first point
+ on it does not necessarily alternate like the rest. */
+
+ /* The first point is larger or equal to the second */
+ IF ( GE_32(x[0] , x[1]) )
+ {
+ ii = -1;
+ IF ( GE_32(x[1] , x[2]) ) /* x[1] is not extremum -> overwrite with x[0] */
+ {
+ x[1] = x[0];
+ ind[1] = ind[0];
+ ind++;
+ len--;
+ }
+ }
+ ELSE /* First point is smaller than the second */
+ {
+ ii = 0;
+ IF ( LT_32(x[1] , x[2]) ) /* x[1] is not extremum -> overwrite with x[0] */
+ {
+ x[1] = x[0];
+ ind[1] = ind[0];
+ ind++;
+ len--;
+ }
+ }
+ }
+ ELSE
+ {
+ ii = -1; /* First point is a peak */
+ IF ( GE_16(len , 2) )
+ {
+ IF ( GE_32(x[1] , x[0]) )
+ {
+ ii = 0; /* First point is a valley, skip it */
+ }
+ }
+ }
+ *cInd = 0;
+
+ /* Loop through extrema which should be peaks and then valleys */
+ WHILE ( ii < len - 1 )
+ {
+ ii++; /* This is a peak */
+
+ /*Reset peak finding if we had a peak and the next peak is bigger
+ than the last or the left min was small enough to reset.*/
+ IF ( foundPeak )
+ {
+ tempMag = minMag;
+ foundPeak = 0;
+ }
+
+ /* Make sure we don't iterate past the length of our vector */
+ IF ( ii == len - 1 )
+ {
+ BREAK; /* We assign the last point differently out of the loop */
+ }
+
+ /* Found new peak that was larger than temp mag and selectivity larger
+ than the minimum to its left. */
+ IF ( ( x[ii] > tempMag ) && ( x[ii] > leftMin + sel ) )
+ {
+ tempLoc = ii;
+ tempMag = x[ii];
+ }
+
+ ii++; /* Move onto the valley */
+
+ /* Come down at least sel from peak */
+ IF ( !foundPeak && ( tempMag > sel + x[ii] ) )
+ {
+ foundPeak = 1; /* We have found a peak */
+ leftMin = x[ii];
+ peakLoc[*cInd] = tempLoc; /* Add peak to index */
+ peakMag[*cInd] = tempMag;
+ ( *cInd )++;
+ }
+ ELSE IF ( x[ii] < leftMin ) /* New left minimum */
+ {
+ leftMin = x[ii];
+ }
+ }
+
+ /* Check end point */
+ IF ( x[len - 1] > tempMag && x[len - 1] > leftMin + sel )
+ {
+ peakLoc[*cInd] = len - 1;
+ peakMag[*cInd] = x[len - 1];
+ ( *cInd )++;
+ }
+ ELSE IF ( !foundPeak && tempMag > minMag ) /* Check if we still need to add the last point */
+ {
+ peakLoc[*cInd] = tempLoc;
+ peakMag[*cInd] = tempMag;
+ ( *cInd )++;
+ }
+
+ /* Create output */
+ FOR ( i = 0; i < *cInd; i++ )
+ {
+ plocs[i] = ind[peakLoc[i]];
+ }
+ }
+ ELSE
+ {
+ IF ( endpoints )
+ {
+ /* This is a monotone function where an endpoint is the only peak */
+ xInd = ( x[0] > x[1] ) ? 0 : 1;
+ peakMag[0] = x[xInd];
+ IF ( GT_32(peakMag[0] , L_add(minMag , sel)) )
+ {
+ plocs[0] = ind[xInd];
+ *cInd = 1;
+ }
+ ELSE
+ {
+ *cInd = 0;
+ }
+ }
+ ELSE
+ {
+ /* Input constant or all zeros -- no peaks found */
+ *cInd = 0;
+ }
+ }
+
+ return;
+}
+
+#if 0
+static void peakfinder_fx_32(
+ const Word32 *x0, /* i : vector from which the maxima will be found */
+ const Word16 len0, /* i : length of input vector */
+ Word16 *plocs, /* o : the indices of the identified peaks in x0 Q0 */
+ Word16 *cInd, /* o : number of identified peaks Q0 */
+ const Word32 sel /* i : The amount above surrounding data for a peak to be identified */
+ ,const Word16 endpoints /* i : Flag to include endpoints in peak search */
+)
+{
+ const Word32 *pX0;
+ Word32 minMag, tempMag, leftMin;
+ Word32 dx0[L_PROT48k_2], x[L_PROT48k_2+1], peakMag[MAX_PLOCS];
+ Word32 *pDx0, *pDx01, *pX;
+ Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16;
+ Word32 threshold, xAt0, xAt1, xAt2;
+ Word16 len0Minus1, len0Minus2, lenMinus1;
+ Word16 indarr[L_PROT48k_2+1], peakLoc[MAX_PLOCS];
+ Word16 *pInd;
+
+ tempLoc = 0;
+
+ /* Find derivative */
+ len0Minus1 = sub(len0, 1);
+ pX0 = x0 + 1;
+ v_sub_32(pX0, x0, dx0, len0Minus1);
+
+ FOR (i=0; i 0)))
+ {
+ /* Set initial parameters for loop */
+ tempMag = minMag;
+ move16();
+ foundPeak = 0;
+ move16();
+ leftMin = minMag;
+ move32();
+ threshold = L_add(leftMin, sel);
+
+ IF(endpoints)
+ {
+ /* Deal with first point a little differently since tacked it on
+ Calculate the sign of the derivative since we took the first point
+ on it does not necessarily alternate like the rest. */
+
+ /* The first point is larger or equal to the second */
+ pX = x;
+ xAt0 = *pX++;
+ move32();
+ xAt1 = *pX++;
+ move32();
+ xAt2 = *pX--; /* After decrement, pX points to x[1]. */ move16();
+ IF(GE_32(xAt0, xAt1))
+ {
+ ii = -1;
+ move16();
+ IF(GE_32(xAt1, xAt2)) /* x[1] is not extremum -> overwrite with x[0] */
+ {
+ *pX = xAt0; /* x[1] = x[0] */ move16();
+ tmp16 = *pInd++;
+ move16();
+ *pInd++ = tmp16; /* ind[1] = ind[0] */ move16();
+ len = sub(len, 1);
+ }
+ pX--; /* After decrement, pX points to x[0]. */
+ }
+ ELSE /* First point is smaller than the second */
+ {
+ ii = 0;
+ IF(LT_32(xAt1, xAt2)) /* x[1] is not extremum -> overwrite with x[0] */
+ {
+ *pX = xAt0; /* x[1] = x[0] */ move16();
+ tmp16 = *pInd++;
+ move16();
+ *pInd++ = tmp16; /* ind[1] = ind[0] */ move16();
+ len = sub(len, 1);
+ }
+ }
+ pX--; /* After decrement, pX points to either x[-1] or x[0]. */
+ }
+ ELSE
+ {
+ ii = -1; /* First point is a peak */
+ IF (GE_16(len , 2))
+ {
+ IF (GE_32(x[1] , x[0]))
+ {
+ ii = 0; /* First point is a valley, skip it */
+ }
+ }
+ }
+ *cInd = 0;
+ move16();
+ /*Loop through extrema which should be peaks and then valleys*/
+ lenMinus1 = sub(len, 1);
+ FOR (;;)
+ {
+ ii = add(ii, 1); /* This is a peak */
+
+ /* Make sure we don't iterate past the length of our vector */
+ IF (GE_16(ii, lenMinus1))
+ {
+ BREAK;
+ }
+
+ /*Reset peak finding if we had a peak and the next peak is bigger
+ than the last or the left min was small enough to reset.*/
+ IF (GT_16(foundPeak,0))
+ {
+ tempMag = minMag;
+ move16();
+ foundPeak = 0;
+ move16();
+ }
+
+ /* Found new peak that was larger than temp mag and selectivity larger
+ than the minimum to its left. */
+ IF (GT_32(*(++pX), tempMag))
+ {
+ IF ( GT_32(*pX, threshold)) /* threshold = leftMin + sel */
+ {
+ tempLoc = ii;
+ move16();
+ tempMag = *pX;
+ move16();
+ }
+ }
+
+ ii = add(ii, 1); /* Move onto the valley */
+ pX++;
+
+ /* Come down at least sel from peak */
+ IF (foundPeak == 0)
+ {
+ IF (GT_32(tempMag, L_add(sel, *pX)))
+ {
+ foundPeak = 1; /* We have found a peak */ move16();
+ leftMin = *pX;
+ move16();
+ threshold = L_add(leftMin, sel);
+ peakLoc[*cInd] = tempLoc; /* Add peak to index */ move16();
+ peakMag[*cInd] = tempMag;
+ move16();
+ *cInd = add(*cInd, 1);
+ }
+ }
+ IF (foundPeak == 0) /* The above IF-block has not found the peak yet. */
+ {
+ IF (LT_32(*pX, leftMin))/* New left minimum */
+ {
+ leftMin = *pX;
+ move16();
+ threshold = L_add(leftMin, sel);
+ }
+ }
+ }
+
+ /* Check end point */
+ IF (GT_32(x[lenMinus1], tempMag))
+ {
+ IF (GT_32(x[lenMinus1], threshold)) /* threshold = leftMin + sel */
+ {
+ peakLoc[*cInd] = lenMinus1;
+ move16();
+ peakMag[*cInd] = x[lenMinus1];
+ move16();
+ *cInd = add(*cInd, 1);
+ foundPeak = 1;
+ move16();
+ }
+ }
+ IF (foundPeak == 0) /* Check if we still need to add the last point */
+ {
+ IF (GT_32(tempMag, minMag))
+ {
+ peakLoc[*cInd] = tempLoc;
+ move16();
+ peakMag[*cInd] = tempMag;
+ move16();
+ *cInd = add(*cInd, 1);
+ }
+ }
+
+ /* Create output */
+ FOR (i = 0; i < *cInd; i++)
+ {
+ plocs[i] = *(indarr + peakLoc[i]);
+ move16();
+ move16();
+ }
+ }
+ ELSE /* This is a monotone function where an endpoint is the only peak */
+ {
+ IF(endpoints)
+ {
+ xInd = 1;
+ move16();
+ IF (GT_32(x[0], x[1]))
+ {
+ xInd = 0;
+ move16();
+ }
+
+ peakMag[0] = x[xInd];
+ move16();
+ IF(GT_32(peakMag[0], L_add(minMag, sel)))
+ {
+ plocs[0] = *(indarr + xInd);
+ move16();
+ *cInd = 1;
+ move16();
+ }
+ ELSE
+ {
+ *cInd = 0;
+ move16();
+ }
+ }
+ ELSE
+ {/* Input constant or all zeros -- no peaks found */
+ *cInd = 0;
+ move16();
+ }
+ }
+}
+#endif
+
+/*---------------------------------------------------------------
+ * stereo_dft_res_subst_spec_fx()
+ *
+ * Generate error concealment frame in DFT domain
+ * ---------------------------------------------------------------*/
+
+void stereo_dft_res_subst_spec_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal */
+ const Word32 *const DFT_PRED_RES, /* i : residual prediction signal */
+ const Word16 time_offs, /* i : Time offset for phase adjustment*/
+ const Word16 L_res, /* i : bandwidth of residual signal */
+ const Word16 L_ana, /* i : Length of FFT analysis */
+ const Word16 k, /* i : Subframe index */
+ Word16 *num_plocs, /* i/o: Number of peak locations */
+ Word16 *plocs, /* i/o: Peak locations (bin) */
+ Word32 *plocsi, /* i/o: Peak locations (fractional) */
+ const Word16 analysis_flag /* i : Flag for running peak analysis */
+)
+{
+ Word16 i, idx;
+ Word16 fac;
+ Word32 s1, s2, abs1, abs2, abs3, abs4;
+ Word32 abs_res[( STEREO_DFT_RES_BW_MAX ) / 2];
+ Word32 Xmax, Xmin;
+ Word32 sel;
+ Word32 corr_phase;
+ Word32 *p_mem;
+ Word16 f_frac;
+ Word32 peak_phase;
+ Word32 phase_tmp;
+ Word32 phase;
+ Word32 conj_sign;
+ Word16 Np;
+ Word16 cos_F, sin_F;
+
+ /* initialization */
+ Copy32( DFT_PRED_RES, pDFT_RES, 2 * L_res );
+ p_mem = hStereoDft->res_mem_fx;
+ Np = 1;
+
+ IF ( analysis_flag )
+ {
+ Word16 q_res = sub(getScaleFactor32(p_mem, shl(L_res, 1)) , 1);
+ /* Perform spectral analysis on 2nd subframe of last good frame */
+ abs_res[0] = L_shr( Mpy_32_32(L_shl(p_mem[0], q_res) , L_shl(p_mem[0], q_res)), 1); /* DC */
+ move32();
+ FOR ( i = 1; i < L_res; i++ )
+ {
+ Word32 r = L_shl(p_mem[2 * i], q_res);
+ Word32 l = L_shl(p_mem[2 * i + 1], q_res);
+ abs_res[i] = Madd_32_32(Mpy_32_32( r, r) , l, l );
+ move32();
+ }
+
+ /* Find maxima */
+ maximum_l( abs_res, L_res, &Xmax );
+ minimum_l( abs_res, L_res, &Xmin );
+ sel = Mpy_32_16_1(L_sub( Xmax , Xmin ) , (Word16)(0x03D7));
+
+ ivas_peakfinder_fx( abs_res, L_res, plocs, num_plocs, sel, FALSE );
+ /* Refine peaks */
+ FOR ( i = 0; i < *num_plocs; i++ )
+ {
+ IF ( EQ_16(plocs[i] , 0) )
+ {
+ plocsi[i] = L_add(L_deposit_h(plocs[i]) , L_shl(imax_pos_fx( &abs_res[plocs[i]]), Q1));
+ move32();
+ }
+ ELSE IF ( EQ_16(plocs[i] , L_res) )
+ {
+ plocsi[i] = L_add(L_deposit_h(sub(plocs[i], 2)) , L_shl(imax_pos_fx( &abs_res[plocs[i] - 2] ), Q1));
+ move32();
+ }
+ ELSE
+ {
+ plocsi[i] = L_add(L_deposit_h(sub(plocs[i] , 1)) , L_shl(imax_pos_fx( &abs_res[plocs[i] - 1] ), Q1));
+ move16();
+ }
+ }
+ }
+
+ /* Apply phase of stereo filling on noise spectrum */
+ FOR ( i = 1; i < L_res; i++ )
+ {
+ s1 = sign_l( pDFT_RES[2 * i] );
+ s2 = sign_l( pDFT_RES[2 * i + 1] );
+ abs1 = L_abs( pDFT_RES[2 * i] );
+ abs2 = L_abs( pDFT_RES[2 * i + 1] );
+ abs3 = L_abs( p_mem[2 * i] );
+ abs4 = L_abs( p_mem[2 * i + 1] );
+
+ fac = MAX_16;
+ move16();
+ /* Low-complex phase matching that brings the angle within pi/4 of the target angle */
+ IF ( ( GT_32( abs1 , abs2 ) && LT_32( abs3 , abs4 ) ) || ( LE_32( abs1 , abs2 ) && GE_32( abs3 , abs4 ) ) )
+ {
+ pDFT_RES[2 * i] = Mpy_32_32(s1 , abs4);
+ move32();
+ pDFT_RES[2 * i + 1] = Mpy_32_32(s2 , abs3);
+ move32();
+ }
+ ELSE
+ {
+ pDFT_RES[2 * i] = Mpy_32_32(s1 , abs3);
+ move32();
+ pDFT_RES[2 * i + 1] = Mpy_32_32(s2 , abs4);
+ move32();
+ }
+ }
+
+ /* Apply phase adjustment of identified peaks, including Np=1 peak neighbors on each side */
+ FOR ( i = *num_plocs - 1; i >= 0; i-- )
+ {
+ Flag flg_ov;
+ IF ( EQ_16(k , 0) )
+ {
+ Word32 op;
+ Word16 q_div, q_shift;
+ /* For 1st subframe, apply reversed time ECU to get correct analysis window */
+ f_frac = extract_l(L_shr(L_sub(plocsi[i] , L_shl(plocs[i], Q16)),1));
+ peak_phase = BASOP_util_atan2( p_mem[2 * plocs[i] + 1], p_mem[2 * plocs[i]], 0 );
+ phase_tmp = L_sub(peak_phase , mult(f_frac , STEREO_DFT_PLC_PH_C_FX));
+ phase = L_sub(phase_tmp , mult(f_frac , EVS_PI_FX));
+ op = L_negate(L_shl(phase, 1));
+ corr_phase = L_add( L_add( STEREO_DFT_PLC_STEP21 , L_ana) , time_offs ) ;
+ q_shift = norm_l(corr_phase);
+ corr_phase = Mpy_32_32(L_shl(corr_phase, q_shift), plocsi[i]);
+ corr_phase = L_deposit_l(BASOP_Util_Divide3232_Scale(corr_phase, L_ana, &q_div));
+ corr_phase = L_shl(corr_phase, sub(q_div, sub(q_shift, Q15)));
+ corr_phase = L_negate(L_shl(Mpy_32_16_1(corr_phase, EVS_PI_FX), Q1));
+ corr_phase = L_add(op, corr_phase);
+ WHILE ( LT_32(corr_phase, -EVS_PI_FX) )
+ {
+ corr_phase = L_add(L_add(corr_phase, EVS_PI_FX), EVS_PI_FX);
+ }
+ WHILE ( GT_32(corr_phase, EVS_PI_FX) )
+ {
+ corr_phase = L_sub(L_sub(corr_phase, EVS_PI_FX), EVS_PI_FX);
+ }
+ conj_sign = MIN_32;
+ }
+ ELSE
+ {
+ Word32 op = L_add(L_ana, time_offs);
+ Word16 q_div;
+ op = Mpy_32_32(L_shl(op, Q15), plocsi[i]);
+ corr_phase = BASOP_Util_Divide3232_Scale(op, L_ana, &q_div);
+ corr_phase = extract_l(L_and(L_shl(corr_phase, q_div), MAX_16));
+ /* For 2nd subframe, do regular phase shift */
+ corr_phase = L_negate(L_shr(L_mult0(extract_l(corr_phase), EVS_PI_FX), Q14));
+ conj_sign = MAX_32;
+ }
+
+ cos_F = shl_o(getCosWord16(extract_l(corr_phase)), 1, &flg_ov);
+ sin_F = getSinWord16(extract_l(corr_phase));
+
+ idx = max( 0, plocs[i] - Np ); /* Iterate over plocs[i]-1:plocs[i]+1, considering the edges of the spectrum */
+ WHILE ( ( idx < plocs[i] + Np + 1 ) && ( idx < L_res ) )
+ {
+ pDFT_RES[2 * idx] = Msub_32_16(Mpy_32_16_1(p_mem[2 * idx] , cos_F) , p_mem[2 * idx + 1] , sin_F);
+ pDFT_RES[2 * idx + 1] = Mpy_32_32(conj_sign , Madd_32_16(Mpy_32_16_1( p_mem[2 * idx] , sin_F) , p_mem[2 * idx + 1] , cos_F));
+ idx++;
+ }
+ }
+ return;
+}
+
+
+/*---------------------------------------------------------------
+ * stereo_dft_res_ecu_burst_att_fx()
+ *
+ * scaling residual PLC in burst error, considering DMX PLC attenuation
+ * ---------------------------------------------------------------*/
+
+void stereo_dft_res_ecu_burst_att_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: Decoder DFT stereo handle */
+ Word32 *pDFT_RES, /* i/o: residual signal /att. residual */
+ const Word32 dmx_nrg, /* i : dmx energy of current frame */
+ const Word16 L_res, /* i : Bandwidth of residual */
+ const Word16 L_ana /* i : Length of FFT analysis */
+)
+{
+ Word32 fac;
+ Word16 q_fac;
+ Word16 exponent;
+
+ q_fac = 0; move16();
+ exponent = 0; move16();
+
+ /* attenuation of residual; follow attenuation of DMX */
+ IF ( EQ_16(hStereoDft->core_hist[0] , ACELP_CORE) )
+ {
+ fac = Mpy_32_16_1(Sqrt32( L_deposit_h(BASOP_Util_Divide3232_Scale(dmx_nrg , hStereoDft->past_dmx_nrg_fx, &q_fac)), &exponent), (Word16)(0x0CCD));
+ }
+ ELSE
+ {
+ fac = L_sub(MAX_32 , L_deposit_h(BASOP_Util_Divide3232_Scale(sub( hStereoDft->time_offs , L_ana ) , add( hStereoDft->time_offs , L_ana ) , &q_fac)));
+ }
+
+ v_multc_fixed( pDFT_RES, fac, pDFT_RES, shl(L_res, 1) );
+
+ return;
+}
+
+/*---------------------------------------------------------------
+ * stereo_dft_dmx_swb_nrg_fx()
+ *
+ * Calculate DMX energy
+ * ---------------------------------------------------------------*/
+
+/*! r: total energy of downmix with maximum swb bandwidth max */
+Word32 stereo_dft_dmx_swb_nrg_fx(
+ const Word32 *dmx_k0, /* i : first subframe spectrum */
+ const Word32 *dmx_k1, /* i : second subframe spectrum */
+ const int16_t frame_length /* i : frame lanegth */
+)
+{
+ int16_t i;
+ Word32 dmx_nrg;
+
+ dmx_nrg = EPSILON_FIX;
+ move32();
+ FOR ( i = 0; i < shr(frame_length, 1); i++ )
+ {
+ dmx_nrg = L_add(dmx_nrg,
+ L_add( Madd_32_32(Mpy_32_32(dmx_k0[shl(i, 1)], dmx_k0[shl(i, 1)]), dmx_k0[add(shl(i, 1), 1)], dmx_k0[add(shl(i, 1), 1)]),
+ Madd_32_32(Mpy_32_32(dmx_k1[shl(i, 1)], dmx_k1[shl(i, 1)]), dmx_k1[add(shl(i, 1), 1)], dmx_k1[add(shl(i, 1), 1)])));
+ }
+
+ return dmx_nrg;
+}
+
+/*---------------------------------------------------------------
+ * stereo_dft_sg_recovery_fx()
+ *
+ * estimates panning measure
+ * updates recovery flag that might enbale recovery of side gain
+ * ---------------------------------------------------------------*/
+
+Word16 stereo_dft_sg_recovery_fx(
+ STEREO_DFT_DEC_DATA_HANDLE hStereoDft /* i/o: Decoder DFT stereo handle */
+)
+{
+ Word16 b;
+ Word32 *pSideGain;
+ Word32 sg_m;
+ Word16 beta;
+
+ IF ( !hStereoDft->sg_mem_corrupt )
+ {
+ pSideGain = hStereoDft->side_gain_fx + 2 * STEREO_DFT_BAND_MAX;
+ beta = (Word16)(0x3666);
+
+ sg_m = EPSILON_FIX;
+ FOR ( b = 0; b < hStereoDft->nbands; b++ )
+ {
+ sg_m = L_add(sg_m , pSideGain[b]);
+ }
+ sg_m /= hStereoDft->nbands;
+
+ IF ( LT_32(sg_m , (Word32)0x4CCCCCCD) && GT_32(sg_m , (Word32)(0xB3333333) ))
+ {
+ hStereoDft->sg_mean_fx = 0;
+ }
+ ELSE
+ {
+ hStereoDft->sg_mean_fx = Madd_32_16(Mpy_32_16_1(sg_m, beta), hStereoDft->sg_mean_fx, sub( MAX_16 , beta )); /* LP filter delta_sg to obtain side gain stability measure */
+ }
+ }
+ ELSE IF ( GT_32(hStereoDft->sg_mean_fx , (Word32)0x4CCCCCCD) || LT_32(hStereoDft->sg_mean_fx , (Word32)(0xB3333333)) )
+ {
+ return MAX_16;
+ }
+
+ return 0;
+}
+#endif
\ No newline at end of file
diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c
index c08b3b9d33ff357aaeebbc2f4fa29937c5e0e4b4..e66192a6afc722ecb1ec75e949e9cf7c9c5f1b22 100644
--- a/lib_dec/ivas_stereo_switching_dec.c
+++ b/lib_dec/ivas_stereo_switching_dec.c
@@ -1520,6 +1520,361 @@ void synchro_synthesis(
return;
}
+#ifdef IVAS_FLOAT_FIXED
+void synchro_synthesis_fx(
+ const Word32 ivas_total_brate, /* i : IVAS total bitrate */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *output[CPE_CHANNELS], /* i/o: output synthesis signal */
+ const Word16 output_frame, /* i : Number of samples */
+ const Word16 sba_dirac_stereo_flag /* i : signal stereo output for SBA DirAC */
+)
+{
+ Word16 n, delay_comp_TD, delay_comp_DFT;
+ Word32 output_Fs;
+ Decoder_State **sts;
+ Word16 i, delay_cldfb, dft32ms_ovl;
+ Word32 *p_output_mem[CPE_CHANNELS];
+ Word32 tmp_out[CPE_CHANNELS][NS2SA( 48000, DELAY_CLDFB_NS )];
+ Word32 tmp_out_TD[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+ Word32 tmp_out_TD2[CPE_CHANNELS][STEREO_DFT32MS_OVL_MAX];
+ Word16 use_cldfb_for_last_dft;
+ Word16 dft_mono_brate_switch;
+ Word16 delay_diff;
+ Word32 tmpF;
+ Word16 nChannels;
+
+ sts = hCPE->hCoreCoder;
+ output_Fs = sts[0]->output_Fs;
+
+ use_cldfb_for_last_dft = 0;
+ if ( ( hCPE->element_mode != IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->last_element_brate <= IVAS_24k4 ) /* note: this is to mimic the DFT stereo condition "hCPE->hStereoDft->hConfig->res_cod_mode == 0" in last frame */
+ || ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) )
+ {
+ use_cldfb_for_last_dft = 1;
+ }
+
+ dft_mono_brate_switch = 0;
+ if ( hCPE->element_mode == IVAS_CPE_DFT && ( hCPE->last_element_mode == IVAS_CPE_DFT || hCPE->last_element_mode == IVAS_CPE_MDCT ) && hCPE->nchan_out == 1 && hCPE->element_brate != hCPE->last_element_brate )
+ {
+ if ( hCPE->last_element_brate >= IVAS_32k && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF )
+ {
+ dft_mono_brate_switch = -1; /* switch from residual coding mode or MDCT Stereo */
+ }
+ else if ( hCPE->last_element_brate <= IVAS_24k4 && hCPE->hStereoDft->hConfig->res_cod_mode > STEREO_DFT_RES_COD_OFF )
+ {
+ dft_mono_brate_switch = 1; /* switch to residual coding mode*/
+ }
+ }
+
+ if ( use_cldfb_for_last_dft )
+ {
+ if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->last_element_mode == IVAS_CPE_TD && ( ivas_total_brate > IVAS_SID_5k2 || hCPE->nchan_out == 2 ) )
+ {
+ stereo_tca_scale_R_channel( hCPE, output[0], output_frame );
+ }
+ }
+
+ /* set delays */
+ delay_comp_DFT = NS2SA( output_Fs, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS );
+ delay_comp_TD = NS2SA( output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
+ delay_diff = delay_comp_TD - delay_comp_DFT;
+
+ dft32ms_ovl = (int16_t) ( ( STEREO_DFT32MS_OVL_MAX * output_Fs ) / 48000 );
+ delay_cldfb = NS2SA( output_Fs, DELAY_CLDFB_NS );
+
+ /* initialize pointers */
+ if ( hCPE->element_mode >= IVAS_CPE_DFT && hCPE->output_mem[0] != NULL )
+ {
+ for ( n = 0; n < CPE_CHANNELS; n++ )
+ {
+ p_output_mem[n] = hCPE->output_mem[n];
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * DFT stereo synchro
+ *----------------------------------------------------------------*/
+
+ if ( hCPE->element_mode == IVAS_CPE_DFT || sba_dirac_stereo_flag )
+ {
+ /* handling of bitrate switching from residual (using DFT) to non-residual mode (using CLDFB) for mono output - as in DFT->TD switching */
+ if ( dft_mono_brate_switch == -1 )
+ {
+ for ( i = delay_comp_DFT; i < delay_comp_TD; i++ )
+ {
+ sts[0]->prev_synth_buffer[i] = p_output_mem[0][i - delay_comp_DFT];
+ }
+
+ for ( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out[0][i - delay_comp_TD] = p_output_mem[0][i - delay_comp_DFT];
+ }
+ }
+
+ if ( hCPE->nchan_out == 1 && hCPE->last_element_mode == IVAS_CPE_MDCT )
+ {
+ v_add( sts[0]->prev_synth_buffer, sts[1]->prev_synth_buffer, sts[0]->prev_synth_buffer, delay_comp_DFT );
+ v_multc( sts[0]->prev_synth_buffer, INV_SQRT_2, sts[0]->prev_synth_buffer, delay_comp_DFT );
+ }
+
+ if ( use_cldfb_for_last_dft )
+ {
+ /* delay CLDFB-based mono output (<= 24.4 kbps) to be aligned with DFT-based mono output (32 kbps), needed to avoid discontinuities with TCX-LTP. */
+ mvr2r( sts[0]->prev_synth_buffer + delay_comp_DFT, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_float, delay_diff );
+ delay_signal_float( output[0], output_frame, hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_float, delay_diff );
+ }
+
+ if ( hCPE->element_mode != IVAS_CPE_MDCT )
+ {
+ ivas_post_proc( NULL, hCPE, 0, output[0], output, output_frame, sba_dirac_stereo_flag );
+ }
+
+ /* zero padding in order to synchronize the upmixed DFT stereo synthesis with the TD/MDCT stereo synthesis */
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ if ( sba_dirac_stereo_flag )
+ {
+ delay_signal_float( output[n], output_frame, hCPE->prev_synth[n], delay_comp_DFT );
+ }
+ else
+ {
+ delay_signal_float( output[n], output_frame, sts[n]->prev_synth_buffer, delay_comp_DFT );
+ }
+ }
+
+ if ( use_cldfb_for_last_dft )
+ {
+ mvr2r( hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_float, sts[0]->prev_synth_buffer + delay_comp_DFT, delay_diff );
+ }
+
+ /* handling of TD->DFT switching */
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ if ( ( hCPE->last_element_mode != IVAS_CPE_DFT && !sba_dirac_stereo_flag && dft_mono_brate_switch != -1 ) || dft_mono_brate_switch == 1 )
+ {
+ Word16 *pPrev_synth;
+ Word16 inv_fade_len = 1.f / delay_diff;
+
+ /* cross-fading between TD synchro memory and the DFT output */
+ if ( sba_dirac_stereo_flag )
+ {
+ pPrev_synth = hCPE->prev_synth_fx[n];
+ }
+ else
+ {
+ pPrev_synth = sts[n]->prev_synth_buffer;
+ }
+
+ if ( hCPE->last_element_mode != IVAS_CPE_MDCT )
+ {
+ for ( i = delay_comp_DFT; i < delay_comp_TD; i++ )
+ {
+ output[n][i] = ( pPrev_synth[i] * ( delay_comp_TD - i ) + output[n][i] * ( i - delay_comp_DFT ) ) * inv_fade_len;
+ }
+ }
+ }
+ else if ( dft_mono_brate_switch == -1 )
+ {
+ float inv_fade_len_1 = 1.0f / (float) delay_diff;
+ float inv_fade_len_2 = 1.0f / (float) delay_cldfb;
+
+ for ( i = 0; i < delay_diff; i++ )
+ {
+ output[0][i + delay_comp_DFT] = ( output[0][i + delay_comp_DFT] * ( delay_diff - i ) + p_output_mem[0][i] * i ) * inv_fade_len_1;
+ }
+
+ for ( i = 0; i < delay_cldfb; i++ )
+ {
+ output[0][i + delay_comp_TD] = ( tmp_out[0][i] * ( delay_cldfb - i ) + output[0][i + delay_comp_TD] * i ) * inv_fade_len_2;
+ }
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * TD/MDCT stereo synchro
+ *----------------------------------------------------------------*/
+
+ if ( sba_dirac_stereo_flag )
+ {
+ return;
+ }
+
+ if ( hCPE->element_mode == IVAS_CPE_TD || hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ /* handling of DFT->TD switching */
+ if ( hCPE->last_element_mode == IVAS_CPE_DFT && !use_cldfb_for_last_dft && hCPE->output_mem[0] != NULL )
+ {
+ /* use redressed DFT stereo OLA part to reconstruct the TD stereo synchro memory */
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ for ( i = delay_comp_DFT; i < delay_comp_TD; i++ )
+ {
+ sts[n]->prev_synth_buffer[i] = p_output_mem[n][i - delay_comp_DFT];
+ }
+
+ for ( i = delay_comp_TD; i < delay_comp_TD + delay_cldfb; i++ )
+ {
+ tmp_out[n][i - delay_comp_TD] = p_output_mem[n][i - delay_comp_DFT];
+ }
+ }
+ }
+
+ /* if previous frame had only one channel copy buffers to other channel */
+ if ( hCPE->nchan_out == 1 && hCPE->element_mode == IVAS_CPE_MDCT && hCPE->last_element_mode == IVAS_CPE_DFT )
+ {
+ mvr2r( sts[0]->prev_synth_buffer, sts[1]->prev_synth_buffer, delay_comp_TD );
+ mvr2r( tmp_out[0], tmp_out[1], delay_cldfb );
+ mvr2r( p_output_mem[0], p_output_mem[1], delay_diff );
+ }
+
+ /*----------------------------------------------------------------*
+ * update DFT synthesis overlap memory @output_Fs; needed for TD->DFT stereo switching
+ *----------------------------------------------------------------*/
+
+ /* resample LB synthesis to output_Fs */
+ if ( hCPE->element_mode != IVAS_CPE_MDCT && !use_cldfb_for_last_dft )
+ {
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ if ( sts[n]->core == ACELP_CORE )
+ {
+ lerp_flt( hCPE->input_mem_LB[n], tmp_out_TD[n], dft32ms_ovl, NS2SA( sts[n]->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) );
+ }
+ else /* TCX/HQ core */
+ {
+ lerp_flt( hCPE->input_mem_LB[n], tmp_out_TD[n], dft32ms_ovl, NS2SA( sts[n]->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) );
+
+ /* use TCX synchro memory (perfect signal is available) */
+ for ( i = delay_diff; i < dft32ms_ovl; i++ )
+ {
+ tmp_out_TD[n][i] = sts[n]->delay_buf_out[i - delay_diff];
+ }
+ }
+ }
+
+ if ( hCPE->nchan_out == CPE_CHANNELS )
+ {
+ /* upmix the resampled LB / the TCX synchro memory */
+ tdm_upmix_plain( tmp_out_TD2[0], tmp_out_TD2[1], tmp_out_TD[0], tmp_out_TD[1], tdm_ratio_tabl[hCPE->hStereoTD->tdm_last_ratio_idx], tdm_den_ratio_tabl[hCPE->hStereoTD->tdm_last_ratio_idx], 0, dft32ms_ovl, 1 );
+ }
+ else
+ {
+ mvr2r( tmp_out_TD[0], tmp_out_TD2[0], dft32ms_ovl );
+ }
+
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ if ( sts[0]->core == ACELP_CORE ) /* ACELP core in primary channel */
+ {
+ tmpF = 1.0f / (float) delay_diff;
+
+ /* cross-fading between regular output synthesis and lerp_flt() resampled synthesis in 3.125 - 1.25 ms OLA part */
+ for ( i = 0; i < delay_diff; i++ )
+ {
+ p_output_mem[n][i] = ( output[n][output_frame - dft32ms_ovl + delay_cldfb + i] * ( delay_diff - i ) + tmp_out_TD2[n][i] * i ) * tmpF;
+ }
+ }
+ else /* TCX core */
+ {
+ /* reconstruct the 3.125 - 1.25 ms OLA part */
+ for ( i = 0; i < delay_diff; i++ )
+ {
+ p_output_mem[n][i] = output[n][output_frame - dft32ms_ovl + delay_cldfb + i];
+ }
+ }
+
+ /* reconstruct the last 1.25 ms part of OLA window */
+ for ( i = delay_diff; i < dft32ms_ovl; i++ )
+ {
+ p_output_mem[n][i] = tmp_out_TD2[n][i];
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * zero padding TD/MDCT synthesis in order to synchronize
+ * the upmixed TD/MDCT stereo synthesis with the DFT stereo synthesis
+ *----------------------------------------------------------------*/
+
+ if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->stereo_switching_counter == 0 && hCPE->nchan_out == 1 && hCPE->last_element_brate <= IVAS_24k4 )
+ {
+ float step;
+ tmpF = 1.0f;
+ step = 0.5f / delay_comp_TD;
+
+ /* for the first switching frame from DFT to TD, downmix memory too */
+ for ( n = 0; n < delay_comp_TD; n++ )
+ {
+ sts[0]->prev_synth_buffer[n] = ( sts[0]->prev_synth_buffer[n] ) * tmpF;
+ tmpF -= step;
+ }
+ }
+
+ if ( hCPE->element_mode == IVAS_CPE_MDCT && hCPE->nchan_out == 1 && !is_DTXrate( hCPE->element_brate ) && is_DTXrate( hCPE->last_element_brate ) )
+ {
+ mvr2r( sts[0]->prev_synth_buffer, sts[1]->prev_synth_buffer, delay_comp_TD );
+ }
+
+ nChannels = ( hCPE->element_mode == IVAS_CPE_MDCT ) ? 2 : hCPE->nchan_out;
+ for ( n = 0; n < nChannels; n++ )
+ {
+ if ( hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ mvr2r( sts[n]->prev_synth_buffer + delay_comp_DFT, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float, delay_diff );
+ delay_signal_float( output[n], output_frame, hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float, delay_diff );
+ ivas_post_proc( NULL, hCPE, n, output[n], output, output_frame, 0 );
+ delay_signal_float( output[n], output_frame, sts[n]->prev_synth_buffer, delay_comp_DFT );
+ mvr2r( hCPE->hCoreCoder[n]->hTcxDec->FBTCXdelayBuf_float, sts[n]->prev_synth_buffer + delay_comp_DFT, delay_diff );
+ }
+ else
+ {
+ delay_signal_float( output[n], output_frame, sts[n]->prev_synth_buffer, delay_comp_TD );
+ }
+ }
+
+ /* handling of DFT->TD switching */
+ if ( hCPE->last_element_mode == IVAS_CPE_DFT && !use_cldfb_for_last_dft )
+ {
+ if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->hStereoCng->prev_sid_nodata )
+ {
+ for ( n = 0; n < hCPE->nchan_out; n++ )
+ {
+ tmpF = 1.0f / (float) delay_cldfb;
+
+ for ( i = 0; i < delay_cldfb; i++ )
+ {
+ tmp_out[n][i] = tmp_out[n][i] * ( delay_cldfb - i ) * tmpF;
+ }
+ }
+ }
+
+ /* cross-fading between DFT OLA memory and TD output */
+ for ( n = 0; n < nChannels; n++ )
+ {
+ if ( hCPE->element_mode == IVAS_CPE_MDCT )
+ {
+ tmpF = 1.0f / (float) delay_diff;
+
+ for ( i = 0; i < delay_diff; i++ )
+ {
+ output[n][i + delay_comp_DFT] = ( output[n][i + delay_comp_DFT] * ( delay_diff - i ) + p_output_mem[n][i] * i ) * tmpF;
+ }
+ }
+
+ tmpF = 1.0f / (float) delay_cldfb;
+
+ for ( i = 0; i < delay_cldfb; i++ )
+ {
+ output[n][i + delay_comp_TD] = ( tmp_out[n][i] * ( delay_cldfb - i ) + output[n][i + delay_comp_TD] * i ) * tmpF;
+ }
+ }
+ }
+ }
+
+ return;
+}
+#endif
/*-------------------------------------------------------------------*
* Function stereo_switching_dec()
diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h
index 90e573273eeeadf2bcbb13ae4686ec7346646abf..849050de56348807855661dd81c244b5929254d9 100644
--- a/lib_dec/stat_dec.h
+++ b/lib_dec/stat_dec.h
@@ -198,6 +198,15 @@ typedef struct
int16_t msPeriodogBufPtr;
+#ifdef IVAS_FLOAT_FIXED
+ Word32 smoothed_psd_fx[L_FRAME16k];
+ Word16 cna_g_state_fx[STEREO_DFT_BAND_MAX]; /* stereo CNA - side gains from the last inactive frame */
+ Word16 cna_cm_fx[STEREO_DFT_BAND_MAX]; /* stereo CNA - coherence from the last inactive frame */
+ Word16 cna_act_fact_fx; /* stereo CNA - long-term signal activity factor (0-1) */
+ Word16 cna_rescale_fact_fx;
+ Word16 q_smoothed_psd;
+#endif
+
} FD_CNG_DEC, *HANDLE_FD_CNG_DEC;
/*---------------------------------------------------------------*
diff --git a/lib_dec/updt_dec_fx.c b/lib_dec/updt_dec_fx.c
index 28baf92434fbcd085f2c55456a4dd12564d5427d..80c72b57be0bbc3ca0bb6dbaca511a9ab3a6653e 100644
--- a/lib_dec/updt_dec_fx.c
+++ b/lib_dec/updt_dec_fx.c
@@ -742,6 +742,358 @@ void updt_dec_common_fx(
}
+#ifdef IVAS_FLOAT_FIXED
+static void ivas_updt_bw_switching_fx(
+ Decoder_State *st_fx, /* i/o: decoder state structure */
+ const Word32 *synth, /* i : float synthesis signal */
+ const Word16 Qpost
+)
+{
+ test();
+ IF(st_fx->output_Fs == 32000 && st_fx->bwidth == SWB)
+ {
+#ifdef BASOP_NOGLOB
+ st_fx->tilt_swb_fx = round_fx_sat(L_shl_sat(ivas_calc_tilt_bwe_fx(synth, Qpost, L_FRAME32k), 3));
+#else
+ st_fx->tilt_swb_fx = round_fx(L_shl(calc_tilt_bwe_fx(synth, Qpost, L_FRAME32k), 3));
+#endif
+ }
+
+ st_fx->prev_enerLH_fx = st_fx->enerLH_fx;
+ move32();
+ st_fx->prev_enerLL_fx = st_fx->enerLL_fx;
+ move32();
+ st_fx->last_bwidth = st_fx->bwidth;
+ move32();
+
+ IF( EQ_16(st_fx->core, ACELP_CORE))
+ {
+ st_fx->last_inner_frame = L_FRAME32k;
+ move16();
+ test();
+ IF( EQ_16(st_fx->bwidth, WB) && EQ_16(st_fx->bws_cnt_fx, 0))
+ {
+ st_fx->last_inner_frame = L_FRAME16k;
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ IF( !(GE_16(st_fx->last_inner_frame, L_FRAME16k)&&LE_16(inner_frame_tbl[st_fx->bwidth],L_FRAME16k)&&st_fx->bws_cnt_fx>0&<_16(st_fx->bws_cnt_fx,N_WS2N_FRAMES)))
+ {
+ st_fx->last_inner_frame = inner_frame_tbl[st_fx->bwidth];
+ move16();
+ }
+ }
+ st_fx->prev_bws_cnt_fx = st_fx->bws_cnt_fx;
+ move16();
+ return;
+}
+
+void ivas_updt_dec_common_fx(
+ Decoder_State *st_fx, /* i/o: decoder state structure */
+ Word16 hq_core_type_fx, /* i : HQ core type */
+ const Word16 concealWholeFrameTmp, /* i : concealWholeFrameTmp flag */
+ const Word32 *synth, /* i : decoded synthesis */
+ const Word16 Qpostd /* i : Synthesis Q value */
+
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+
+ TCX_DEC_HANDLE hTcxDec;
+ hTcxDec = st_fx->hTcxDec;
+
+ st_fx->last_codec_mode = st_fx->codec_mode;
+ move16();
+ st_fx->last_extl = st_fx->extl;
+ move16();
+ st_fx->last_L_frame = st_fx->L_frame;
+ move16();
+
+ st_fx->prev_old_bfi_fx = st_fx->prev_bfi;
+ st_fx->prev_bfi = st_fx->bfi;
+ move16();
+ IF (NE_16(st_fx->core, AMR_WB_CORE))
+ {
+ st_fx->old_bfi_cnt_fx = st_fx->nbLostCmpt;
+ move16();
+ }
+ move16();
+ st_fx->last_con_tcx = st_fx->con_tcx;
+ move16();
+ st_fx->con_tcx = 0;
+
+ move16();
+ IF(st_fx->hHQ_nbfec != NULL)
+ {
+ st_fx->hHQ_nbfec->prev_last_core_fx = st_fx->last_core;
+ }
+ IF(st_fx->hTcxDec != NULL)
+ {
+ hTcxDec->tcxConceal_recalc_exc = 0;
+ move16();
+ }
+ test();test();
+ IF( (GE_16(st_fx->rf_frame_type,RF_TCXFD) && LE_16(st_fx->rf_frame_type,RF_TCXTD2) && st_fx->use_partial_copy && st_fx->bfi) || !st_fx->bfi)
+ {
+ test();test();
+ test(); test();
+ IF( st_fx->bfi && (LE_16(st_fx->last_good_fx, UNVOICED_TRANSITION)) && (GT_16(st_fx->clas_dec,UNVOICED_TRANSITION)) && st_fx->last_con_tcx && st_fx->hTcxDec != NULL)
+ {
+ hTcxDec->tcxConceal_recalc_exc = 1;
+ move16();
+ }
+ st_fx->last_good_fx = st_fx->clas_dec;
+ move16();
+ }
+ IF (st_fx->use_partial_copy)
+ {
+ st_fx->prev_rf_frame_type = st_fx->rf_frame_type;
+ }
+ ELSE
+ {
+ st_fx->prev_rf_frame_type = INACTIVE;
+ }
+
+ IF (EQ_16(st_fx->m_frame_type, ACTIVE_FRAME) && (st_fx->bfi!=1 || st_fx->use_partial_copy!=0))
+ {
+ st_fx->rf_flag_last = st_fx->rf_flag;
+ }
+
+ IF( EQ_16(st_fx->codec_mode,MODE1))
+ {
+ test();
+ IF( !st_fx->bfi && (st_fx->core_brate > SID_2k40 || (GT_32(st_fx->core_brate, SID_1k75) && EQ_16(st_fx->core, AMR_WB_CORE))))
+ {
+ move16();
+ st_fx->last_active_brate = st_fx->total_brate;
+ }
+
+ move16();
+ move16();
+ st_fx->last_core = st_fx->core;
+ if (st_fx->hHQ_core != NULL)
+ {
+ st_fx->hHQ_core->last_hq_core_type_fx = hq_core_type_fx;
+ }
+ }
+ ELSE IF( EQ_16(st_fx->codec_mode,MODE2))
+ {
+ test();
+ IF ((!st_fx->bfi) && (st_fx->last_is_cng==0))
+ {
+ move16();
+ st_fx->last_active_brate = st_fx->total_brate;
+ }
+ /* INFO: moved from update_decoder_LPD_cng() */
+ IF (NE_16(st_fx->m_frame_type,ACTIVE_FRAME))
+ {
+ move16();
+ st_fx->last_is_cng = 1;
+ }
+
+
+ IF (!st_fx->bfi)
+ {
+ st_fx->last_core = st_fx->core;
+ }
+ move16();
+ move16();
+ st_fx->last_core_bfi = st_fx->core; /* also required for clean channel decoding */
+ }
+ move16();
+ st_fx->last_core_brate = st_fx->core_brate;
+
+ /* save synthesis for core switching */
+ test();
+ IF (EQ_16(st_fx->element_mode, EVS_MONO) && NE_16(st_fx->core, AMR_WB_CORE))
+ {
+ Copy_Scale_sig_32_16(synth + NS2SA_fx2(st_fx->output_Fs, ACELP_LOOK_NS + DELAY_BWE_TOTAL_NS), st_fx->old_synth_sw_fx, NS2SA_fx2(st_fx->output_Fs, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS), st_fx->hHQ_core->Q_old_postdec);
+ }
+ test();
+ test();
+ test();
+#ifdef IVAS_CODE
+ /* Store long-term estimates of stab_fac and log energy diff to estimate env_stab in case of core switch ACELP/TCX->HQ */
+ if (st->element_mode != EVS_MONO)
+ {
+ output_frame = NS2SA(st->output_Fs, FRAME_SIZE_NS);
+ log_energy = log2f((sum2_f(synth, output_frame) / output_frame) + 1.0f);
+ log_energy_diff = fabsf(st->log_energy_old - log_energy);
+ st->log_energy_old = log_energy;
+ st->log_energy_diff_lt = ENV_SMOOTH_FAC * log_energy_diff + (1.0f - ENV_SMOOTH_FAC) * st->log_energy_diff_lt;
+ if (st->core == HQ_CORE)
+ {
+ st->stab_fac = min(1, (STAB_FAC_EST1 + (STAB_FAC_EST2 * st->hHQ_core->mem_env_delta) + (STAB_FAC_EST3 * st->log_energy_diff_lt)));
+ st->stab_fac = max(0, st->stab_fac);
+ }
+ st->stab_fac_smooth_lt = ENV_SMOOTH_FAC * st->stab_fac + (1.0f - ENV_SMOOTH_FAC) * st->stab_fac_smooth_lt;
+ }
+#endif
+ IF( ((LE_32(st_fx->core_brate,SID_2k40))&&EQ_16(st_fx->cng_type,FD_CNG))
+ || (st_fx->tcxonly && EQ_16(st_fx->codec_mode,MODE2))
+ )
+
+ {
+ /* reset LP memories */
+ set16_fx( st_fx->mem_MA_fx,0, M );
+ IF( EQ_32(st_fx->sr_core,INT_FS_16k))
+ {
+ Copy( GEWB2_Ave_fx, st_fx->mem_AR_fx, M );
+ }
+ ELSE
+ {
+ Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M );
+ }
+ }
+ IF(EQ_16(st_fx->codec_mode, MODE2))
+ {
+ test();
+ IF(EQ_16(st_fx->use_partial_copy, 1) && EQ_16(st_fx->rf_frame_type, RF_NELP))
+ {
+ st_fx->last_nelp_mode_dec_fx = 1;
+ }
+ ELSE
+ {
+ st_fx->last_nelp_mode_dec_fx = 0;
+ }
+ }
+
+ st_fx->prev_use_partial_copy = st_fx->use_partial_copy;
+ move16();
+
+ st_fx->prev_tilt_code_dec_fx = 0;
+ move16();
+
+ st_fx->prev_Q_exc = st_fx->Q_exc;
+ move16();
+
+ L_tmp = L_mult(st_fx->tilt_code_dec_fx[0], 4096);
+ FOR(i = 1; i < NB_SUBFR; i++)
+ {
+ L_tmp = L_mac(L_tmp, st_fx->tilt_code_dec_fx[i], 4096);
+ }
+ st_fx->prev_tilt_code_dec_fx = round_fx(L_tmp);
+
+ IF (EQ_16(st_fx->core, HQ_CORE))
+ {
+ st_fx->prev_coder_type_fx = GENERIC;
+ }
+ ELSE IF (NE_16(st_fx->core, AMR_WB_CORE) )
+ {
+ st_fx->prev_coder_type_fx = st_fx->coder_type_fx;
+ }
+
+ test();
+ IF((GT_32(st_fx->core_brate, SID_2k40) || (GT_32(st_fx->core_brate, SID_1k75) && EQ_16(st_fx->core, AMR_WB_CORE))) && EQ_16(st_fx->first_CNG, 1) && st_fx->hTdCngDec != NULL)
+ {
+ IF (GE_16(st_fx->hTdCngDec->act_cnt_fx, BUF_DEC_RATE))
+ {
+ st_fx->hTdCngDec->act_cnt_fx = 0;
+ move16();
+ }
+
+ st_fx->hTdCngDec->act_cnt_fx = add(st_fx->hTdCngDec->act_cnt_fx, 1);
+
+ test();
+ IF ((EQ_16(st_fx->hTdCngDec->act_cnt_fx, BUF_DEC_RATE)) && (st_fx->hTdCngDec->ho_hist_size_fx > 0))
+ {
+ st_fx->hTdCngDec->ho_hist_size_fx = sub(st_fx->hTdCngDec->ho_hist_size_fx, 1);
+ }
+
+ st_fx->hTdCngDec->act_cnt2_fx = add(st_fx->hTdCngDec->act_cnt2_fx, 1);
+ IF (GE_16(st_fx->hTdCngDec->act_cnt2_fx, MIN_ACT_CNG_UPD))
+ {
+ st_fx->hTdCngDec->act_cnt2_fx = MIN_ACT_CNG_UPD;
+ move16();
+ }
+ }
+
+ test();
+ test();
+ if (LE_32(st_fx->core_brate, SID_2k40) && st_fx->first_CNG == 0 && (EQ_16(st_fx->cng_type, LP_CNG) || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT)))
+ {
+ st_fx->first_CNG = 1;
+ move16();
+ }
+
+ /* update bandwidth switching parameters */
+ test(); test();
+ st_fx->last_flag_cna = st_fx->flag_cna;
+ move16();
+ if (st_fx->hFdCngDec != NULL)
+ {
+ st_fx->hFdCngDec->hFdCngCom->frame_type_previous = st_fx->m_frame_type;
+ move16();
+ }
+
+ if (GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ st_fx->m_old_frame_type = st_fx->m_frame_type;
+ }
+
+ /* update bandwidth switching parameters */
+ IF ( EQ_16(st_fx->core, AMR_WB_CORE))
+ {
+ st_fx->last_bwidth = WB;
+
+ st_fx->prev_bws_cnt_fx = 0;
+ st_fx->bws_cnt_fx = 0;
+ st_fx->bws_cnt1_fx = 0;
+ move16();move16();move16();move16();
+
+ }
+ ELSE IF(EQ_16(st_fx->codec_mode, MODE1) && ((GT_32(st_fx->core_brate, SID_2k40)) || (EQ_16(st_fx->element_mode, EVS_MONO))))
+ {
+ ivas_updt_bw_switching_fx(st_fx, synth, Qpostd);
+ }
+ ELSE
+ {
+ st_fx->last_bwidth = st_fx->bwidth;
+ st_fx->prev_bws_cnt_fx = st_fx->bws_cnt_fx;
+ move32();
+ move16();
+ }
+
+ /* synchronisation of CNG seeds*/
+ test();
+ test();
+ IF(st_fx->hTdCngDec != NULL && (st_fx->bfi || (NE_32(st_fx->core_brate, FRAME_NO_DATA) && NE_32(st_fx->core_brate, SID_2k40))) && NE_16(st_fx->core, AMR_WB_CORE))
+ {
+ Random(&(st_fx->hTdCngDec->cng_seed_fx));
+ Random(&(st_fx->hTdCngDec->cng_ener_seed_fx));
+ }
+
+ test();test();test();
+ IF(st_fx->hTcxDec != NULL && st_fx->enablePlcWaveadjust && !concealWholeFrameTmp && NE_16(st_fx->core, AMR_WB_CORE))
+ {
+ /* update the parameters used in waveform adjustment */
+ concealment_update2_x(synth, &st_fx->plcInfo, hTcxDec->L_frameTCX);
+ }
+
+ st_fx->last_total_brate_ber = st_fx->total_brate;
+ move32();
+ if (st_fx->bfi == 0)
+ {
+ st_fx->last_total_brate = st_fx->total_brate;
+ st_fx->last_bits_frame_nominal = st_fx->bits_frame_nominal;
+ move32();
+ }
+ st_fx->last_low_rate_mode = st_fx->low_rate_mode; move16();
+ if (LT_16(st_fx->ini_frame, MAX_FRAME_COUNTER))
+ {
+ st_fx->ini_frame = add(st_fx->ini_frame,1);
+ }
+
+ return;
+}
+#endif
+
/*-------------------------------------------------------------------*
* update_decoder_LPD_cng()
*